view and model notif and news

This commit is contained in:
Parsa Nazer
2025-05-24 22:02:16 +03:30
parent 11eab8c21b
commit 7c1c34e1e5
9 changed files with 235 additions and 2 deletions
+12 -1
View File
@@ -134,4 +134,15 @@ class SecurityBreachAttemptAdmin(ModelAdmin, ImportExportModelAdmin):
return format_html(
svg
)
)
@admin.register(NewsModel)
class NewsAdmin(ModelAdmin):
pass
@admin.register(UserNotificationModel)
class UserNotificationAdmin(ModelAdmin):
pass
@@ -0,0 +1,43 @@
# Generated by Django 5.1.2 on 2025-04-24 22:25
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0025_alter_pushsubscription_options_and_more'),
]
operations = [
migrations.CreateModel(
name='News',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('content', models.TextField()),
('image', models.ImageField(upload_to='')),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='UserNotification',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('content', models.TextField()),
('image', models.ImageField(upload_to='')),
('created_at', models.DateTimeField(auto_now_add=True)),
('is_read', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
),
]
@@ -0,0 +1,21 @@
# Generated by Django 5.1.2 on 2025-04-24 22:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0026_news_usernotification'),
]
operations = [
migrations.RenameModel(
old_name='News',
new_name='NewsModel',
),
migrations.RenameModel(
old_name='UserNotification',
new_name='UserNotificationModel',
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2025-05-24 17:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0027_rename_news_newsmodel_and_more'),
]
operations = [
migrations.AddField(
model_name='newsmodel',
name='is_read',
field=models.BooleanField(default=False),
),
]
+26
View File
@@ -207,6 +207,32 @@ class PushSubscription(models.Model):
class NotifBaseModel(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
image = models.ImageField()
created_at = models.DateTimeField(auto_now_add=True)
is_read = models.BooleanField(default=False)
class Meta:
abstract = True
def __str__(self):
return self.title
class NewsModel(NotifBaseModel):
def notif_type(self):
return 'NEWS'
class UserNotificationModel(NotifBaseModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
def notif_type(self):
return 'USER_NOTIF'
def get_location_from_ip(ip_address):
try:
response = requests.get(f"http://ip-api.com/json/{ip_address}")
+29
View File
@@ -32,3 +32,32 @@ class PushSubscriptionSerializer(serializers.ModelSerializer):
class Meta:
model = PushSubscription
fields = ('endpoint', 'keys')
class NewsSerializer(serializers.ModelSerializer):
notif_type = serializers.SerializerMethodField()
class Meta:
model = NewsModel
fields = ['title', 'content', 'image', 'created_at', 'notif_type']
def get_notif_type(self, obj):
return 'NEWS'
class UserNotifSerializer(serializers.ModelSerializer):
notif_type = serializers.SerializerMethodField()
class Meta:
model = UserNotificationModel
fields = ['title', 'content', 'image', 'created_at', 'notif_type', 'is_read']
def get_notif_type(self, obj):
return 'USER_NOTIF'
class UnifiedNotifSerializer(serializers.Serializer):
def to_representation(self, instance):
if isinstance(instance, NewsModel):
return NewsSerializer(instance).data
elif isinstance(instance, UserNotificationModel):
return UserNotifSerializer(instance).data
+1
View File
@@ -17,4 +17,5 @@ urlpatterns = [
path('unsubscribe', views.UnsubscribeView.as_view(), name='unsubscibe'),
path('attack/view/<int:pk>', views.ChangeViewAttack.as_view(), name='attack-view'),
path('logout', views.LogoutView.as_view(), name='logout'),
path('notif/list', views.NotificationListAPIView.as_view(), name='notif-list')
]
+73 -1
View File
@@ -14,6 +14,9 @@ from django.views import View
from rest_framework import serializers
from rest_framework_simplejwt.tokens import RefreshToken
from itertools import chain
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
from utils.pagination import StructurePagination
class SendOTPView(APIView):
@@ -268,4 +271,73 @@ from djoser.urls.jwt import views as djoser_jwt_views
post=extend_schema(tags=["authentication"])
)
class TokenVerifyView(djoser_jwt_views.TokenVerifyView):
pass
pass
class NotificationListAPIView(APIView):
serializer_class = UnifiedNotifSerializer
permission_classes = [IsAuthenticated]
pagination_class = StructurePagination
@extend_schema(
parameters=[
OpenApiParameter(
name="notif_type",
type=OpenApiTypes.STR,
description="NEWS OR USER_NOTIF",
required=False,
),
OpenApiParameter(
name="is_read",
type=OpenApiTypes.STR,
description="is_read filter",
required=False,
),
OpenApiParameter(
name="limit",
description="Number of results to return per page (pagination).",
required=False,
type=OpenApiTypes.INT,
),
OpenApiParameter(
name="offset",
description="The starting position of the results (pagination).",
required=False,
type=OpenApiTypes.INT,
),
],
)
def get(self, request):
notif_type = request.query_params.get('notif_type')
is_read_param = request.query_params.get('is_read')
is_read = self.str_to_bool(is_read_param)
news_qs = NewsModel.objects.all()
user_notif_qs = UserNotificationModel.objects.filter(user=request.user)
if is_read is not None:
news_qs = news_qs.filter(is_read=is_read)
user_notif_qs = user_notif_qs.filter(is_read=is_read)
if notif_type is None:
notifs = sorted(
chain(news_qs, user_notif_qs),
key=lambda n: n.created_at,
reverse=True
)
elif notif_type == 'NEWS':
notifs = news_qs
elif notif_type == 'USER_NOTIF':
notifs = user_notif_qs
else:
return Response({'detail': 'wrong notif type'}, status=status.HTTP_400_BAD_REQUEST)
paginator = self.pagination_class()
paginated_notifs = paginator.paginate_queryset(notifs, request)
serializer = self.serializer_class(paginated_notifs, many=True)
return paginator.get_paginated_response(serializer.data)
def str_to_bool(val):
return True if val and val == 'true' else False
+12
View File
@@ -221,6 +221,18 @@ UNFOLD = {
"link": reverse_lazy("admin:account_securitybreachattemptmodel_changelist"),
"badge": 'utils.admin.new_attck_count'
},
{
"title": _("اخبار"),
"icon": "newspaper",
"link": reverse_lazy("admin:account_newsmodel_changelist"),
},
{
"title": _("اطلاعیه ها"),
"icon": "notifications",
"link": reverse_lazy("admin:account_usernotificationmodel_changelist"),
},
],
},