mirror of
https://github.com/Hopiu/django-notifications.git
synced 2026-03-16 21:30:24 +00:00
Fixed related_name to not conflit with other apps
This commit is contained in:
parent
21c0a63ef5
commit
b1827ca531
13 changed files with 129 additions and 38 deletions
|
|
@ -3,13 +3,15 @@
|
|||
## 2.0.0
|
||||
- Migrated to Github CI
|
||||
- Added docker environment and migrated to Poetry and pyproject.toml
|
||||
- Added verbose_name migration
|
||||
- Migrated from `jsonfield` to Django `JSONField`
|
||||
- Converted the `level` field from a `CharField` to an `IntegerField`
|
||||
- Added **verbose_name** migration
|
||||
- Migrated the **data** field from `jsonfield` to Django `JSONField`
|
||||
- Converted the **level** field from a `CharField` to an `IntegerField`
|
||||
- Extracted and improved the sample code
|
||||
- Fixed variable types on JS code
|
||||
- Added `/all/` for the path to all notifications
|
||||
- Remove slug2id and id2slug
|
||||
- Changed **related_name** from `notifications` to `%(app_label)s_%(class)s_related` (default: `notifications_notification_related`)
|
||||
- Changed **related_query_name** from `notifications` to `%(app_label)s_%(class)s` (default: `notifications_notification`)
|
||||
|
||||
## 1.8.0
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -13,7 +13,7 @@ server:
|
|||
run: server
|
||||
|
||||
migrations:
|
||||
poetry run python manage.py makemigrations
|
||||
poetry run python notifications/manage.py makemigrations
|
||||
|
||||
migrate:
|
||||
poetry run python manage.py migrate
|
||||
|
|
|
|||
|
|
@ -184,7 +184,8 @@ can do:
|
|||
|
||||
```python
|
||||
user = User.objects.get(pk=pk)
|
||||
user.notifications.unread()
|
||||
user.notifications_notification_related.unread()
|
||||
# user.<your_app_name>_<your_model_name>_related.unread() # If you are using a custom model
|
||||
```
|
||||
|
||||
There are some other QuerySet methods, too.
|
||||
|
|
@ -477,6 +478,8 @@ You will require to define `NOTIFICATIONS_NOTIFICATION_MODEL` setting in
|
|||
NOTIFICATIONS_NOTIFICATION_MODEL = 'your_app.Notification'
|
||||
```
|
||||
|
||||
> If you are using a custom notification model, your **related_name** will change to `<your_app_name>_<your_model_name>_related`.
|
||||
|
||||
## Notes
|
||||
|
||||
### Email Notification
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ def get_num_to_fetch(request):
|
|||
def get_notification_list(request, method_name="all"):
|
||||
num_to_fetch = get_num_to_fetch(request)
|
||||
notification_list = []
|
||||
for notification in getattr(request.user.notifications, method_name)()[0:num_to_fetch]:
|
||||
for notification in getattr(request.user.notifications_notification_related, method_name)()[0:num_to_fetch]:
|
||||
struct = model_to_dict(notification)
|
||||
struct["slug"] = notification.id
|
||||
if notification.actor:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import os
|
|||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notification.tests.settings_for_tests")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notifications.tests.settings_for_tests")
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
# Generated by Django 4.2.11 on 2024-04-21 14:38
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("contenttypes", "0002_remove_content_type_name"),
|
||||
("notifications", "0014_rename_new_level_notification_level"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="notification",
|
||||
name="action_object_content_type",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="%(app_label)s_%(class)s_action_object_related",
|
||||
to="contenttypes.contenttype",
|
||||
verbose_name="action object content type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="notification",
|
||||
name="actor_content_type",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="%(app_label)s_%(class)s_actor_related",
|
||||
to="contenttypes.contenttype",
|
||||
verbose_name="actor content type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="notification",
|
||||
name="recipient",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="%(app_label)s_%(class)s_related",
|
||||
related_query_name="%(app_label)s_%(class)s",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="recipient",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="notification",
|
||||
name="target_content_type",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="%(app_label)s_%(class)s_target_related",
|
||||
to="contenttypes.contenttype",
|
||||
verbose_name="target content type",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
@ -57,14 +57,18 @@ class AbstractNotification(models.Model):
|
|||
recipient = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="notifications",
|
||||
related_name="%(app_label)s_%(class)s_related",
|
||||
related_query_name="%(app_label)s_%(class)s",
|
||||
verbose_name=_("recipient"),
|
||||
blank=False,
|
||||
)
|
||||
unread = models.BooleanField(_("unread"), default=True, blank=False, db_index=True)
|
||||
|
||||
actor_content_type = models.ForeignKey(
|
||||
ContentType, on_delete=models.CASCADE, related_name="notify_actor", verbose_name=_("actor content type")
|
||||
ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="%(app_label)s_%(class)s_actor_related",
|
||||
verbose_name=_("actor content type"),
|
||||
)
|
||||
actor_object_id = models.CharField(_("actor object id"), max_length=255)
|
||||
actor = GenericForeignKey("actor_content_type", "actor_object_id")
|
||||
|
|
@ -76,7 +80,7 @@ class AbstractNotification(models.Model):
|
|||
target_content_type = models.ForeignKey(
|
||||
ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="notify_target",
|
||||
related_name="%(app_label)s_%(class)s_target_related",
|
||||
verbose_name=_("target content type"),
|
||||
blank=True,
|
||||
null=True,
|
||||
|
|
@ -88,7 +92,7 @@ class AbstractNotification(models.Model):
|
|||
action_object_content_type = models.ForeignKey(
|
||||
ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="notify_action_object",
|
||||
related_name="%(app_label)s_%(class)s_action_object_related",
|
||||
verbose_name=_("action object content type"),
|
||||
blank=True,
|
||||
null=True,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from notifications.notification_types import AbstractUser
|
||||
from notifications.settings import notification_settings
|
||||
from notifications.types import AbstractUser
|
||||
|
||||
|
||||
def assert_soft_delete() -> None:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ register = Library()
|
|||
|
||||
def get_cached_notification_unread_count(user):
|
||||
return cache.get_or_set(
|
||||
"cache_notification_unread_count", user.notifications.unread().count, notification_settings.CACHE_TIMEOUT
|
||||
"cache_notification_unread_count",
|
||||
user.notifications_notification_related.unread().count,
|
||||
notification_settings.CACHE_TIMEOUT,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -27,7 +29,7 @@ def notifications_unread(context):
|
|||
@register.filter
|
||||
def has_notification(user):
|
||||
if user:
|
||||
return user.notifications.unread().exists()
|
||||
return user.notifications_notification_related.unread().exists()
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -82,29 +82,37 @@ class NotificationTestPages(TestCase):
|
|||
response = self.client.get(reverse("notifications:all"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.all()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.all())
|
||||
)
|
||||
|
||||
def test_unread_messages_pages(self):
|
||||
self.login("to", "pwd")
|
||||
response = self.client.get(reverse("notifications:unread"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.unread())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count)
|
||||
|
||||
for index, notification in enumerate(self.to_user.notifications.all()):
|
||||
for index, notification in enumerate(self.to_user.notifications_notification_related.all()):
|
||||
if index % 3 == 0:
|
||||
response = self.client.get(reverse("notifications:mark_as_read", args=[notification.id]))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
response = self.client.get(reverse("notifications:unread"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.unread())
|
||||
)
|
||||
self.assertTrue(len(response.context["notifications"]) < self.message_count)
|
||||
|
||||
response = self.client.get(reverse("notifications:mark_all_as_read"))
|
||||
self.assertRedirects(response, reverse("notifications:unread"))
|
||||
response = self.client.get(reverse("notifications:unread"))
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.unread())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), 0)
|
||||
|
||||
def test_next_pages(self):
|
||||
|
|
@ -119,7 +127,7 @@ class NotificationTestPages(TestCase):
|
|||
)
|
||||
self.assertRedirects(response, reverse("notifications:unread") + query_parameters)
|
||||
|
||||
slug = self.to_user.notifications.first().id
|
||||
slug = self.to_user.notifications_notification_related.first().id
|
||||
response = self.client.get(
|
||||
reverse("notifications:mark_as_read", args=[slug]),
|
||||
data={
|
||||
|
|
@ -128,7 +136,7 @@ class NotificationTestPages(TestCase):
|
|||
)
|
||||
self.assertRedirects(response, reverse("notifications:unread") + query_parameters)
|
||||
|
||||
slug = self.to_user.notifications.first().id
|
||||
slug = self.to_user.notifications_notification_related.first().id
|
||||
response = self.client.get(
|
||||
reverse("notifications:mark_as_unread", args=[slug]),
|
||||
{
|
||||
|
|
@ -137,7 +145,7 @@ class NotificationTestPages(TestCase):
|
|||
)
|
||||
self.assertRedirects(response, reverse("notifications:unread") + query_parameters)
|
||||
|
||||
@override_settings(ALLOWED_HOSTS=["www.notifications.com"])
|
||||
@override_settings(ALLOWED_HOSTS=["www.notifications_notification_related.com"])
|
||||
def test_malicious_next_pages(self):
|
||||
self.client.force_login(self.to_user)
|
||||
query_parameters = "?var1=hello&var2=world"
|
||||
|
|
@ -154,36 +162,44 @@ class NotificationTestPages(TestCase):
|
|||
def test_delete_messages_pages(self):
|
||||
self.login("to", "pwd")
|
||||
|
||||
slug = self.to_user.notifications.first().id
|
||||
slug = self.to_user.notifications_notification_related.first().id
|
||||
response = self.client.get(reverse("notifications:delete", args=[slug]))
|
||||
self.assertRedirects(response, reverse("notifications:all"))
|
||||
|
||||
response = self.client.get(reverse("notifications:all"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.all()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.all())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count - 1)
|
||||
|
||||
response = self.client.get(reverse("notifications:unread"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.unread())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count - 1)
|
||||
|
||||
@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True})
|
||||
def test_soft_delete_messages_manager(self):
|
||||
self.login("to", "pwd")
|
||||
|
||||
slug = self.to_user.notifications.first().id
|
||||
slug = self.to_user.notifications_notification_related.first().id
|
||||
response = self.client.get(reverse("notifications:delete", args=[slug]))
|
||||
self.assertRedirects(response, reverse("notifications:all"))
|
||||
|
||||
response = self.client.get(reverse("notifications:all"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.active()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.active())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count - 1)
|
||||
|
||||
response = self.client.get(reverse("notifications:unread"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(
|
||||
len(response.context["notifications"]), len(self.to_user.notifications_notification_related.unread())
|
||||
)
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count - 1)
|
||||
|
||||
def test_unread_count_api(self):
|
||||
|
|
|
|||
|
|
@ -34,20 +34,20 @@ class AllNotificationsList(NotificationViewList):
|
|||
|
||||
def get_queryset(self):
|
||||
if notification_settings.SOFT_DELETE:
|
||||
qset = self.request.user.notifications.active()
|
||||
qset = self.request.user.notifications_notification_related.active()
|
||||
else:
|
||||
qset = self.request.user.notifications.all()
|
||||
qset = self.request.user.notifications_notification_related.all()
|
||||
return qset
|
||||
|
||||
|
||||
class UnreadNotificationsList(NotificationViewList):
|
||||
def get_queryset(self):
|
||||
return self.request.user.notifications.unread()
|
||||
return self.request.user.notifications_notification_related.unread()
|
||||
|
||||
|
||||
@login_required
|
||||
def mark_all_as_read(request):
|
||||
request.user.notifications.mark_all_as_read()
|
||||
request.user.notifications_notification_related.mark_all_as_read()
|
||||
|
||||
_next = request.GET.get("next")
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ def live_unread_notification_count(request):
|
|||
data = {"unread_count": 0}
|
||||
else:
|
||||
data = {
|
||||
"unread_count": request.user.notifications.unread().count(),
|
||||
"unread_count": request.user.notifications_notification_related.unread().count(),
|
||||
}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
|
@ -126,7 +126,10 @@ def live_unread_notification_list(request):
|
|||
|
||||
unread_list = get_notification_list(request, "unread")
|
||||
|
||||
data = {"unread_count": request.user.notifications.unread().count(), "unread_list": unread_list}
|
||||
data = {
|
||||
"unread_count": request.user.notifications_notification_related.unread().count(),
|
||||
"unread_list": unread_list,
|
||||
}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
|
|
@ -139,7 +142,7 @@ def live_all_notification_list(request):
|
|||
|
||||
all_list = get_notification_list(request)
|
||||
|
||||
data = {"all_count": request.user.notifications.count(), "all_list": all_list}
|
||||
data = {"all_count": request.user.notifications_notification_related.count(), "all_list": all_list}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
|
|
@ -148,6 +151,6 @@ def live_all_notification_count(request):
|
|||
data = {"all_count": 0}
|
||||
else:
|
||||
data = {
|
||||
"all_count": request.user.notifications.count(),
|
||||
"all_count": request.user.notifications_notification_related.count(),
|
||||
}
|
||||
return JsonResponse(data)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ def live_tester(request):
|
|||
request,
|
||||
"test_live.html",
|
||||
{
|
||||
"unread_count": request.user.notifications.unread().count(),
|
||||
"notifications": request.user.notifications.all(),
|
||||
"unread_count": request.user.notifications_notification_related.unread().count(),
|
||||
"notifications": request.user.notifications_notification_related.all(),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue