mirror of
https://github.com/Hopiu/django-notifications.git
synced 2026-05-04 03:24:52 +00:00
Fix #367
This commit is contained in:
parent
14f7651c35
commit
6eb74f47c5
9 changed files with 79 additions and 22 deletions
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.11 on 2024-05-16 22:42
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("notifications", "0016_rename_notification_recipient_unread_notificatio_recipie_8bedf2_idx"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="notification",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, serialize=False, null=True),
|
||||
),
|
||||
]
|
||||
22
notifications/migrations/0018_auto_20240516_1750.py
Normal file
22
notifications/migrations/0018_auto_20240516_1750.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 4.2.11 on 2024-05-16 22:50
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def gen_uuid(apps, schema_editor):
|
||||
Notification = apps.get_model("notifications", "Notification")
|
||||
for row in Notification.objects.all():
|
||||
row.uuid = uuid.uuid4()
|
||||
row.save(update_fields=["uuid"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("notifications", "0017_remove_notification_recipient_unread_idx_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
|
||||
]
|
||||
19
notifications/migrations/0019_auto_20240516_1750.py
Normal file
19
notifications/migrations/0019_auto_20240516_1750.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.11 on 2024-05-16 22:42
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("notifications", "0018_auto_20240516_1750"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="notification",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, serialize=False, unique=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from typing import Union
|
||||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
|
|
@ -54,6 +55,7 @@ class AbstractNotification(models.Model):
|
|||
|
||||
"""
|
||||
|
||||
uuid = models.UUIDField(unique=True, default=uuid4, editable=False)
|
||||
recipient = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
|
|
@ -136,10 +138,6 @@ class AbstractNotification(models.Model):
|
|||
return _("%(actor)s %(verb)s %(action_object)s %(timesince)s ago") % ctx
|
||||
return _("%(actor)s %(verb)s %(timesince)s ago") % ctx
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
return self.id
|
||||
|
||||
def _mark_as(self, field: str, status: bool) -> None:
|
||||
if getattr(self, field, None) != status:
|
||||
setattr(self, field, status)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<div class="alert alert-block alert-{{ notice.level }}">
|
||||
<a class="close pull-right" href="{% url 'notifications:mark_as' notice.slug 'read' %}">
|
||||
<a class="close pull-right" href="{% url 'notifications:mark_as' notice.uuid 'read' %}">
|
||||
<i class="icon-close"></i>
|
||||
</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,6 @@ def test__str__():
|
|||
assert str(notification.action_object) in notification_str
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_slug():
|
||||
notification = NotificationShortFactory()
|
||||
assert notification.id == notification.slug
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"field,initial_status,method_name,expected",
|
||||
(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import override_settings
|
||||
|
|
@ -20,7 +22,8 @@ VIEW_NAME = "notifications:mark_as"
|
|||
@pytest.mark.parametrize("status", status_list + wrong_status_list + soft_delete_status_list)
|
||||
@pytest.mark.django_db
|
||||
def test_login_required(status, client):
|
||||
view_url = reverse(VIEW_NAME, args=(1, status))
|
||||
_id = uuid4()
|
||||
view_url = reverse(VIEW_NAME, args=(_id, status))
|
||||
response = client.get(view_url, follow=True)
|
||||
assert response.status_code == 200
|
||||
assert len(response.redirect_chain) == 1
|
||||
|
|
@ -31,8 +34,9 @@ def test_login_required(status, client):
|
|||
@pytest.mark.parametrize("status", status_list + soft_delete_status_list)
|
||||
@pytest.mark.django_db
|
||||
def test_notification_not_found(status, client, staff_user):
|
||||
_id = uuid4()
|
||||
client.force_login(staff_user)
|
||||
response = client.get(reverse(VIEW_NAME, args=(9999, status)))
|
||||
response = client.get(reverse(VIEW_NAME, args=(_id, status)))
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
|
|
@ -40,7 +44,8 @@ def test_notification_not_found(status, client, staff_user):
|
|||
@pytest.mark.django_db
|
||||
def test_wrong_methods(status, client, staff_user, notifications): # pylint: disable=unused-argument
|
||||
client.force_login(staff_user)
|
||||
response = client.get(reverse(VIEW_NAME, args=(1, status)))
|
||||
notification = staff_user.notifications_notification_related.first()
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, status)))
|
||||
assert response.status_code == 404
|
||||
assert response.content.decode() == f'Status "{status}" not exists.'
|
||||
|
||||
|
|
@ -69,7 +74,7 @@ def test_mark_as(
|
|||
client.force_login(staff_user)
|
||||
notification = NotificationFullFactory(recipient=staff_user, **{field: initial_status})
|
||||
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.slug, status)))
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, status)))
|
||||
assert response.status_code == 302
|
||||
notification.refresh_from_db()
|
||||
assert getattr(notification, field) == expected
|
||||
|
|
@ -81,10 +86,10 @@ def test_mark_as_active(client, staff_user, notifications): # pylint: disable=u
|
|||
notification = NotificationFullFactory(recipient=staff_user, deleted=True)
|
||||
|
||||
with pytest.raises(ImproperlyConfigured):
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.slug, "active")))
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, "active")))
|
||||
|
||||
with override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True}):
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.slug, "active")))
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, "active")))
|
||||
assert response.status_code == 302
|
||||
notification.refresh_from_db()
|
||||
assert notification.deleted is False
|
||||
|
|
@ -96,11 +101,11 @@ def test_mark_as_deleted(client, staff_user, notifications): # pylint: disable=
|
|||
notification = NotificationFullFactory(recipient=staff_user, deleted=False)
|
||||
|
||||
with override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True}):
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.slug, "deleted")))
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, "deleted")))
|
||||
assert response.status_code == 302
|
||||
notification.refresh_from_db()
|
||||
assert notification.deleted is True
|
||||
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.slug, "deleted")))
|
||||
response = client.get(reverse(VIEW_NAME, args=(notification.uuid, "deleted")))
|
||||
with pytest.raises(Notification.DoesNotExist):
|
||||
notification.refresh_from_db()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ app_name = "notifications"
|
|||
urlpatterns = [
|
||||
path("list/<str:filter_by>/", views.NotificationsList.as_view(), name="list"),
|
||||
path("mark-all-as/<str:status>/", views.NotificationsMarkAll.as_view(), name="mark_all_as"),
|
||||
path("mark/<str:slug>/as/<str:status>/", views.NotificationsMarkAs.as_view(), name="mark_as"),
|
||||
path("mark/<uuid:uuid>/as/<str:status>/", views.NotificationsMarkAs.as_view(), name="mark_as"),
|
||||
path("api/<str:filter_by>/", views.NotificationsAPI.as_view(), name="api"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ class NotificationsMarkAs(NotificationRedirectMixin, RedirectView):
|
|||
|
||||
def get(self, request, *args, **kwargs):
|
||||
status = self.kwargs["status"]
|
||||
notification_id = self.kwargs["slug"]
|
||||
notification_uuid = self.kwargs["uuid"]
|
||||
|
||||
notification = get_object_or_404(Notification, recipient=request.user, id=notification_id)
|
||||
notification = get_object_or_404(Notification, recipient=request.user, uuid=notification_uuid)
|
||||
|
||||
method = getattr(notification, f"mark_as_{status}", None)
|
||||
if not method:
|
||||
|
|
|
|||
Loading…
Reference in a new issue