Skip to content

Commit 3ed913e

Browse files
committed
stuff
1 parent 517e497 commit 3ed913e

12 files changed

Lines changed: 259 additions & 161 deletions

File tree

floonder/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
'corsheaders',
4444
'rest_framework',
4545
'users',
46+
'news',
4647
'django_filters',
4748
'django_extensions',
4849
'spatial_data_services',

floonder/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from auth.urls import urlpatterns as auth_urlpatterns, router as auth_router
66
from users.urls import urlpatterns_cms as users_router_cms, urlpatterns_public as users_router_public
77
from spatial_data_services.urls import urlpatterns as gis_urlpatterns
8+
from news.urls import urlpatterns as news_urlpatterns
9+
from news.urls import urlpatterns_public as news_urlpatterns_public
810

911
urlpatterns = [
1012
path('api', include([
@@ -14,10 +16,12 @@
1416
])),
1517
path('/cms', include([
1618
path('/users', include(users_router_cms)),
19+
path('/news', include(news_urlpatterns)),
1720
])),
1821
path('/public', include([
1922
path('/users', include(users_router_public)),
2023
path('/gis', include(gis_urlpatterns)),
24+
path('/news', include(news_urlpatterns_public)),
2125
])),
2226
])),
2327
]

news/migrations/0001_initial.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Generated by Django 5.0.3 on 2025-05-25 02:50
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
initial = True
9+
10+
dependencies = [
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='News',
16+
fields=[
17+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('title', models.CharField(max_length=200)),
19+
('content', models.TextField()),
20+
('author', models.CharField(max_length=100)),
21+
('published_date', models.DateTimeField(auto_now_add=True)),
22+
],
23+
options={
24+
'verbose_name': 'News',
25+
'verbose_name_plural': 'News Articles',
26+
'ordering': ['-published_date'],
27+
},
28+
),
29+
]

news/models.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
1-
# Create your models here.
1+
from django.db import models
2+
3+
4+
class News(models.Model):
5+
title = models.CharField(max_length=200)
6+
content = models.TextField()
7+
author = models.CharField(max_length=100)
8+
published_date = models.DateTimeField(auto_now_add=True)
9+
10+
def __str__(self):
11+
return self.title
12+
13+
class Meta:
14+
ordering = ['-published_date']
15+
verbose_name = 'News'
16+
verbose_name_plural = 'News Articles'

news/serializers/__init__.py

Whitespace-only changes.

news/serializers/serializers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from rest_framework import serializers
2+
from ..models import News
3+
4+
class NewsSerializer(serializers.ModelSerializer):
5+
class Meta:
6+
model = News
7+
fields = ['id', 'title', 'content', 'author', 'published_date']

news/urls.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.urls import path
2+
3+
from .views import NewsViewSet, PublishNewsViewSet
4+
5+
urlpatterns = [
6+
path('', NewsViewSet.as_view({'get': 'list', 'post': 'create'}), name='news-list-create'),
7+
]
8+
9+
urlpatterns_public = [
10+
path('', PublishNewsViewSet.as_view({'get': 'list'}), name='news-public-list'),
11+
]

news/views.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,53 @@
1-
# Create your views here.
1+
from rest_framework import viewsets
2+
from rest_framework.permissions import AllowAny
3+
from rest_framework.response import Response
4+
from rest_framework_simplejwt.authentication import JWTAuthentication
5+
6+
from auth.auth import IsAdmin, IsSuperUser
7+
from news.models import News
8+
from news.serializers.serializers import NewsSerializer
9+
10+
11+
class NewsViewSet(viewsets.ModelViewSet):
12+
queryset = News.objects.all()
13+
serializer_class = NewsSerializer
14+
authentication_classes = [JWTAuthentication]
15+
permission_classes = [IsSuperUser]
16+
17+
def list(self, request, *args, **kwargs):
18+
if request.query_params.get('id'):
19+
news_id = request.query_params.get('id')
20+
try:
21+
news_item = News.objects.get(id=news_id)
22+
except News.DoesNotExist:
23+
return Response({'error': 'News item not found'}, status=404)
24+
25+
serializer = self.get_serializer(news_item)
26+
return Response(serializer.data)
27+
28+
queryset = self.get_queryset()
29+
serializer = self.get_serializer(queryset, many=True)
30+
31+
return Response(serializer.data)
32+
33+
class PublishNewsViewSet(viewsets.ModelViewSet):
34+
queryset = News.objects.all()
35+
serializer_class = NewsSerializer
36+
authentication_classes = [JWTAuthentication]
37+
permission_classes = [AllowAny]
38+
39+
def list(self, request, *args, **kwargs):
40+
if request.query_params.get('id'):
41+
news_id = request.query_params.get('id')
42+
try:
43+
news_item = News.objects.get(id=news_id, published=True)
44+
except News.DoesNotExist:
45+
return Response({'error': 'News item not found'}, status=404)
46+
47+
serializer = self.get_serializer(news_item)
48+
return Response(serializer.data)
49+
50+
queryset = self.get_queryset()
51+
serializer = self.get_serializer(queryset, many=True)
52+
53+
return Response(serializer.data)

spatial_data_services/migrations/0001_initial.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import django.contrib.gis.db.models.fields
44
from django.db import migrations, models
5-
5+
from django.contrib.postgres.operations import CreateExtension
66

77
class Migration(migrations.Migration):
88

@@ -12,6 +12,7 @@ class Migration(migrations.Migration):
1212
]
1313

1414
operations = [
15+
CreateExtension('postgis_raster'),
1516
migrations.CreateModel(
1617
name='AdministrationRegion',
1718
fields=[

spatial_data_services/tests.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,52 @@
11
from django.test import TestCase
2+
from django.contrib.gis.geos import Point
23

3-
# Create your tests here.
4+
from .models import Kosan
5+
6+
7+
class KosanModelTests(TestCase):
8+
def setUp(self):
9+
# Create dummy object
10+
self.kosan = Kosan.objects.create(
11+
nama="Kosan Mawar",
12+
alamat_lengkap="Jl. Mawar No. 12",
13+
luas_bangunan=24.5,
14+
link_lengkap_properti="https://example.com/kosan-mawar",
15+
geometry=Point(107.6191, -6.9175) # (longitude, latitude)
16+
)
17+
18+
def test_create_kosan(self):
19+
self.assertEqual(Kosan.objects.count(), 1)
20+
kosan = Kosan.objects.first()
21+
self.assertEqual(kosan.nama, "Kosan Mawar")
22+
self.assertEqual(kosan.geometry.x, 107.6191)
23+
self.assertEqual(kosan.geometry.y, -6.9175)
24+
25+
def test_read_kosan(self):
26+
kosan = Kosan.objects.get(nama="Kosan Mawar")
27+
self.assertEqual(kosan.alamat_lengkap, "Jl. Mawar No. 12")
28+
29+
def test_update_kosan(self):
30+
kosan = self.kosan
31+
kosan.nama = "Kosan Melati"
32+
kosan.luas_bangunan = 30.0
33+
kosan.save()
34+
35+
updated = Kosan.objects.get(id=kosan.id)
36+
self.assertEqual(updated.nama, "Kosan Melati")
37+
self.assertEqual(updated.luas_bangunan, 30.0)
38+
39+
def test_delete_kosan(self):
40+
kosan_id = self.kosan.id
41+
self.kosan.delete()
42+
self.assertFalse(Kosan.objects.filter(id=kosan_id).exists())
43+
44+
def test_dunder_str_with_name(self):
45+
self.assertEqual(str(self.kosan), "Kosan Mawar")
46+
47+
def test_dunder_str_without_name(self):
48+
kosan = Kosan.objects.create(
49+
nama=None,
50+
geometry=Point(107.6191, -6.9175)
51+
)
52+
self.assertEqual(str(kosan), "Kosan tanpa nama")

0 commit comments

Comments
 (0)