django/tests/admin_ordering/tests.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

209 lines
7.1 KiB
Python
Raw Normal View History

from django.contrib import admin
from django.contrib.admin.options import ModelAdmin
from django.contrib.auth.models import User
from django.db.models import F
from django.test import RequestFactory, TestCase
from .models import (
Band,
DynOrderingBandAdmin,
Song,
SongInlineDefaultOrdering,
SongInlineNewOrdering,
)
class MockRequest:
pass
class MockSuperUser:
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, module):
return True
2016-11-13 01:11:23 +08:00
request = MockRequest()
request.user = MockSuperUser()
site = admin.AdminSite()
class TestAdminOrdering(TestCase):
"""
Let's make sure that ModelAdmin.get_queryset uses the ordering we define
in ModelAdmin rather that ordering defined in the model's inner Meta
class.
"""
request_factory = RequestFactory()
@classmethod
def setUpTestData(cls):
Band.objects.bulk_create(
[
Band(name="Aerosmith", bio="", rank=3),
Band(name="Radiohead", bio="", rank=1),
Band(name="Van Halen", bio="", rank=2),
]
)
def test_default_ordering(self):
"""
The default ordering should be by name, as specified in the inner Meta
class.
"""
ma = ModelAdmin(Band, site)
names = [b.name for b in ma.get_queryset(request)]
self.assertEqual(["Aerosmith", "Radiohead", "Van Halen"], names)
def test_specified_ordering(self):
"""
Let's use a custom ModelAdmin that changes the ordering, and make sure
it actually changes.
"""
class BandAdmin(ModelAdmin):
2013-11-03 05:02:56 +08:00
ordering = ("rank",) # default ordering is ('name',)
ma = BandAdmin(Band, site)
names = [b.name for b in ma.get_queryset(request)]
self.assertEqual(["Radiohead", "Van Halen", "Aerosmith"], names)
def test_specified_ordering_by_f_expression(self):
class BandAdmin(ModelAdmin):
ordering = (F("rank").desc(nulls_last=True),)
band_admin = BandAdmin(Band, site)
names = [b.name for b in band_admin.get_queryset(request)]
self.assertEqual(["Aerosmith", "Van Halen", "Radiohead"], names)
def test_dynamic_ordering(self):
"""
Let's use a custom ModelAdmin that changes the ordering dynamically.
"""
super_user = User.objects.create(username="admin", is_superuser=True)
other_user = User.objects.create(username="other")
request = self.request_factory.get("/")
request.user = super_user
ma = DynOrderingBandAdmin(Band, site)
names = [b.name for b in ma.get_queryset(request)]
self.assertEqual(["Radiohead", "Van Halen", "Aerosmith"], names)
request.user = other_user
names = [b.name for b in ma.get_queryset(request)]
self.assertEqual(["Aerosmith", "Radiohead", "Van Halen"], names)
class TestInlineModelAdminOrdering(TestCase):
"""
Let's make sure that InlineModelAdmin.get_queryset uses the ordering we
define in InlineModelAdmin.
"""
@classmethod
def setUpTestData(cls):
cls.band = Band.objects.create(name="Aerosmith", bio="", rank=3)
Song.objects.bulk_create(
[
Song(band=cls.band, name="Pink", duration=235),
Song(band=cls.band, name="Dude (Looks Like a Lady)", duration=264),
Song(band=cls.band, name="Jaded", duration=214),
]
)
def test_default_ordering(self):
"""
The default ordering should be by name, as specified in the inner Meta
class.
"""
inline = SongInlineDefaultOrdering(self.band, site)
names = [s.name for s in inline.get_queryset(request)]
self.assertEqual(["Dude (Looks Like a Lady)", "Jaded", "Pink"], names)
def test_specified_ordering(self):
"""
Let's check with ordering set to something different than the default.
"""
inline = SongInlineNewOrdering(self.band, site)
names = [s.name for s in inline.get_queryset(request)]
self.assertEqual(["Jaded", "Pink", "Dude (Looks Like a Lady)"], names)
class TestRelatedFieldsAdminOrdering(TestCase):
@classmethod
def setUpTestData(cls):
cls.b1 = Band.objects.create(name="Pink Floyd", bio="", rank=1)
cls.b2 = Band.objects.create(name="Foo Fighters", bio="", rank=5)
def setUp(self):
# we need to register a custom ModelAdmin (instead of just using
# ModelAdmin) because the field creator tries to find the ModelAdmin
# for the related model
class SongAdmin(admin.ModelAdmin):
pass
site.register(Song, SongAdmin)
def tearDown(self):
site.unregister(Song)
if Band in site._registry:
site.unregister(Band)
def check_ordering_of_field_choices(self, correct_ordering):
fk_field = site._registry[Song].formfield_for_foreignkey(
Song.band.field, request=None
)
m2m_field = site._registry[Song].formfield_for_manytomany(
Song.other_interpreters.field, request=None
)
self.assertEqual(list(fk_field.queryset), correct_ordering)
self.assertEqual(list(m2m_field.queryset), correct_ordering)
def test_no_admin_fallback_to_model_ordering(self):
# should be ordered by name (as defined by the model)
self.check_ordering_of_field_choices([self.b2, self.b1])
def test_admin_with_no_ordering_fallback_to_model_ordering(self):
class NoOrderingBandAdmin(admin.ModelAdmin):
pass
site.register(Band, NoOrderingBandAdmin)
# should be ordered by name (as defined by the model)
self.check_ordering_of_field_choices([self.b2, self.b1])
def test_admin_ordering_beats_model_ordering(self):
class StaticOrderingBandAdmin(admin.ModelAdmin):
ordering = ("rank",)
site.register(Band, StaticOrderingBandAdmin)
# should be ordered by rank (defined by the ModelAdmin)
self.check_ordering_of_field_choices([self.b1, self.b2])
def test_custom_queryset_still_wins(self):
"""Custom queryset has still precedence (#21405)"""
class SongAdmin(admin.ModelAdmin):
# Exclude one of the two Bands from the querysets
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "band":
kwargs["queryset"] = Band.objects.filter(rank__gt=2)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
2013-11-23 01:10:18 +08:00
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "other_interpreters":
kwargs["queryset"] = Band.objects.filter(rank__gt=2)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
class StaticOrderingBandAdmin(admin.ModelAdmin):
ordering = ("rank",)
site.unregister(Song)
site.register(Song, SongAdmin)
site.register(Band, StaticOrderingBandAdmin)
self.check_ordering_of_field_choices([self.b2])