mirror of
https://github.com/lemeow125/DRF_Template.git
synced 2025-04-28 10:41:15 +08:00
Overhauled entire project config, added notifications, email templates, optimized stripe subscriptions, redis caching, and webdriver utilities
This commit is contained in:
parent
7cbe8fd720
commit
99dfcef67b
84 changed files with 4300 additions and 867 deletions
0
backend/notifications/__init__.py
Normal file
0
backend/notifications/__init__.py
Normal file
10
backend/notifications/admin.py
Normal file
10
backend/notifications/admin.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from unfold.admin import ModelAdmin
|
||||
from django.contrib import admin
|
||||
from .models import Notification
|
||||
|
||||
|
||||
@admin.register(Notification)
|
||||
class NotificationAdmin(ModelAdmin):
|
||||
model = Notification
|
||||
search_fields = ('id', 'content')
|
||||
list_display = ['id', 'dismissed']
|
9
backend/notifications/apps.py
Normal file
9
backend/notifications/apps.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class NotificationsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'notifications'
|
||||
|
||||
def ready(self):
|
||||
import notifications.signals
|
27
backend/notifications/migrations/0001_initial.py
Normal file
27
backend/notifications/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 5.0.6 on 2024-05-10 13:56
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Notification',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('content', models.CharField(max_length=1000, null=True)),
|
||||
('timestamp', models.DateTimeField(auto_now_add=True)),
|
||||
('dismissed', models.BooleanField(default=False)),
|
||||
('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
0
backend/notifications/migrations/__init__.py
Normal file
0
backend/notifications/migrations/__init__.py
Normal file
12
backend/notifications/models.py
Normal file
12
backend/notifications/models.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class Notification(models.Model):
|
||||
recipient = models.ForeignKey(
|
||||
'accounts.CustomUser', on_delete=models.CASCADE)
|
||||
content = models.CharField(max_length=1000, null=True)
|
||||
timestamp = models.DateTimeField(auto_now_add=True, editable=False)
|
||||
dismissed = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.content
|
12
backend/notifications/serializers.py
Normal file
12
backend/notifications/serializers.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from rest_framework import serializers
|
||||
from notifications.models import Notification
|
||||
|
||||
|
||||
class NotificationSerializer(serializers.ModelSerializer):
|
||||
timestamp = serializers.DateTimeField(
|
||||
format="%m-%d-%Y %I:%M %p", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Notification
|
||||
fields = '__all__'
|
||||
read_only_fields = ('id', 'recipient', 'content', 'timestamp')
|
13
backend/notifications/signals.py
Normal file
13
backend/notifications/signals.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from django.dispatch import receiver
|
||||
from django.db.models.signals import post_save
|
||||
from notifications.models import Notification
|
||||
from django.core.cache import cache
|
||||
|
||||
# Template for running actions after user have paid for a subscription
|
||||
|
||||
|
||||
@receiver(post_save, sender=Notification)
|
||||
def clear_cache_after_notification_update(sender, instance, **kwargs):
|
||||
# Clear cache
|
||||
cache.delete('notifications')
|
||||
cache.delete(f'notifications_user:{instance.recipient.id}')
|
13
backend/notifications/tasks.py
Normal file
13
backend/notifications/tasks.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from celery import shared_task
|
||||
from django.utils import timezone
|
||||
from notifications.models import Notification
|
||||
|
||||
|
||||
@shared_task
|
||||
def cleanup_notifications():
|
||||
# Calculate the date 3 days ago
|
||||
three_days_ago = timezone.now() - timezone.timedelta(days=3)
|
||||
|
||||
# Delete notifications that are older than 3 days and dismissed
|
||||
Notification.objects.filter(
|
||||
dismissed=True, timestamp__lte=three_days_ago).delete()
|
10
backend/notifications/urls.py
Normal file
10
backend/notifications/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.urls import path, include
|
||||
from notifications.views import NotificationViewSet
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'', NotificationViewSet,
|
||||
basename="Notifications")
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
35
backend/notifications/views.py
Normal file
35
backend/notifications/views.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
from rest_framework import viewsets
|
||||
from notifications.models import Notification
|
||||
from notifications.serializers import NotificationSerializer
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
class NotificationViewSet(viewsets.ModelViewSet):
|
||||
http_method_names = ['get', 'patch', 'delete']
|
||||
serializer_class = NotificationSerializer
|
||||
queryset = Notification.objects.all()
|
||||
|
||||
def get_queryset(self):
|
||||
user = self.request.user
|
||||
key = f'notifications_user:{user.id}'
|
||||
queryset = cache.get(key)
|
||||
if not queryset:
|
||||
queryset = Notification.objects.filter(
|
||||
recipient=user).order_by('-timestamp')
|
||||
cache.set(key, queryset, 60*60)
|
||||
return queryset
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.recipient != request.user:
|
||||
raise PermissionDenied(
|
||||
"You do not have permission to update this notification.")
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.recipient != request.user:
|
||||
raise PermissionDenied(
|
||||
"You do not have permission to delete this notification.")
|
||||
return super().destroy(request, *args, **kwargs)
|
Loading…
Add table
Add a link
Reference in a new issue