diff --git a/cachalot/admin_tests/__init__.py b/cachalot/admin_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cachalot/admin_tests/admin.py b/cachalot/admin_tests/admin.py new file mode 100644 index 0000000..dc42133 --- /dev/null +++ b/cachalot/admin_tests/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import TestModel + +@admin.register(TestModel) +class TestModelAdmin(admin.ModelAdmin): + list_display = ('name', 'owner') diff --git a/cachalot/admin_tests/migrations/0001_initial.py b/cachalot/admin_tests/migrations/0001_initial.py new file mode 100644 index 0000000..9e41fe6 --- /dev/null +++ b/cachalot/admin_tests/migrations/0001_initial.py @@ -0,0 +1,52 @@ +# Generated by Django 4.1.7 on 2023-03-10 19:33 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.db.models.functions.text + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="TestModel", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=20)), + ( + "owner", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "ordering": ("name",), + }, + ), + migrations.AddConstraint( + model_name="testmodel", + constraint=models.UniqueConstraint( + fields=["name"], + condition=models.Q(owner=None), + name="unique_name", + ), + ), + ] diff --git a/cachalot/admin_tests/migrations/__init__.py b/cachalot/admin_tests/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cachalot/admin_tests/models.py b/cachalot/admin_tests/models.py new file mode 100644 index 0000000..15ce4eb --- /dev/null +++ b/cachalot/admin_tests/models.py @@ -0,0 +1,18 @@ +from django.conf import settings +from django.db.models import Q, UniqueConstraint, Model, CharField, ForeignKey, SET_NULL + + +class TestModel(Model): + name = CharField(max_length=20) + owner = ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, + on_delete=SET_NULL) + + class Meta: + ordering = ('name',) + constraints = [ + UniqueConstraint( + fields=["name"], + condition=Q(owner=None), + name="unique_name", + ) + ] diff --git a/cachalot/admin_tests/test_admin.py b/cachalot/admin_tests/test_admin.py new file mode 100644 index 0000000..81df0fe --- /dev/null +++ b/cachalot/admin_tests/test_admin.py @@ -0,0 +1,19 @@ +from django.test import TestCase +from django.contrib.auth.models import User +from .models import TestModel +from django.test import Client + + +class AdminTestCase(TestCase): + def setUp(self): + self.client = Client() + self.user = User.objects.create(username='admin', is_staff=True, is_superuser=True) + + def test_save_test_model(self): + """ + Model 'TestModel' has UniqueConstraint which caused problems when saving TestModelAdmin in Django >= 4.1 + """ + self.client.force_login(self.user) + response = self.client.post('/admin/admin_tests/testmodel/add/', {'name': 'test', 'public': True}) + self.assertEqual(response.status_code, 302) + self.assertEqual(TestModel.objects.count(), 1) diff --git a/cachalot/tests/read.py b/cachalot/tests/read.py index a08237e..f06354a 100644 --- a/cachalot/tests/read.py +++ b/cachalot/tests/read.py @@ -52,12 +52,13 @@ class ReadTestCase(TestUtilsMixin, TransactionTestCase): self.group__permissions = list(Permission.objects.all()[:3]) self.group.permissions.add(*self.group__permissions) self.user = User.objects.create_user('user') - self.user__permissions = list(Permission.objects.all()[3:6]) + self.user__permissions = list(Permission.objects.filter(content_type__app_label='auth')[3:6]) self.user.groups.add(self.group) self.user.user_permissions.add(*self.user__permissions) self.admin = User.objects.create_superuser('admin', 'admin@test.me', 'password') - self.t1__permission = (Permission.objects.order_by('?') + self.t1__permission = (Permission.objects + .order_by('?') .select_related('content_type')[0]) self.t1 = Test.objects.create( name='test1', owner=self.user, diff --git a/runtests.py b/runtests.py index 14496e3..11f53a0 100755 --- a/runtests.py +++ b/runtests.py @@ -9,6 +9,6 @@ if __name__ == '__main__': django.setup() from django.test.runner import DiscoverRunner test_runner = DiscoverRunner(verbosity=2, interactive=False) - failures = test_runner.run_tests(['cachalot.tests']) + failures = test_runner.run_tests(['cachalot.tests', 'cachalot.admin_tests']) if failures: sys.exit(failures) diff --git a/runtests_urls.py b/runtests_urls.py index b11ff8c..4ca4fd1 100644 --- a/runtests_urls.py +++ b/runtests_urls.py @@ -1,6 +1,7 @@ import debug_toolbar -from django.urls import re_path, include +from django.urls import path, re_path, include from django.http import HttpResponse +from django.contrib import admin def empty_page(request): @@ -10,4 +11,5 @@ def empty_page(request): urlpatterns = [ re_path(r'^$', empty_page), re_path(r'^__debug__/', include(debug_toolbar.urls)), + path('admin/', admin.site.urls), ] diff --git a/settings.py b/settings.py index 0c1a89f..19d7560 100644 --- a/settings.py +++ b/settings.py @@ -12,6 +12,7 @@ DATABASES = { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'cachalot', 'USER': 'cachalot', + 'PASSWORD': 'password', 'HOST': '127.0.0.1', }, 'mysql': { @@ -90,9 +91,13 @@ elif DEFAULT_CACHE_ALIAS == 'pylibmc': INSTALLED_APPS = [ 'cachalot', + 'cachalot.admin_tests', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.postgres', # Enables the unaccent lookup. + 'django.contrib.sessions', + 'django.contrib.admin', + 'django.contrib.messages', ] MIGRATION_MODULES = { @@ -104,6 +109,12 @@ TEMPLATES = [ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + } }, { 'BACKEND': 'django.template.backends.jinja2.Jinja2', @@ -116,7 +127,11 @@ TEMPLATES = [ } ] -MIDDLEWARE = [] +MIDDLEWARE = [ + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +] PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher'] SECRET_KEY = 'it’s not important in tests but we have to set it'