summaryrefslogtreecommitdiff
path: root/tests/admin_views
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2022-02-03 20:24:19 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-02-07 20:37:05 +0100
commit9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch)
treef0506b668a013d0063e5fba3dbf4863b466713ba /tests/admin_views
parentf68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff)
downloaddjango-9c19aff7c7561e3a82978a272ecdaad40dda5c00.tar.gz
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/admin_views')
-rw-r--r--tests/admin_views/admin.py727
-rw-r--r--tests/admin_views/custom_has_permission_admin.py14
-rw-r--r--tests/admin_views/customadmin.py33
-rw-r--r--tests/admin_views/forms.py11
-rw-r--r--tests/admin_views/models.py238
-rw-r--r--tests/admin_views/test_actions.py414
-rw-r--r--tests/admin_views/test_adminsite.py72
-rw-r--r--tests/admin_views/test_autocomplete_view.py442
-rw-r--r--tests/admin_views/test_forms.py25
-rw-r--r--tests/admin_views/test_history_view.py79
-rw-r--r--tests/admin_views/test_multidb.py38
-rw-r--r--tests/admin_views/test_nav_sidebar.py187
-rw-r--r--tests/admin_views/test_templatetags.py147
-rw-r--r--tests/admin_views/tests.py5981
-rw-r--r--tests/admin_views/urls.py42
-rw-r--r--tests/admin_views/views.py2
16 files changed, 5122 insertions, 3330 deletions
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 9cd078074b..b78746c0ff 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -20,33 +20,127 @@ from django.views.decorators.common import no_append_slash
from .forms import MediaActionForm
from .models import (
- Actor, AdminOrderedAdminMethod, AdminOrderedCallable, AdminOrderedField,
- AdminOrderedModelMethod, Album, Answer, Answer2, Article, BarAccount, Book,
- Bookmark, Box, Category, Chapter, ChapterXtra1, Child, ChildOfReferer,
- Choice, City, Collector, Color, Color2, ComplexSortedPerson, CoverLetter,
- CustomArticle, CyclicOne, CyclicTwo, DependentChild, DooHickey, EmptyModel,
- EmptyModelHidden, EmptyModelMixin, EmptyModelVisible, ExplicitlyProvidedPK,
- ExternalSubscriber, Fabric, FancyDoodad, FieldOverridePost,
- FilteredManager, FooAccount, FoodDelivery, FunkyTag, Gadget, Gallery,
- GenRelReference, Grommet, ImplicitlyGeneratedPK, Ingredient,
- InlineReference, InlineReferer, Inquisition, Language, Link,
- MainPrepopulated, ModelWithStringPrimaryKey, NotReferenced, OldSubscriber,
- OtherStory, Paper, Parent, ParentWithDependentChildren, ParentWithUUIDPK,
- Person, Persona, Picture, Pizza, Plot, PlotDetails, PlotProxy,
- PluggableSearchPerson, Podcast, Post, PrePopulatedPost,
- PrePopulatedPostLargeSlug, PrePopulatedSubPost, Promo, Question,
- ReadablePizza, ReadOnlyPizza, ReadOnlyRelatedField, Recipe, Recommendation,
- Recommender, ReferencedByGenRel, ReferencedByInline, ReferencedByParent,
- RelatedPrepopulated, RelatedWithUUIDPKModel, Report, Reservation,
- Restaurant, RowLevelChangePermissionModel, Section, ShortMessage, Simple,
- Sketch, Song, State, Story, StumpJoke, Subscriber, SuperVillain, Telegram,
- Thing, Topping, UnchangeableObject, UndeletableObject, UnorderedObject,
- UserMessenger, UserProxy, Villain, Vodcast, Whatsit, Widget, Worker,
+ Actor,
+ AdminOrderedAdminMethod,
+ AdminOrderedCallable,
+ AdminOrderedField,
+ AdminOrderedModelMethod,
+ Album,
+ Answer,
+ Answer2,
+ Article,
+ BarAccount,
+ Book,
+ Bookmark,
+ Box,
+ Category,
+ Chapter,
+ ChapterXtra1,
+ Child,
+ ChildOfReferer,
+ Choice,
+ City,
+ Collector,
+ Color,
+ Color2,
+ ComplexSortedPerson,
+ CoverLetter,
+ CustomArticle,
+ CyclicOne,
+ CyclicTwo,
+ DependentChild,
+ DooHickey,
+ EmptyModel,
+ EmptyModelHidden,
+ EmptyModelMixin,
+ EmptyModelVisible,
+ ExplicitlyProvidedPK,
+ ExternalSubscriber,
+ Fabric,
+ FancyDoodad,
+ FieldOverridePost,
+ FilteredManager,
+ FooAccount,
+ FoodDelivery,
+ FunkyTag,
+ Gadget,
+ Gallery,
+ GenRelReference,
+ Grommet,
+ ImplicitlyGeneratedPK,
+ Ingredient,
+ InlineReference,
+ InlineReferer,
+ Inquisition,
+ Language,
+ Link,
+ MainPrepopulated,
+ ModelWithStringPrimaryKey,
+ NotReferenced,
+ OldSubscriber,
+ OtherStory,
+ Paper,
+ Parent,
+ ParentWithDependentChildren,
+ ParentWithUUIDPK,
+ Person,
+ Persona,
+ Picture,
+ Pizza,
+ Plot,
+ PlotDetails,
+ PlotProxy,
+ PluggableSearchPerson,
+ Podcast,
+ Post,
+ PrePopulatedPost,
+ PrePopulatedPostLargeSlug,
+ PrePopulatedSubPost,
+ Promo,
+ Question,
+ ReadablePizza,
+ ReadOnlyPizza,
+ ReadOnlyRelatedField,
+ Recipe,
+ Recommendation,
+ Recommender,
+ ReferencedByGenRel,
+ ReferencedByInline,
+ ReferencedByParent,
+ RelatedPrepopulated,
+ RelatedWithUUIDPKModel,
+ Report,
+ Reservation,
+ Restaurant,
+ RowLevelChangePermissionModel,
+ Section,
+ ShortMessage,
+ Simple,
+ Sketch,
+ Song,
+ State,
+ Story,
+ StumpJoke,
+ Subscriber,
+ SuperVillain,
+ Telegram,
+ Thing,
+ Topping,
+ UnchangeableObject,
+ UndeletableObject,
+ UnorderedObject,
+ UserMessenger,
+ UserProxy,
+ Villain,
+ Vodcast,
+ Whatsit,
+ Widget,
+ Worker,
WorkHour,
)
-@admin.display(ordering='date')
+@admin.display(ordering="date")
def callable_year(dt_value):
try:
return dt_value.year
@@ -56,19 +150,11 @@ def callable_year(dt_value):
class ArticleInline(admin.TabularInline):
model = Article
- fk_name = 'section'
- prepopulated_fields = {
- 'title': ('content',)
- }
+ fk_name = "section"
+ prepopulated_fields = {"title": ("content",)}
fieldsets = (
- ('Some fields', {
- 'classes': ('collapse',),
- 'fields': ('title', 'content')
- }),
- ('Some other fields', {
- 'classes': ('wide',),
- 'fields': ('date', 'section')
- })
+ ("Some fields", {"classes": ("collapse",), "fields": ("title", "content")}),
+ ("Some other fields", {"classes": ("wide",), "fields": ("date", "section")}),
)
@@ -78,13 +164,13 @@ class ChapterInline(admin.TabularInline):
class ChapterXtra1Admin(admin.ModelAdmin):
list_filter = (
- 'chap',
- 'chap__title',
- 'chap__book',
- 'chap__book__name',
- 'chap__book__promo',
- 'chap__book__promo__name',
- 'guest_author__promo__book',
+ "chap",
+ "chap__title",
+ "chap__book",
+ "chap__book__name",
+ "chap__book__promo",
+ "chap__book__promo__name",
+ "guest_author__promo__book",
)
@@ -92,7 +178,7 @@ class ArticleForm(forms.ModelForm):
extra_form_field = forms.BooleanField(required=False)
class Meta:
- fields = '__all__'
+ fields = "__all__"
model = Article
@@ -100,7 +186,11 @@ class ArticleAdminWithExtraUrl(admin.ModelAdmin):
def get_urls(self):
urlpatterns = super().get_urls()
urlpatterns.append(
- path('extra.json', self.admin_site.admin_view(self.extra_json), name='article_extra_json')
+ path(
+ "extra.json",
+ self.admin_site.admin_view(self.extra_json),
+ name="article_extra_json",
+ )
)
return urlpatterns
@@ -110,76 +200,87 @@ class ArticleAdminWithExtraUrl(admin.ModelAdmin):
class ArticleAdmin(ArticleAdminWithExtraUrl):
list_display = (
- 'content', 'date', callable_year, 'model_year', 'modeladmin_year',
- 'model_year_reversed', 'section', lambda obj: obj.title,
- 'order_by_expression', 'model_property_year', 'model_month',
- 'order_by_f_expression', 'order_by_orderby_expression',
+ "content",
+ "date",
+ callable_year,
+ "model_year",
+ "modeladmin_year",
+ "model_year_reversed",
+ "section",
+ lambda obj: obj.title,
+ "order_by_expression",
+ "model_property_year",
+ "model_month",
+ "order_by_f_expression",
+ "order_by_orderby_expression",
)
- list_editable = ('section',)
- list_filter = ('date', 'section')
- autocomplete_fields = ('section',)
+ list_editable = ("section",)
+ list_filter = ("date", "section")
+ autocomplete_fields = ("section",)
view_on_site = False
form = ArticleForm
fieldsets = (
- ('Some fields', {
- 'classes': ('collapse',),
- 'fields': ('title', 'content', 'extra_form_field'),
- }),
- ('Some other fields', {
- 'classes': ('wide',),
- 'fields': ('date', 'section', 'sub_section')
- })
+ (
+ "Some fields",
+ {
+ "classes": ("collapse",),
+ "fields": ("title", "content", "extra_form_field"),
+ },
+ ),
+ (
+ "Some other fields",
+ {"classes": ("wide",), "fields": ("date", "section", "sub_section")},
+ ),
)
# These orderings aren't particularly useful but show that expressions can
# be used for admin_order_field.
- @admin.display(ordering=models.F('date') + datetime.timedelta(days=3))
+ @admin.display(ordering=models.F("date") + datetime.timedelta(days=3))
def order_by_expression(self, obj):
return obj.model_year
- @admin.display(ordering=models.F('date'))
+ @admin.display(ordering=models.F("date"))
def order_by_f_expression(self, obj):
return obj.model_year
- @admin.display(ordering=models.F('date').asc(nulls_last=True))
+ @admin.display(ordering=models.F("date").asc(nulls_last=True))
def order_by_orderby_expression(self, obj):
return obj.model_year
def changelist_view(self, request):
- return super().changelist_view(request, extra_context={'extra_var': 'Hello!'})
+ return super().changelist_view(request, extra_context={"extra_var": "Hello!"})
- @admin.display(ordering='date', description=None)
+ @admin.display(ordering="date", description=None)
def modeladmin_year(self, obj):
return obj.date.year
def delete_model(self, request, obj):
EmailMessage(
- 'Greetings from a deleted object',
- 'I hereby inform you that some user deleted me',
- 'from@example.com',
- ['to@example.com']
+ "Greetings from a deleted object",
+ "I hereby inform you that some user deleted me",
+ "from@example.com",
+ ["to@example.com"],
).send()
return super().delete_model(request, obj)
def save_model(self, request, obj, form, change=True):
EmailMessage(
- 'Greetings from a created object',
- 'I hereby inform you that some user created me',
- 'from@example.com',
- ['to@example.com']
+ "Greetings from a created object",
+ "I hereby inform you that some user created me",
+ "from@example.com",
+ ["to@example.com"],
).send()
return super().save_model(request, obj, form, change)
class ArticleAdmin2(admin.ModelAdmin):
-
def has_module_permission(self, request):
return False
class RowLevelChangePermissionModelAdmin(admin.ModelAdmin):
def has_change_permission(self, request, obj=None):
- """ Only allow changing objects with even id number """
+ """Only allow changing objects with even id number"""
return request.user.is_staff and (obj is not None) and (obj.id % 2 == 0)
def has_view_permission(self, request, obj=None):
@@ -191,63 +292,68 @@ class CustomArticleAdmin(admin.ModelAdmin):
"""
Tests various hooks for using custom templates and contexts.
"""
- change_list_template = 'custom_admin/change_list.html'
- change_form_template = 'custom_admin/change_form.html'
- add_form_template = 'custom_admin/add_form.html'
- object_history_template = 'custom_admin/object_history.html'
- delete_confirmation_template = 'custom_admin/delete_confirmation.html'
- delete_selected_confirmation_template = 'custom_admin/delete_selected_confirmation.html'
- popup_response_template = 'custom_admin/popup_response.html'
+
+ change_list_template = "custom_admin/change_list.html"
+ change_form_template = "custom_admin/change_form.html"
+ add_form_template = "custom_admin/add_form.html"
+ object_history_template = "custom_admin/object_history.html"
+ delete_confirmation_template = "custom_admin/delete_confirmation.html"
+ delete_selected_confirmation_template = (
+ "custom_admin/delete_selected_confirmation.html"
+ )
+ popup_response_template = "custom_admin/popup_response.html"
def changelist_view(self, request):
- return super().changelist_view(request, extra_context={'extra_var': 'Hello!'})
+ return super().changelist_view(request, extra_context={"extra_var": "Hello!"})
class ThingAdmin(admin.ModelAdmin):
- list_filter = ('color', 'color__warm', 'color__value', 'pub_date')
+ list_filter = ("color", "color__warm", "color__value", "pub_date")
class InquisitionAdmin(admin.ModelAdmin):
- list_display = ('leader', 'country', 'expected', 'sketch')
+ list_display = ("leader", "country", "expected", "sketch")
@admin.display
def sketch(self, obj):
# A method with the same name as a reverse accessor.
- return 'list-display-sketch'
+ return "list-display-sketch"
class SketchAdmin(admin.ModelAdmin):
- raw_id_fields = ('inquisition', 'defendant0', 'defendant1')
+ raw_id_fields = ("inquisition", "defendant0", "defendant1")
class FabricAdmin(admin.ModelAdmin):
- list_display = ('surface',)
- list_filter = ('surface',)
+ list_display = ("surface",)
+ list_filter = ("surface",)
class BasePersonModelFormSet(BaseModelFormSet):
def clean(self):
for person_dict in self.cleaned_data:
- person = person_dict.get('id')
- alive = person_dict.get('alive')
+ person = person_dict.get("id")
+ alive = person_dict.get("alive")
if person and alive and person.name == "Grace Hopper":
raise ValidationError("Grace is not a Zombie")
class PersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'gender', 'alive')
- list_editable = ('gender', 'alive')
- list_filter = ('gender',)
- search_fields = ('^name',)
+ list_display = ("name", "gender", "alive")
+ list_editable = ("gender", "alive")
+ list_filter = ("gender",)
+ search_fields = ("^name",)
save_as = True
def get_changelist_formset(self, request, **kwargs):
- return super().get_changelist_formset(request, formset=BasePersonModelFormSet, **kwargs)
+ return super().get_changelist_formset(
+ request, formset=BasePersonModelFormSet, **kwargs
+ )
def get_queryset(self, request):
# Order by a field that isn't in list display, to be able to test
# whether ordering is preserved.
- return super().get_queryset(request).order_by('age')
+ return super().get_queryset(request).order_by("age")
class FooAccountAdmin(admin.StackedInline):
@@ -261,14 +367,11 @@ class BarAccountAdmin(admin.StackedInline):
class PersonaAdmin(admin.ModelAdmin):
- inlines = (
- FooAccountAdmin,
- BarAccountAdmin
- )
+ inlines = (FooAccountAdmin, BarAccountAdmin)
class SubscriberAdmin(admin.ModelAdmin):
- actions = ['mail_admin']
+ actions = ["mail_admin"]
action_form = MediaActionForm
def delete_queryset(self, request, queryset):
@@ -278,38 +381,39 @@ class SubscriberAdmin(admin.ModelAdmin):
@admin.action
def mail_admin(self, request, selected):
EmailMessage(
- 'Greetings from a ModelAdmin action',
- 'This is the test email from an admin action',
- 'from@example.com',
- ['to@example.com']
+ "Greetings from a ModelAdmin action",
+ "This is the test email from an admin action",
+ "from@example.com",
+ ["to@example.com"],
).send()
-@admin.action(description='External mail (Another awesome action)')
+@admin.action(description="External mail (Another awesome action)")
def external_mail(modeladmin, request, selected):
EmailMessage(
- 'Greetings from a function action',
- 'This is the test email from a function action',
- 'from@example.com',
- ['to@example.com']
+ "Greetings from a function action",
+ "This is the test email from a function action",
+ "from@example.com",
+ ["to@example.com"],
).send()
-@admin.action(description='Redirect to (Awesome action)')
+@admin.action(description="Redirect to (Awesome action)")
def redirect_to(modeladmin, request, selected):
from django.http import HttpResponseRedirect
- return HttpResponseRedirect('/some-where-else/')
+ return HttpResponseRedirect("/some-where-else/")
-@admin.action(description='Download subscription')
+
+@admin.action(description="Download subscription")
def download(modeladmin, request, selected):
- buf = StringIO('This is the content of the file')
+ buf = StringIO("This is the content of the file")
return StreamingHttpResponse(FileWrapper(buf))
-@admin.action(description='No permission to run')
+@admin.action(description="No permission to run")
def no_perm(modeladmin, request, selected):
- return HttpResponse(content='No permission to perform this action', status=403)
+ return HttpResponse(content="No permission to perform this action", status=403)
class ExternalSubscriberAdmin(admin.ModelAdmin):
@@ -317,17 +421,17 @@ class ExternalSubscriberAdmin(admin.ModelAdmin):
class PodcastAdmin(admin.ModelAdmin):
- list_display = ('name', 'release_date')
- list_editable = ('release_date',)
- date_hierarchy = 'release_date'
- ordering = ('name',)
+ list_display = ("name", "release_date")
+ list_editable = ("release_date",)
+ date_hierarchy = "release_date"
+ ordering = ("name",)
class VodcastAdmin(admin.ModelAdmin):
- list_display = ('name', 'released')
- list_editable = ('released',)
+ list_display = ("name", "released")
+ list_editable = ("released",)
- ordering = ('name',)
+ ordering = ("name",)
class ChildInline(admin.StackedInline):
@@ -338,16 +442,19 @@ class ParentAdmin(admin.ModelAdmin):
model = Parent
inlines = [ChildInline]
save_as = True
- list_display = ('id', 'name',)
- list_display_links = ('id',)
- list_editable = ('name',)
+ list_display = (
+ "id",
+ "name",
+ )
+ list_display_links = ("id",)
+ list_editable = ("name",)
def save_related(self, request, form, formsets, change):
super().save_related(request, form, formsets, change)
first_name, last_name = form.instance.name.split()
for child in form.instance.child_set.all():
if len(child.name.split()) < 2:
- child.name = child.name + ' ' + last_name
+ child.name = child.name + " " + last_name
child.save()
@@ -374,13 +481,16 @@ class PictureAdmin(admin.ModelAdmin):
class LanguageAdmin(admin.ModelAdmin):
- list_display = ['iso', 'shortlist', 'english_name', 'name']
- list_editable = ['shortlist']
+ list_display = ["iso", "shortlist", "english_name", "name"]
+ list_editable = ["shortlist"]
class RecommendationAdmin(admin.ModelAdmin):
show_full_result_count = False
- search_fields = ('=titletranslation__text', '=the_recommender__titletranslation__text',)
+ search_fields = (
+ "=titletranslation__text",
+ "=the_recommender__titletranslation__text",
+ )
class WidgetInline(admin.StackedInline):
@@ -404,8 +514,8 @@ class FancyDoodadInline(admin.StackedInline):
class CategoryAdmin(admin.ModelAdmin):
- list_display = ('id', 'collector', 'order')
- list_editable = ('order',)
+ list_display = ("id", "collector", "order")
+ list_editable = ("order",)
class CategoryInline(admin.StackedInline):
@@ -414,8 +524,12 @@ class CategoryInline(admin.StackedInline):
class CollectorAdmin(admin.ModelAdmin):
inlines = [
- WidgetInline, DooHickeyInline, GrommetInline, WhatsitInline,
- FancyDoodadInline, CategoryInline
+ WidgetInline,
+ DooHickeyInline,
+ GrommetInline,
+ WhatsitInline,
+ FancyDoodadInline,
+ CategoryInline,
]
@@ -433,13 +547,11 @@ class LinkInline(admin.TabularInline):
class SubPostInline(admin.TabularInline):
model = PrePopulatedSubPost
- prepopulated_fields = {
- 'subslug': ('subtitle',)
- }
+ prepopulated_fields = {"subslug": ("subtitle",)}
def get_readonly_fields(self, request, obj=None):
if obj and obj.published:
- return ('subslug',)
+ return ("subslug",)
return self.readonly_fields
def get_prepopulated_fields(self, request, obj=None):
@@ -449,16 +561,14 @@ class SubPostInline(admin.TabularInline):
class PrePopulatedPostAdmin(admin.ModelAdmin):
- list_display = ['title', 'slug']
- prepopulated_fields = {
- 'slug': ('title',)
- }
+ list_display = ["title", "slug"]
+ prepopulated_fields = {"slug": ("title",)}
inlines = [SubPostInline]
def get_readonly_fields(self, request, obj=None):
if obj and obj.published:
- return ('slug',)
+ return ("slug",)
return self.readonly_fields
def get_prepopulated_fields(self, request, obj=None):
@@ -468,23 +578,26 @@ class PrePopulatedPostAdmin(admin.ModelAdmin):
class PrePopulatedPostReadOnlyAdmin(admin.ModelAdmin):
- prepopulated_fields = {'slug': ('title',)}
+ prepopulated_fields = {"slug": ("title",)}
def has_change_permission(self, *args, **kwargs):
return False
class PostAdmin(admin.ModelAdmin):
- list_display = ['title', 'public']
+ list_display = ["title", "public"]
readonly_fields = (
- 'posted', 'awesomeness_level', 'coolness', 'value',
- 'multiline', 'multiline_html', lambda obj: "foo",
- 'readonly_content',
+ "posted",
+ "awesomeness_level",
+ "coolness",
+ "value",
+ "multiline",
+ "multiline_html",
+ lambda obj: "foo",
+ "readonly_content",
)
- inlines = [
- LinkInline
- ]
+ inlines = [LinkInline]
@admin.display
def coolness(self, instance):
@@ -493,7 +606,7 @@ class PostAdmin(admin.ModelAdmin):
else:
return "Unknown coolness."
- @admin.display(description='Value in $US')
+ @admin.display(description="Value in $US")
def value(self, instance):
return 1000
@@ -511,10 +624,10 @@ class FieldOverridePostForm(forms.ModelForm):
class Meta:
help_texts = {
- 'posted': 'Overridden help text for the date',
+ "posted": "Overridden help text for the date",
}
labels = {
- 'public': 'Overridden public label',
+ "public": "Overridden public label",
}
@@ -524,7 +637,7 @@ class FieldOverridePostAdmin(PostAdmin):
class CustomChangeList(ChangeList):
def get_queryset(self, request):
- return self.root_queryset.order_by('pk').filter(pk=9999) # Doesn't exist
+ return self.root_queryset.order_by("pk").filter(pk=9999) # Doesn't exist
class GadgetAdmin(admin.ModelAdmin):
@@ -533,23 +646,23 @@ class GadgetAdmin(admin.ModelAdmin):
class ToppingAdmin(admin.ModelAdmin):
- readonly_fields = ('pizzas',)
+ readonly_fields = ("pizzas",)
class PizzaAdmin(admin.ModelAdmin):
- readonly_fields = ('toppings',)
+ readonly_fields = ("toppings",)
class ReadOnlyRelatedFieldAdmin(admin.ModelAdmin):
- readonly_fields = ('chapter', 'language', 'user')
+ readonly_fields = ("chapter", "language", "user")
class StudentAdmin(admin.ModelAdmin):
- search_fields = ('name',)
+ search_fields = ("name",)
class ReadOnlyPizzaAdmin(admin.ModelAdmin):
- readonly_fields = ('name', 'toppings')
+ readonly_fields = ("name", "toppings")
def has_add_permission(self, request):
return False
@@ -562,13 +675,13 @@ class ReadOnlyPizzaAdmin(admin.ModelAdmin):
class WorkHourAdmin(admin.ModelAdmin):
- list_display = ('datum', 'employee')
- list_filter = ('employee',)
+ list_display = ("datum", "employee")
+ list_filter = ("employee",)
class FoodDeliveryAdmin(admin.ModelAdmin):
- list_display = ('reference', 'driver', 'restaurant')
- list_editable = ('driver', 'restaurant')
+ list_display = ("reference", "driver", "restaurant")
+ list_editable = ("driver", "restaurant")
class CoverLetterAdmin(admin.ModelAdmin):
@@ -580,7 +693,7 @@ class CoverLetterAdmin(admin.ModelAdmin):
"""
def get_queryset(self, request):
- return super().get_queryset(request).defer('date_written')
+ return super().get_queryset(request).defer("date_written")
class PaperAdmin(admin.ModelAdmin):
@@ -592,7 +705,7 @@ class PaperAdmin(admin.ModelAdmin):
"""
def get_queryset(self, request):
- return super().get_queryset(request).only('title')
+ return super().get_queryset(request).only("title")
class ShortMessageAdmin(admin.ModelAdmin):
@@ -604,7 +717,7 @@ class ShortMessageAdmin(admin.ModelAdmin):
"""
def get_queryset(self, request):
- return super().get_queryset(request).defer('timestamp')
+ return super().get_queryset(request).defer("timestamp")
class TelegramAdmin(admin.ModelAdmin):
@@ -616,45 +729,47 @@ class TelegramAdmin(admin.ModelAdmin):
"""
def get_queryset(self, request):
- return super().get_queryset(request).only('title')
+ return super().get_queryset(request).only("title")
class StoryForm(forms.ModelForm):
class Meta:
- widgets = {'title': forms.HiddenInput}
+ widgets = {"title": forms.HiddenInput}
class StoryAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'content')
- list_display_links = ('title',) # 'id' not in list_display_links
- list_editable = ('content',)
+ list_display = ("id", "title", "content")
+ list_display_links = ("title",) # 'id' not in list_display_links
+ list_editable = ("content",)
form = StoryForm
- ordering = ['-id']
+ ordering = ["-id"]
class OtherStoryAdmin(admin.ModelAdmin):
- list_display = ('id', 'title', 'content')
- list_display_links = ('title', 'id') # 'id' in list_display_links
- list_editable = ('content',)
- ordering = ['-id']
+ list_display = ("id", "title", "content")
+ list_display_links = ("title", "id") # 'id' in list_display_links
+ list_editable = ("content",)
+ ordering = ["-id"]
class ComplexSortedPersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'age', 'is_employee', 'colored_name')
- ordering = ('name',)
+ list_display = ("name", "age", "is_employee", "colored_name")
+ ordering = ("name",)
- @admin.display(ordering='name')
+ @admin.display(ordering="name")
def colored_name(self, obj):
return format_html('<span style="color: #ff00ff;">{}</span>', obj.name)
class PluggableSearchPersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'age')
- search_fields = ('name',)
+ list_display = ("name", "age")
+ search_fields = ("name",)
def get_search_results(self, request, queryset, search_term):
queryset, may_have_duplicates = super().get_search_results(
- request, queryset, search_term,
+ request,
+ queryset,
+ search_term,
)
try:
search_term_as_int = int(search_term)
@@ -666,51 +781,50 @@ class PluggableSearchPersonAdmin(admin.ModelAdmin):
class AlbumAdmin(admin.ModelAdmin):
- list_filter = ['title']
+ list_filter = ["title"]
class QuestionAdmin(admin.ModelAdmin):
- ordering = ['-posted']
- search_fields = ['question']
- autocomplete_fields = ['related_questions']
+ ordering = ["-posted"]
+ search_fields = ["question"]
+ autocomplete_fields = ["related_questions"]
class AnswerAdmin(admin.ModelAdmin):
- autocomplete_fields = ['question']
+ autocomplete_fields = ["question"]
class PrePopulatedPostLargeSlugAdmin(admin.ModelAdmin):
- prepopulated_fields = {
- 'slug': ('title',)
- }
+ prepopulated_fields = {"slug": ("title",)}
class AdminOrderedFieldAdmin(admin.ModelAdmin):
- ordering = ('order',)
- list_display = ('stuff', 'order')
+ ordering = ("order",)
+ list_display = ("stuff", "order")
class AdminOrderedModelMethodAdmin(admin.ModelAdmin):
- ordering = ('order',)
- list_display = ('stuff', 'some_order')
+ ordering = ("order",)
+ list_display = ("stuff", "some_order")
class AdminOrderedAdminMethodAdmin(admin.ModelAdmin):
- @admin.display(ordering='order')
+ @admin.display(ordering="order")
def some_admin_order(self, obj):
return obj.order
- ordering = ('order',)
- list_display = ('stuff', 'some_admin_order')
+
+ ordering = ("order",)
+ list_display = ("stuff", "some_admin_order")
-@admin.display(ordering='order')
+@admin.display(ordering="order")
def admin_ordered_callable(obj):
return obj.order
class AdminOrderedCallableAdmin(admin.ModelAdmin):
- ordering = ('order',)
- list_display = ('stuff', admin_ordered_callable)
+ ordering = ("order",)
+ list_display = ("stuff", admin_ordered_callable)
class ReportAdmin(admin.ModelAdmin):
@@ -719,60 +833,67 @@ class ReportAdmin(admin.ModelAdmin):
def get_urls(self):
# Corner case: Don't call parent implementation
- return [path('extra/', self.extra, name='cable_extra')]
+ return [path("extra/", self.extra, name="cable_extra")]
class CustomTemplateBooleanFieldListFilter(BooleanFieldListFilter):
- template = 'custom_filter_template.html'
+ template = "custom_filter_template.html"
class CustomTemplateFilterColorAdmin(admin.ModelAdmin):
- list_filter = (('warm', CustomTemplateBooleanFieldListFilter),)
+ list_filter = (("warm", CustomTemplateBooleanFieldListFilter),)
# For Selenium Prepopulated tests -------------------------------------
class RelatedPrepopulatedInline1(admin.StackedInline):
fieldsets = (
- (None, {
- 'fields': (
- ('fk', 'm2m'),
- ('pubdate', 'status'),
- ('name', 'slug1', 'slug2',),
- ),
- }),
+ (
+ None,
+ {
+ "fields": (
+ ("fk", "m2m"),
+ ("pubdate", "status"),
+ (
+ "name",
+ "slug1",
+ "slug2",
+ ),
+ ),
+ },
+ ),
)
- formfield_overrides = {models.CharField: {'strip': False}}
+ formfield_overrides = {models.CharField: {"strip": False}}
model = RelatedPrepopulated
extra = 1
- autocomplete_fields = ['fk', 'm2m']
+ autocomplete_fields = ["fk", "m2m"]
prepopulated_fields = {
- 'slug1': ['name', 'pubdate'],
- 'slug2': ['status', 'name'],
+ "slug1": ["name", "pubdate"],
+ "slug2": ["status", "name"],
}
class RelatedPrepopulatedInline2(admin.TabularInline):
model = RelatedPrepopulated
extra = 1
- autocomplete_fields = ['fk', 'm2m']
+ autocomplete_fields = ["fk", "m2m"]
prepopulated_fields = {
- 'slug1': ['name', 'pubdate'],
- 'slug2': ['status', 'name'],
+ "slug1": ["name", "pubdate"],
+ "slug2": ["status", "name"],
}
class RelatedPrepopulatedInline3(admin.TabularInline):
model = RelatedPrepopulated
extra = 0
- autocomplete_fields = ['fk', 'm2m']
+ autocomplete_fields = ["fk", "m2m"]
class RelatedPrepopulatedStackedInlineNoFieldsets(admin.StackedInline):
model = RelatedPrepopulated
extra = 1
prepopulated_fields = {
- 'slug1': ['name', 'pubdate'],
- 'slug2': ['status'],
+ "slug1": ["name", "pubdate"],
+ "slug2": ["status"],
}
@@ -784,28 +905,29 @@ class MainPrepopulatedAdmin(admin.ModelAdmin):
RelatedPrepopulatedStackedInlineNoFieldsets,
]
fieldsets = (
- (None, {
- 'fields': (('pubdate', 'status'), ('name', 'slug1', 'slug2', 'slug3'))
- }),
+ (
+ None,
+ {"fields": (("pubdate", "status"), ("name", "slug1", "slug2", "slug3"))},
+ ),
)
- formfield_overrides = {models.CharField: {'strip': False}}
+ formfield_overrides = {models.CharField: {"strip": False}}
prepopulated_fields = {
- 'slug1': ['name', 'pubdate'],
- 'slug2': ['status', 'name'],
- 'slug3': ['name'],
+ "slug1": ["name", "pubdate"],
+ "slug2": ["status", "name"],
+ "slug3": ["name"],
}
class UnorderedObjectAdmin(admin.ModelAdmin):
- list_display = ['id', 'name']
- list_display_links = ['id']
- list_editable = ['name']
+ list_display = ["id", "name"]
+ list_display_links = ["id"]
+ list_editable = ["name"]
list_per_page = 2
class UndeletableObjectAdmin(admin.ModelAdmin):
def change_view(self, *args, **kwargs):
- kwargs['extra_context'] = {'show_delete': False}
+ kwargs["extra_context"] = {"show_delete": False}
return super().change_view(*args, **kwargs)
@@ -831,8 +953,14 @@ class CustomManagerAdmin(admin.ModelAdmin):
class MessageTestingAdmin(admin.ModelAdmin):
- actions = ["message_debug", "message_info", "message_success",
- "message_warning", "message_error", "message_extra_tags"]
+ actions = [
+ "message_debug",
+ "message_info",
+ "message_success",
+ "message_warning",
+ "message_error",
+ "message_extra_tags",
+ ]
@admin.action
def message_debug(self, request, selected):
@@ -860,9 +988,9 @@ class MessageTestingAdmin(admin.ModelAdmin):
class ChoiceList(admin.ModelAdmin):
- list_display = ['choice']
- readonly_fields = ['choice']
- fields = ['choice']
+ list_display = ["choice"]
+ readonly_fields = ["choice"]
+ fields = ["choice"]
class DependentChildAdminForm(forms.ModelForm):
@@ -870,11 +998,16 @@ class DependentChildAdminForm(forms.ModelForm):
Issue #20522
Form to test child dependency on parent object's validation
"""
+
def clean(self):
- parent = self.cleaned_data.get('parent')
- if parent.family_name and parent.family_name != self.cleaned_data.get('family_name'):
- raise ValidationError("Children must share a family name with their parents " +
- "in this contrived test case")
+ parent = self.cleaned_data.get("parent")
+ if parent.family_name and parent.family_name != self.cleaned_data.get(
+ "family_name"
+ ):
+ raise ValidationError(
+ "Children must share a family name with their parents "
+ + "in this contrived test case"
+ )
return super().clean()
@@ -889,6 +1022,7 @@ class ParentWithDependentChildrenAdmin(admin.ModelAdmin):
# Tests for ticket 11277 ----------------------------------
+
class FormWithoutHiddenField(forms.ModelForm):
first = forms.CharField()
second = forms.CharField()
@@ -907,9 +1041,12 @@ class FormWithVisibleAndHiddenField(forms.ModelForm):
class EmptyModelVisibleAdmin(admin.ModelAdmin):
form = FormWithoutHiddenField
fieldsets = (
- (None, {
- 'fields': (('first', 'second'),),
- }),
+ (
+ None,
+ {
+ "fields": (("first", "second"),),
+ },
+ ),
)
@@ -933,8 +1070,8 @@ class StateAdminForm(forms.ModelForm):
class Meta:
model = State
- fields = '__all__'
- labels = {'name': 'State name (from form’s Meta.labels)'}
+ fields = "__all__"
+ labels = {"name": "State name (from form’s Meta.labels)"}
@property
def changed_data(self):
@@ -942,7 +1079,7 @@ class StateAdminForm(forms.ModelForm):
if data:
# Add arbitrary name to changed_data to test
# change message construction.
- return data + ['not_a_form_field']
+ return data + ["not_a_form_field"]
return data
@@ -963,20 +1100,20 @@ class CityAdmin(admin.ModelAdmin):
def get_formset_kwargs(self, request, obj, inline, prefix):
return {
**super().get_formset_kwargs(request, obj, inline, prefix),
- 'form_kwargs': {'initial': {'name': 'overridden_name'}},
+ "form_kwargs": {"initial": {"name": "overridden_name"}},
}
class WorkerAdmin(admin.ModelAdmin):
def view_on_site(self, obj):
- return '/worker/%s/%s/' % (obj.surname, obj.name)
+ return "/worker/%s/%s/" % (obj.surname, obj.name)
class WorkerInlineAdmin(admin.TabularInline):
model = Worker
def view_on_site(self, obj):
- return '/worker_inline/%s/%s/' % (obj.surname, obj.name)
+ return "/worker_inline/%s/%s/" % (obj.surname, obj.name)
class RestaurantAdmin(admin.ModelAdmin):
@@ -984,11 +1121,11 @@ class RestaurantAdmin(admin.ModelAdmin):
view_on_site = False
def get_changeform_initial_data(self, request):
- return {'name': 'overridden_value'}
+ return {"name": "overridden_value"}
class FunkyTagAdmin(admin.ModelAdmin):
- list_display = ('name', 'content_object')
+ list_display = ("name", "content_object")
class InlineReferenceInline(admin.TabularInline):
@@ -1000,11 +1137,11 @@ class InlineRefererAdmin(admin.ModelAdmin):
class PlotReadonlyAdmin(admin.ModelAdmin):
- readonly_fields = ('plotdetails',)
+ readonly_fields = ("plotdetails",)
class GetFormsetsArgumentCheckingAdmin(admin.ModelAdmin):
- fields = ['name']
+ fields = ["name"]
def add_view(self, request, *args, **kwargs):
request.is_add_view = True
@@ -1016,19 +1153,26 @@ class GetFormsetsArgumentCheckingAdmin(admin.ModelAdmin):
def get_formsets_with_inlines(self, request, obj=None):
if request.is_add_view and obj is not None:
- raise Exception("'obj' passed to get_formsets_with_inlines wasn't None during add_view")
+ raise Exception(
+ "'obj' passed to get_formsets_with_inlines wasn't None during add_view"
+ )
if not request.is_add_view and obj is None:
- raise Exception("'obj' passed to get_formsets_with_inlines was None during change_view")
+ raise Exception(
+ "'obj' passed to get_formsets_with_inlines was None during change_view"
+ )
return super().get_formsets_with_inlines(request, obj)
site = admin.AdminSite(name="admin")
-site.site_url = '/my-site-url/'
+site.site_url = "/my-site-url/"
site.register(Article, ArticleAdmin)
site.register(CustomArticle, CustomArticleAdmin)
site.register(
- Section, save_as=True, inlines=[ArticleInline],
- readonly_fields=['name_property'], search_fields=['name'],
+ Section,
+ save_as=True,
+ inlines=[ArticleInline],
+ readonly_fields=["name_property"],
+ search_fields=["name"],
)
site.register(ModelWithStringPrimaryKey)
site.register(Color)
@@ -1091,7 +1235,7 @@ site.register(InlineReferer, InlineRefererAdmin)
site.register(ReferencedByGenRel)
site.register(GenRelReference)
site.register(ParentWithUUIDPK)
-site.register(RelatedPrepopulated, search_fields=['name'])
+site.register(RelatedPrepopulated, search_fields=["name"])
site.register(RelatedWithUUIDPKModel)
site.register(ReadOnlyRelatedField, ReadOnlyRelatedFieldAdmin)
@@ -1113,8 +1257,8 @@ site.register(Topping, ToppingAdmin)
site.register(Album, AlbumAdmin)
site.register(Song)
site.register(Question, QuestionAdmin)
-site.register(Answer, AnswerAdmin, date_hierarchy='question__posted')
-site.register(Answer2, date_hierarchy='question__expires')
+site.register(Answer, AnswerAdmin, date_hierarchy="question__posted")
+site.register(Answer2, date_hierarchy="question__expires")
site.register(PrePopulatedPost, PrePopulatedPostAdmin)
site.register(ComplexSortedPerson, ComplexSortedPersonAdmin)
site.register(FilteredManager, CustomManagerAdmin)
@@ -1152,9 +1296,9 @@ site2.register(Group, GroupAdmin)
site2.register(ParentWithUUIDPK)
site2.register(
RelatedWithUUIDPKModel,
- list_display=['pk', 'parent'],
- list_editable=['parent'],
- raw_id_fields=['parent'],
+ list_display=["pk", "parent"],
+ list_editable=["parent"],
+ raw_id_fields=["parent"],
)
site2.register(Person, save_as_continue=False)
site2.register(ReadOnlyRelatedField, ReadOnlyRelatedFieldAdmin)
@@ -1166,21 +1310,27 @@ site7.register(Section)
site7.register(PrePopulatedPost, PrePopulatedPostReadOnlyAdmin)
site7.register(
Pizza,
- filter_horizontal=['toppings'],
+ filter_horizontal=["toppings"],
fieldsets=(
- ('Collapsible', {
- 'classes': ['collapse'],
- 'fields': ['toppings'],
- }),
+ (
+ "Collapsible",
+ {
+ "classes": ["collapse"],
+ "fields": ["toppings"],
+ },
+ ),
),
)
site7.register(
Question,
- filter_horizontal=['related_questions'],
+ filter_horizontal=["related_questions"],
fieldsets=(
- ('Not collapsible', {
- 'fields': ['related_questions'],
- }),
+ (
+ "Not collapsible",
+ {
+ "fields": ["related_questions"],
+ },
+ ),
),
)
@@ -1188,37 +1338,42 @@ site7.register(
# Used to test ModelAdmin.sortable_by and get_sortable_by().
class ArticleAdmin6(admin.ModelAdmin):
list_display = (
- 'content', 'date', callable_year, 'model_year', 'modeladmin_year',
- 'model_year_reversed', 'section',
+ "content",
+ "date",
+ callable_year,
+ "model_year",
+ "modeladmin_year",
+ "model_year_reversed",
+ "section",
)
- sortable_by = ('date', callable_year)
+ sortable_by = ("date", callable_year)
- @admin.display(ordering='date')
+ @admin.display(ordering="date")
def modeladmin_year(self, obj):
return obj.date.year
class ActorAdmin6(admin.ModelAdmin):
- list_display = ('name', 'age')
- sortable_by = ('name',)
+ list_display = ("name", "age")
+ sortable_by = ("name",)
def get_sortable_by(self, request):
- return ('age',)
+ return ("age",)
class ChapterAdmin6(admin.ModelAdmin):
- list_display = ('title', 'book')
+ list_display = ("title", "book")
sortable_by = ()
class ColorAdmin6(admin.ModelAdmin):
- list_display = ('value',)
+ list_display = ("value",)
def get_sortable_by(self, request):
return ()
-site6 = admin.AdminSite(name='admin6')
+site6 = admin.AdminSite(name="admin6")
site6.register(Article, ArticleAdmin6)
site6.register(Actor, ActorAdmin6)
site6.register(Chapter, ChapterAdmin6)
@@ -1240,10 +1395,10 @@ class ActorAdmin9(admin.ModelAdmin):
return urls
-site9 = admin.AdminSite(name='admin9')
+site9 = admin.AdminSite(name="admin9")
site9.register(Article, ArticleAdmin9)
site9.register(Actor, ActorAdmin9)
-site10 = admin.AdminSite(name='admin10')
+site10 = admin.AdminSite(name="admin10")
site10.final_catch_all_view = False
site10.register(Article, ArticleAdminWithExtraUrl)
diff --git a/tests/admin_views/custom_has_permission_admin.py b/tests/admin_views/custom_has_permission_admin.py
index 354f6a2418..6dc2011b24 100644
--- a/tests/admin_views/custom_has_permission_admin.py
+++ b/tests/admin_views/custom_has_permission_admin.py
@@ -6,24 +6,26 @@ from django.contrib.auth import get_permission_codename
from django.contrib.auth.forms import AuthenticationForm
from django.core.exceptions import ValidationError
-from . import admin as base_admin, models
+from . import admin as base_admin
+from . import models
-PERMISSION_NAME = 'admin_views.%s' % get_permission_codename('change', models.Article._meta)
+PERMISSION_NAME = "admin_views.%s" % get_permission_codename(
+ "change", models.Article._meta
+)
class PermissionAdminAuthenticationForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if not user.is_active or not (user.is_staff or user.has_perm(PERMISSION_NAME)):
- raise ValidationError('permission denied')
+ raise ValidationError("permission denied")
class HasPermissionAdmin(admin.AdminSite):
login_form = PermissionAdminAuthenticationForm
def has_permission(self, request):
- return (
- request.user.is_active and
- (request.user.is_staff or request.user.has_perm(PERMISSION_NAME))
+ return request.user.is_active and (
+ request.user.is_staff or request.user.has_perm(PERMISSION_NAME)
)
diff --git a/tests/admin_views/customadmin.py b/tests/admin_views/customadmin.py
index a9d8a060b9..f9e1f6fe1a 100644
--- a/tests/admin_views/customadmin.py
+++ b/tests/admin_views/customadmin.py
@@ -7,32 +7,33 @@ from django.contrib.auth.models import User
from django.http import HttpResponse
from django.urls import path
-from . import admin as base_admin, forms, models
+from . import admin as base_admin
+from . import forms, models
class Admin2(admin.AdminSite):
- app_index_template = 'custom_admin/app_index.html'
+ app_index_template = "custom_admin/app_index.html"
login_form = forms.CustomAdminAuthenticationForm
- login_template = 'custom_admin/login.html'
- logout_template = 'custom_admin/logout.html'
- index_template = ['custom_admin/index.html'] # a list, to test fix for #18697
- password_change_template = 'custom_admin/password_change_form.html'
- password_change_done_template = 'custom_admin/password_change_done.html'
+ login_template = "custom_admin/login.html"
+ logout_template = "custom_admin/logout.html"
+ index_template = ["custom_admin/index.html"] # a list, to test fix for #18697
+ password_change_template = "custom_admin/password_change_form.html"
+ password_change_done_template = "custom_admin/password_change_done.html"
# A custom index view.
def index(self, request, extra_context=None):
- return super().index(request, {'foo': '*bar*'})
+ return super().index(request, {"foo": "*bar*"})
def get_urls(self):
return [
- path('my_view/', self.admin_view(self.my_view), name='my_view'),
+ path("my_view/", self.admin_view(self.my_view), name="my_view"),
] + super().get_urls()
def my_view(self, request):
return HttpResponse("Django is a magical pony!")
def password_change(self, request, extra_context=None):
- return super().password_change(request, {'spam': 'eggs'})
+ return super().password_change(request, {"spam": "eggs"})
class UserLimitedAdmin(UserAdmin):
@@ -43,19 +44,23 @@ class UserLimitedAdmin(UserAdmin):
class CustomPwdTemplateUserAdmin(UserAdmin):
- change_user_password_template = ['admin/auth/user/change_password.html'] # a list, to test fix for #18697
+ change_user_password_template = [
+ "admin/auth/user/change_password.html"
+ ] # a list, to test fix for #18697
class BookAdmin(admin.ModelAdmin):
def get_deleted_objects(self, objs, request):
- return ['a deletable object'], {'books': 1}, set(), []
+ return ["a deletable object"], {"books": 1}, set(), []
site = Admin2(name="admin2")
site.register(models.Article, base_admin.ArticleAdmin)
site.register(models.Book, BookAdmin)
-site.register(models.Section, inlines=[base_admin.ArticleInline], search_fields=['name'])
+site.register(
+ models.Section, inlines=[base_admin.ArticleInline], search_fields=["name"]
+)
site.register(models.Thing, base_admin.ThingAdmin)
site.register(models.Fabric, base_admin.FabricAdmin)
site.register(models.ChapterXtra1, base_admin.ChapterXtra1Admin)
@@ -63,5 +68,5 @@ site.register(User, UserLimitedAdmin)
site.register(models.UndeletableObject, base_admin.UndeletableObjectAdmin)
site.register(models.Simple, base_admin.AttributeErrorRaisingAdmin)
-simple_site = Admin2(name='admin4')
+simple_site = Admin2(name="admin4")
simple_site.register(User, CustomPwdTemplateUserAdmin)
diff --git a/tests/admin_views/forms.py b/tests/admin_views/forms.py
index b25e49246a..e9d9c0a8a5 100644
--- a/tests/admin_views/forms.py
+++ b/tests/admin_views/forms.py
@@ -4,17 +4,16 @@ from django.core.exceptions import ValidationError
class CustomAdminAuthenticationForm(AdminAuthenticationForm):
-
class Media:
- css = {'all': ('path/to/media.css',)}
+ css = {"all": ("path/to/media.css",)}
def clean_username(self):
- username = self.cleaned_data.get('username')
- if username == 'customform':
- raise ValidationError('custom form error')
+ username = self.cleaned_data.get("username")
+ if username == "customform":
+ raise ValidationError("custom form error")
return username
class MediaActionForm(ActionForm):
class Media:
- js = ['path/to/media.js']
+ js = ["path/to/media.js"]
diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py
index c2972e0940..f6632816e8 100644
--- a/tests/admin_views/models.py
+++ b/tests/admin_views/models.py
@@ -4,9 +4,7 @@ import uuid
from django.contrib import admin
from django.contrib.auth.models import User
-from django.contrib.contenttypes.fields import (
- GenericForeignKey, GenericRelation,
-)
+from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.core.files.storage import FileSystemStorage
@@ -18,6 +16,7 @@ class Section(models.Model):
A simple section that links to articles, to test linking to related items
in admin views.
"""
+
name = models.CharField(max_length=100)
def __str__(self):
@@ -35,26 +34,31 @@ class Article(models.Model):
"""
A simple article to test admin views. Test backwards compatibility.
"""
+
title = models.CharField(max_length=100)
content = models.TextField()
date = models.DateTimeField()
section = models.ForeignKey(Section, models.CASCADE, null=True, blank=True)
- another_section = models.ForeignKey(Section, models.CASCADE, null=True, blank=True, related_name='+')
- sub_section = models.ForeignKey(Section, models.SET_NULL, null=True, blank=True, related_name='+')
+ another_section = models.ForeignKey(
+ Section, models.CASCADE, null=True, blank=True, related_name="+"
+ )
+ sub_section = models.ForeignKey(
+ Section, models.SET_NULL, null=True, blank=True, related_name="+"
+ )
def __str__(self):
return self.title
- @admin.display(ordering='date', description='')
+ @admin.display(ordering="date", description="")
def model_year(self):
return self.date.year
- @admin.display(ordering='-date', description='')
+ @admin.display(ordering="-date", description="")
def model_year_reversed(self):
return self.date.year
@property
- @admin.display(ordering='date')
+ @admin.display(ordering="date")
def model_property_year(self):
return self.date.year
@@ -67,14 +71,15 @@ class Book(models.Model):
"""
A simple book that has chapters.
"""
- name = models.CharField(max_length=100, verbose_name='¿Name?')
+
+ name = models.CharField(max_length=100, verbose_name="¿Name?")
def __str__(self):
return self.name
class Promo(models.Model):
- name = models.CharField(max_length=100, verbose_name='¿Name?')
+ name = models.CharField(max_length=100, verbose_name="¿Name?")
book = models.ForeignKey(Book, models.CASCADE)
author = models.ForeignKey(User, models.SET_NULL, blank=True, null=True)
@@ -83,33 +88,33 @@ class Promo(models.Model):
class Chapter(models.Model):
- title = models.CharField(max_length=100, verbose_name='¿Title?')
+ title = models.CharField(max_length=100, verbose_name="¿Title?")
content = models.TextField()
book = models.ForeignKey(Book, models.CASCADE)
class Meta:
# Use a utf-8 bytestring to ensure it works (see #11710)
- verbose_name = '¿Chapter?'
+ verbose_name = "¿Chapter?"
def __str__(self):
return self.title
class ChapterXtra1(models.Model):
- chap = models.OneToOneField(Chapter, models.CASCADE, verbose_name='¿Chap?')
- xtra = models.CharField(max_length=100, verbose_name='¿Xtra?')
+ chap = models.OneToOneField(Chapter, models.CASCADE, verbose_name="¿Chap?")
+ xtra = models.CharField(max_length=100, verbose_name="¿Xtra?")
guest_author = models.ForeignKey(User, models.SET_NULL, blank=True, null=True)
def __str__(self):
- return '¿Xtra1: %s' % self.xtra
+ return "¿Xtra1: %s" % self.xtra
class ChapterXtra2(models.Model):
- chap = models.OneToOneField(Chapter, models.CASCADE, verbose_name='¿Chap?')
- xtra = models.CharField(max_length=100, verbose_name='¿Xtra?')
+ chap = models.OneToOneField(Chapter, models.CASCADE, verbose_name="¿Chap?")
+ xtra = models.CharField(max_length=100, verbose_name="¿Xtra?")
def __str__(self):
- return '¿Xtra2: %s' % self.xtra
+ return "¿Xtra2: %s" % self.xtra
class RowLevelChangePermissionModel(models.Model):
@@ -128,7 +133,7 @@ class ModelWithStringPrimaryKey(models.Model):
return self.string_pk
def get_absolute_url(self):
- return '/dummy/%s/' % self.string_pk
+ return "/dummy/%s/" % self.string_pk
class Color(models.Model):
@@ -147,7 +152,7 @@ class Color2(Color):
class Thing(models.Model):
title = models.CharField(max_length=20)
- color = models.ForeignKey(Color, models.CASCADE, limit_choices_to={'warm': True})
+ color = models.ForeignKey(Color, models.CASCADE, limit_choices_to={"warm": True})
pub_date = models.DateField(blank=True, null=True)
def __str__(self):
@@ -178,22 +183,22 @@ class Sketch(models.Model):
Inquisition,
models.CASCADE,
limit_choices_to={
- 'leader__name': 'Palin',
- 'leader__age': 27,
- 'expected': False,
+ "leader__name": "Palin",
+ "leader__age": 27,
+ "expected": False,
},
)
defendant0 = models.ForeignKey(
Actor,
models.CASCADE,
- limit_choices_to={'title__isnull': False},
- related_name='as_defendant0',
+ limit_choices_to={"title__isnull": False},
+ related_name="as_defendant0",
)
defendant1 = models.ForeignKey(
Actor,
models.CASCADE,
- limit_choices_to={'title__isnull': True},
- related_name='as_defendant1',
+ limit_choices_to={"title__isnull": True},
+ related_name="as_defendant1",
)
def __str__(self):
@@ -224,7 +229,9 @@ class StumpJoke(models.Model):
limit_choices_to=today_callable_dict,
related_name="+",
)
- has_fooled_today = models.ManyToManyField(Character, limit_choices_to=today_callable_q, related_name="+")
+ has_fooled_today = models.ManyToManyField(
+ Character, limit_choices_to=today_callable_q, related_name="+"
+ )
def __str__(self):
return self.variation
@@ -232,11 +239,14 @@ class StumpJoke(models.Model):
class Fabric(models.Model):
NG_CHOICES = (
- ('Textured', (
- ('x', 'Horizontal'),
- ('y', 'Vertical'),
- )),
- ('plain', 'Smooth'),
+ (
+ "Textured",
+ (
+ ("x", "Horizontal"),
+ ("y", "Vertical"),
+ ),
+ ),
+ ("plain", "Smooth"),
)
surface = models.CharField(max_length=20, choices=NG_CHOICES)
@@ -260,6 +270,7 @@ class Persona(models.Model):
A simple persona associated with accounts, to test inlining of related
accounts which inherit from a common accounts class.
"""
+
name = models.CharField(blank=False, max_length=80)
def __str__(self):
@@ -271,9 +282,10 @@ class Account(models.Model):
A simple, generic account encapsulating the information shared by all
types of accounts.
"""
+
username = models.CharField(blank=False, max_length=80)
persona = models.ForeignKey(Persona, models.CASCADE, related_name="accounts")
- servicename = 'generic service'
+ servicename = "generic service"
def __str__(self):
return "%s: %s" % (self.servicename, self.username)
@@ -281,12 +293,14 @@ class Account(models.Model):
class FooAccount(Account):
"""A service-specific account of type Foo."""
- servicename = 'foo'
+
+ servicename = "foo"
class BarAccount(Account):
"""A service-specific account of type Bar."""
- servicename = 'bar'
+
+ servicename = "bar"
class Subscriber(models.Model):
@@ -313,11 +327,13 @@ class Podcast(Media):
release_date = models.DateField()
class Meta:
- ordering = ('release_date',) # overridden in PodcastAdmin
+ ordering = ("release_date",) # overridden in PodcastAdmin
class Vodcast(Media):
- media = models.OneToOneField(Media, models.CASCADE, primary_key=True, parent_link=True)
+ media = models.OneToOneField(
+ Media, models.CASCADE, primary_key=True, parent_link=True
+ )
released = models.BooleanField(default=False)
@@ -325,8 +341,8 @@ class Parent(models.Model):
name = models.CharField(max_length=128)
def clean(self):
- if self.name == '_invalid':
- raise ValidationError('invalid')
+ if self.name == "_invalid":
+ raise ValidationError("invalid")
class Child(models.Model):
@@ -334,19 +350,20 @@ class Child(models.Model):
name = models.CharField(max_length=30, blank=True)
def clean(self):
- if self.name == '_invalid':
- raise ValidationError('invalid')
+ if self.name == "_invalid":
+ raise ValidationError("invalid")
class PKChild(models.Model):
"""
Used to check autocomplete to_field resolution when ForeignKey is PK.
"""
+
parent = models.ForeignKey(Parent, models.CASCADE, primary_key=True)
name = models.CharField(max_length=128)
class Meta:
- ordering = ['parent']
+ ordering = ["parent"]
def __str__(self):
return self.name
@@ -370,7 +387,7 @@ class Gallery(models.Model):
class Picture(models.Model):
name = models.CharField(max_length=100)
- image = models.FileField(storage=temp_storage, upload_to='test_upload')
+ image = models.FileField(storage=temp_storage, upload_to="test_upload")
gallery = models.ForeignKey(Gallery, models.CASCADE, related_name="pictures")
@@ -384,7 +401,7 @@ class Language(models.Model):
return self.iso
class Meta:
- ordering = ('iso',)
+ ordering = ("iso",)
# a base class for Recommender and Recommendation
@@ -446,10 +463,10 @@ class Category(models.Model):
order = models.PositiveIntegerField()
class Meta:
- ordering = ('order',)
+ ordering = ("order",)
def __str__(self):
- return '%s:o%s' % (self.id, self.order)
+ return "%s:o%s" % (self.id, self.order)
def link_posted_default():
@@ -476,12 +493,16 @@ class PrePopulatedSubPost(models.Model):
class Post(models.Model):
- title = models.CharField(max_length=100, help_text='Some help text for the title (with Unicode ŠĐĆŽćžšđ)')
- content = models.TextField(help_text='Some help text for the content (with Unicode ŠĐĆŽćžšđ)')
+ title = models.CharField(
+ max_length=100, help_text="Some help text for the title (with Unicode ŠĐĆŽćžšđ)"
+ )
+ content = models.TextField(
+ help_text="Some help text for the content (with Unicode ŠĐĆŽćžšđ)"
+ )
readonly_content = models.TextField()
posted = models.DateField(
default=datetime.date.today,
- help_text='Some help text for the date (with Unicode ŠĐĆŽćžšđ)',
+ help_text="Some help text for the date (with Unicode ŠĐĆŽćžšđ)",
)
public = models.BooleanField(null=True, blank=True)
@@ -519,7 +540,7 @@ class FunkyTag(models.Model):
name = models.CharField(max_length=25)
content_type = models.ForeignKey(ContentType, models.CASCADE)
object_id = models.PositiveIntegerField()
- content_object = GenericForeignKey('content_type', 'object_id')
+ content_object = GenericForeignKey("content_type", "object_id")
def __str__(self):
return self.name
@@ -527,8 +548,8 @@ class FunkyTag(models.Model):
class Plot(models.Model):
name = models.CharField(max_length=100)
- team_leader = models.ForeignKey(Villain, models.CASCADE, related_name='lead_plots')
- contact = models.ForeignKey(Villain, models.CASCADE, related_name='contact_plots')
+ team_leader = models.ForeignKey(Villain, models.CASCADE, related_name="lead_plots")
+ contact = models.ForeignKey(Villain, models.CASCADE, related_name="contact_plots")
tags = GenericRelation(FunkyTag)
def __str__(self):
@@ -549,7 +570,8 @@ class PlotProxy(Plot):
class SecretHideout(models.Model):
- """ Secret! Not registered with the admin! """
+ """Secret! Not registered with the admin!"""
+
location = models.CharField(max_length=100)
villain = models.ForeignKey(Villain, models.CASCADE)
@@ -558,7 +580,8 @@ class SecretHideout(models.Model):
class SuperSecretHideout(models.Model):
- """ Secret! Not registered with the admin! """
+ """Secret! Not registered with the admin!"""
+
location = models.CharField(max_length=100)
supervillain = models.ForeignKey(SuperVillain, models.CASCADE)
@@ -568,7 +591,7 @@ class SuperSecretHideout(models.Model):
class Bookmark(models.Model):
name = models.CharField(max_length=60)
- tag = GenericRelation(FunkyTag, related_query_name='bookmark')
+ tag = GenericRelation(FunkyTag, related_query_name="bookmark")
def __str__(self):
return self.name
@@ -576,7 +599,7 @@ class Bookmark(models.Model):
class CyclicOne(models.Model):
name = models.CharField(max_length=25)
- two = models.ForeignKey('CyclicTwo', models.CASCADE)
+ two = models.ForeignKey("CyclicTwo", models.CASCADE)
def __str__(self):
return self.name
@@ -599,7 +622,7 @@ class Topping(models.Model):
class Pizza(models.Model):
name = models.CharField(max_length=20)
- toppings = models.ManyToManyField('Topping', related_name='pizzas')
+ toppings = models.ManyToManyField("Topping", related_name="pizzas")
# Pizza's ModelAdmin has readonly_fields = ['toppings'].
@@ -634,7 +657,7 @@ class Employee(Person):
code = models.CharField(max_length=20)
class Meta:
- ordering = ['name']
+ ordering = ["name"]
class WorkHour(models.Model):
@@ -646,6 +669,7 @@ class Manager(Employee):
"""
A multi-layer MTI child.
"""
+
pass
@@ -658,7 +682,7 @@ class Question(models.Model):
question = models.CharField(max_length=20)
posted = models.DateField(default=datetime.date.today)
expires = models.DateTimeField(null=True, blank=True)
- related_questions = models.ManyToManyField('self')
+ related_questions = models.ManyToManyField("self")
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
def __str__(self):
@@ -668,12 +692,15 @@ class Question(models.Model):
class Answer(models.Model):
question = models.ForeignKey(Question, models.PROTECT)
question_with_to_field = models.ForeignKey(
- Question, models.SET_NULL,
- blank=True, null=True, to_field='uuid',
- related_name='uuid_answers',
- limit_choices_to=~models.Q(question__istartswith='not'),
+ Question,
+ models.SET_NULL,
+ blank=True,
+ null=True,
+ to_field="uuid",
+ related_name="uuid_answers",
+ limit_choices_to=~models.Q(question__istartswith="not"),
)
- related_answers = models.ManyToManyField('self')
+ related_answers = models.ManyToManyField("self")
answer = models.CharField(max_length=20)
def __str__(self):
@@ -692,17 +719,19 @@ class Reservation(models.Model):
class FoodDelivery(models.Model):
DRIVER_CHOICES = (
- ('bill', 'Bill G'),
- ('steve', 'Steve J'),
+ ("bill", "Bill G"),
+ ("steve", "Steve J"),
)
RESTAURANT_CHOICES = (
- ('indian', 'A Taste of India'),
- ('thai', 'Thai Pography'),
- ('pizza', 'Pizza Mama'),
+ ("indian", "A Taste of India"),
+ ("thai", "Thai Pography"),
+ ("pizza", "Pizza Mama"),
)
reference = models.CharField(max_length=100)
driver = models.CharField(max_length=100, choices=DRIVER_CHOICES, blank=True)
- restaurant = models.CharField(max_length=100, choices=RESTAURANT_CHOICES, blank=True)
+ restaurant = models.CharField(
+ max_length=100, choices=RESTAURANT_CHOICES, blank=True
+ )
class Meta:
unique_together = (("driver", "restaurant"),)
@@ -761,6 +790,7 @@ class PrePopulatedPostLargeSlug(models.Model):
be localized in prepopulated_fields_js.html or it might end up breaking
the JavaScript (ie, using THOUSAND_SEPARATOR ends up with maxLength=1,000)
"""
+
title = models.CharField(max_length=100)
published = models.BooleanField(default=False)
# `db_index=False` because MySQL cannot index large CharField (#21196).
@@ -776,7 +806,7 @@ class AdminOrderedModelMethod(models.Model):
order = models.IntegerField()
stuff = models.CharField(max_length=200)
- @admin.display(ordering='order')
+ @admin.display(ordering="order")
def some_order(self):
return self.order
@@ -803,8 +833,8 @@ class MainPrepopulated(models.Model):
pubdate = models.DateField()
status = models.CharField(
max_length=20,
- choices=(('option one', 'Option One'),
- ('option two', 'Option Two')))
+ choices=(("option one", "Option One"), ("option two", "Option Two")),
+ )
slug1 = models.SlugField(blank=True)
slug2 = models.SlugField(blank=True)
slug3 = models.SlugField(blank=True, allow_unicode=True)
@@ -813,13 +843,13 @@ class MainPrepopulated(models.Model):
class RelatedPrepopulated(models.Model):
parent = models.ForeignKey(MainPrepopulated, models.CASCADE)
name = models.CharField(max_length=75)
- fk = models.ForeignKey('self', models.CASCADE, blank=True, null=True)
- m2m = models.ManyToManyField('self', blank=True)
+ fk = models.ForeignKey("self", models.CASCADE, blank=True, null=True)
+ m2m = models.ManyToManyField("self", blank=True)
pubdate = models.DateField()
status = models.CharField(
max_length=20,
- choices=(('option one', 'Option One'),
- ('option two', 'Option Two')))
+ choices=(("option one", "Option One"), ("option two", "Option Two")),
+ )
slug1 = models.SlugField(max_length=50)
slug2 = models.SlugField(max_length=60)
@@ -829,6 +859,7 @@ class UnorderedObject(models.Model):
Model without any defined `Meta.ordering`.
Refs #16819.
"""
+
name = models.CharField(max_length=255)
bool = models.BooleanField(default=True)
@@ -838,6 +869,7 @@ class UndeletableObject(models.Model):
Model whose show_delete in admin change_view has been disabled
Refs #10057.
"""
+
name = models.CharField(max_length=255)
@@ -862,8 +894,9 @@ class Simple(models.Model):
class Choice(models.Model):
choice = models.IntegerField(
- blank=True, null=True,
- choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion')),
+ blank=True,
+ null=True,
+ choices=((1, "Yes"), (0, "No"), (None, "No opinion")),
)
@@ -873,6 +906,7 @@ class ParentWithDependentChildren(models.Model):
Model where the validation of child foreign-key relationships depends
on validation of the parent
"""
+
some_required_info = models.PositiveIntegerField()
family_name = models.CharField(max_length=255, blank=False)
@@ -883,6 +917,7 @@ class DependentChild(models.Model):
Model that depends on validation of the parent class for one of its
fields to validate during clean
"""
+
parent = models.ForeignKey(ParentWithDependentChildren, models.CASCADE)
family_name = models.CharField(max_length=255)
@@ -901,27 +936,27 @@ class FilteredManager(models.Model):
class EmptyModelVisible(models.Model):
- """ See ticket #11277. """
+ """See ticket #11277."""
class EmptyModelHidden(models.Model):
- """ See ticket #11277. """
+ """See ticket #11277."""
class EmptyModelMixin(models.Model):
- """ See ticket #11277. """
+ """See ticket #11277."""
class State(models.Model):
- name = models.CharField(max_length=100, verbose_name='State verbose_name')
+ name = models.CharField(max_length=100, verbose_name="State verbose_name")
class City(models.Model):
state = models.ForeignKey(State, models.CASCADE)
- name = models.CharField(max_length=100, verbose_name='City verbose_name')
+ name = models.CharField(max_length=100, verbose_name="City verbose_name")
def get_absolute_url(self):
- return '/dummy/%s/' % self.pk
+ return "/dummy/%s/" % self.pk
class Restaurant(models.Model):
@@ -929,7 +964,7 @@ class Restaurant(models.Model):
name = models.CharField(max_length=100)
def get_absolute_url(self):
- return '/dummy/%s/' % self.pk
+ return "/dummy/%s/" % self.pk
class Worker(models.Model):
@@ -947,8 +982,8 @@ class ParentWithFK(models.Model):
fk = models.ForeignKey(
ReferencedByParent,
models.CASCADE,
- to_field='name',
- related_name='hidden+',
+ to_field="name",
+ related_name="hidden+",
)
@@ -970,8 +1005,8 @@ class InlineReference(models.Model):
fk = models.ForeignKey(
ReferencedByInline,
models.CASCADE,
- to_field='name',
- related_name='hidden+',
+ to_field="name",
+ related_name="hidden+",
)
@@ -981,12 +1016,12 @@ class Recipe(models.Model):
class Ingredient(models.Model):
iname = models.CharField(max_length=20, unique=True)
- recipes = models.ManyToManyField(Recipe, through='RecipeIngredient')
+ recipes = models.ManyToManyField(Recipe, through="RecipeIngredient")
class RecipeIngredient(models.Model):
- ingredient = models.ForeignKey(Ingredient, models.CASCADE, to_field='iname')
- recipe = models.ForeignKey(Recipe, models.CASCADE, to_field='rname')
+ ingredient = models.ForeignKey(Ingredient, models.CASCADE, to_field="iname")
+ recipe = models.ForeignKey(Recipe, models.CASCADE, to_field="rname")
# Model for #23839
@@ -1008,7 +1043,7 @@ class ImplicitlyGeneratedPK(models.Model):
class ReferencedByGenRel(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
- content_object = GenericForeignKey('content_type', 'object_id')
+ content_object = GenericForeignKey("content_type", "object_id")
class GenRelReference(models.Model):
@@ -1024,7 +1059,9 @@ class ParentWithUUIDPK(models.Model):
class RelatedWithUUIDPKModel(models.Model):
- parent = models.ForeignKey(ParentWithUUIDPK, on_delete=models.SET_NULL, null=True, blank=True)
+ parent = models.ForeignKey(
+ ParentWithUUIDPK, on_delete=models.SET_NULL, null=True, blank=True
+ )
class Author(models.Model):
@@ -1038,6 +1075,7 @@ class Authorship(models.Model):
class UserProxy(User):
"""Proxy a model with a different app_label."""
+
class Meta:
proxy = True
@@ -1054,5 +1092,9 @@ class Héllo(models.Model):
class Box(models.Model):
title = models.CharField(max_length=100)
- next_box = models.ForeignKey("self", null=True, on_delete=models.SET_NULL, blank=True)
- next_box = models.ForeignKey("self", null=True, on_delete=models.SET_NULL, blank=True)
+ next_box = models.ForeignKey(
+ "self", null=True, on_delete=models.SET_NULL, blank=True
+ )
+ next_box = models.ForeignKey(
+ "self", null=True, on_delete=models.SET_NULL, blank=True
+ )
diff --git a/tests/admin_views/test_actions.py b/tests/admin_views/test_actions.py
index 6c5aa5ad53..2bdcff44ae 100644
--- a/tests/admin_views/test_actions.py
+++ b/tests/admin_views/test_actions.py
@@ -12,19 +12,29 @@ from django.urls import reverse
from .admin import SubscriberAdmin
from .forms import MediaActionForm
from .models import (
- Actor, Answer, Book, ExternalSubscriber, Question, Subscriber,
+ Actor,
+ Answer,
+ Book,
+ ExternalSubscriber,
+ Question,
+ Subscriber,
UnchangeableObject,
)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminActionsTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = ExternalSubscriber.objects.create(name='John Doe', email='john@example.org')
- cls.s2 = Subscriber.objects.create(name='Max Mustermann', email='max@example.org')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = ExternalSubscriber.objects.create(
+ name="John Doe", email="john@example.org"
+ )
+ cls.s2 = Subscriber.objects.create(
+ name="Max Mustermann", email="max@example.org"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -33,44 +43,56 @@ class AdminActionsTest(TestCase):
"""A custom action defined in a ModelAdmin method."""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'mail_admin',
- 'index': 0,
+ "action": "mail_admin",
+ "index": 0,
}
- self.client.post(reverse('admin:admin_views_subscriber_changelist'), action_data)
+ self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), action_data
+ )
self.assertEqual(len(mail.outbox), 1)
- self.assertEqual(mail.outbox[0].subject, 'Greetings from a ModelAdmin action')
+ self.assertEqual(mail.outbox[0].subject, "Greetings from a ModelAdmin action")
def test_model_admin_default_delete_action(self):
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
delete_confirmation_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
- 'action': 'delete_selected',
- 'post': 'yes',
+ "action": "delete_selected",
+ "post": "yes",
}
- confirmation = self.client.post(reverse('admin:admin_views_subscriber_changelist'), action_data)
+ confirmation = self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), action_data
+ )
self.assertIsInstance(confirmation, TemplateResponse)
- self.assertContains(confirmation, 'Are you sure you want to delete the selected subscribers?')
- self.assertContains(confirmation, '<h2>Summary</h2>')
- self.assertContains(confirmation, '<li>Subscribers: 2</li>')
- self.assertContains(confirmation, '<li>External subscribers: 1</li>')
+ self.assertContains(
+ confirmation, "Are you sure you want to delete the selected subscribers?"
+ )
+ self.assertContains(confirmation, "<h2>Summary</h2>")
+ self.assertContains(confirmation, "<li>Subscribers: 2</li>")
+ self.assertContains(confirmation, "<li>External subscribers: 1</li>")
self.assertContains(confirmation, ACTION_CHECKBOX_NAME, count=2)
- self.client.post(reverse('admin:admin_views_subscriber_changelist'), delete_confirmation_data)
+ self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), delete_confirmation_data
+ )
self.assertEqual(Subscriber.objects.count(), 0)
def test_default_delete_action_nonexistent_pk(self):
self.assertFalse(Subscriber.objects.filter(id=9998).exists())
action_data = {
- ACTION_CHECKBOX_NAME: ['9998'],
- 'action': 'delete_selected',
- 'index': 0,
+ ACTION_CHECKBOX_NAME: ["9998"],
+ "action": "delete_selected",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_subscriber_changelist'), action_data)
- self.assertContains(response, 'Are you sure you want to delete the selected subscribers?')
- self.assertContains(response, '<ul></ul>', html=True)
+ response = self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), action_data
+ )
+ self.assertContains(
+ response, "Are you sure you want to delete the selected subscribers?"
+ )
+ self.assertContains(response, "<ul></ul>", html=True)
@override_settings(USE_THOUSAND_SEPARATOR=True, NUMBER_GROUPING=3)
def test_non_localized_pk(self):
@@ -81,11 +103,13 @@ class AdminActionsTest(TestCase):
s = ExternalSubscriber.objects.create(id=9999)
action_data = {
ACTION_CHECKBOX_NAME: [s.pk, self.s2.pk],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_subscriber_changelist'), action_data)
- self.assertTemplateUsed(response, 'admin/delete_selected_confirmation.html')
+ response = self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), action_data
+ )
+ self.assertTemplateUsed(response, "admin/delete_selected_confirmation.html")
self.assertContains(response, 'value="9999"') # Instead of 9,999
self.assertContains(response, 'value="%s"' % self.s2.pk)
@@ -94,33 +118,43 @@ class AdminActionsTest(TestCase):
The default delete action where some related objects are protected
from deletion.
"""
- q1 = Question.objects.create(question='Why?')
- a1 = Answer.objects.create(question=q1, answer='Because.')
- a2 = Answer.objects.create(question=q1, answer='Yes.')
- q2 = Question.objects.create(question='Wherefore?')
+ q1 = Question.objects.create(question="Why?")
+ a1 = Answer.objects.create(question=q1, answer="Because.")
+ a2 = Answer.objects.create(question=q1, answer="Yes.")
+ q2 = Question.objects.create(question="Wherefore?")
action_data = {
ACTION_CHECKBOX_NAME: [q1.pk, q2.pk],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
delete_confirmation_data = action_data.copy()
- delete_confirmation_data['post'] = 'yes'
- response = self.client.post(reverse('admin:admin_views_question_changelist'), action_data)
- self.assertContains(response, 'would require deleting the following protected related objects')
+ delete_confirmation_data["post"] = "yes"
+ response = self.client.post(
+ reverse("admin:admin_views_question_changelist"), action_data
+ )
+ self.assertContains(
+ response, "would require deleting the following protected related objects"
+ )
self.assertContains(
response,
- '<li>Answer: <a href="%s">Because.</a></li>' % reverse('admin:admin_views_answer_change', args=(a1.pk,)),
- html=True
+ '<li>Answer: <a href="%s">Because.</a></li>'
+ % reverse("admin:admin_views_answer_change", args=(a1.pk,)),
+ html=True,
)
self.assertContains(
response,
- '<li>Answer: <a href="%s">Yes.</a></li>' % reverse('admin:admin_views_answer_change', args=(a2.pk,)),
- html=True
+ '<li>Answer: <a href="%s">Yes.</a></li>'
+ % reverse("admin:admin_views_answer_change", args=(a2.pk,)),
+ html=True,
)
# A POST request to delete protected objects displays the page which
# says the deletion is prohibited.
- response = self.client.post(reverse('admin:admin_views_question_changelist'), delete_confirmation_data)
- self.assertContains(response, 'would require deleting the following protected related objects')
+ response = self.client.post(
+ reverse("admin:admin_views_question_changelist"), delete_confirmation_data
+ )
+ self.assertContains(
+ response, "would require deleting the following protected related objects"
+ )
self.assertEqual(Question.objects.count(), 2)
def test_model_admin_default_delete_action_no_change_url(self):
@@ -131,58 +165,68 @@ class AdminActionsTest(TestCase):
obj = UnchangeableObject.objects.create()
action_data = {
ACTION_CHECKBOX_NAME: obj.pk,
- 'action': 'delete_selected',
- 'index': '0',
+ "action": "delete_selected",
+ "index": "0",
}
- response = self.client.post(reverse('admin:admin_views_unchangeableobject_changelist'), action_data)
+ response = self.client.post(
+ reverse("admin:admin_views_unchangeableobject_changelist"), action_data
+ )
# No 500 caused by NoReverseMatch. The page doesn't display a link to
# the nonexistent change page.
- self.assertContains(response, '<li>Unchangeable object: %s</li>' % obj, 1, html=True)
+ self.assertContains(
+ response, "<li>Unchangeable object: %s</li>" % obj, 1, html=True
+ )
def test_delete_queryset_hook(self):
delete_confirmation_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
- 'action': 'delete_selected',
- 'post': 'yes',
- 'index': 0,
+ "action": "delete_selected",
+ "post": "yes",
+ "index": 0,
}
SubscriberAdmin.overridden = False
- self.client.post(reverse('admin:admin_views_subscriber_changelist'), delete_confirmation_data)
+ self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), delete_confirmation_data
+ )
# SubscriberAdmin.delete_queryset() sets overridden to True.
self.assertIs(SubscriberAdmin.overridden, True)
self.assertEqual(Subscriber.objects.all().count(), 0)
def test_delete_selected_uses_get_deleted_objects(self):
"""The delete_selected action uses ModelAdmin.get_deleted_objects()."""
- book = Book.objects.create(name='Test Book')
+ book = Book.objects.create(name="Test Book")
data = {
ACTION_CHECKBOX_NAME: [book.pk],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
- response = self.client.post(reverse('admin2:admin_views_book_changelist'), data)
+ response = self.client.post(reverse("admin2:admin_views_book_changelist"), data)
# BookAdmin.get_deleted_objects() returns custom text.
- self.assertContains(response, 'a deletable object')
+ self.assertContains(response, "a deletable object")
def test_custom_function_mail_action(self):
"""A custom action may be defined in a function."""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'external_mail',
- 'index': 0,
+ "action": "external_mail",
+ "index": 0,
}
- self.client.post(reverse('admin:admin_views_externalsubscriber_changelist'), action_data)
+ self.client.post(
+ reverse("admin:admin_views_externalsubscriber_changelist"), action_data
+ )
self.assertEqual(len(mail.outbox), 1)
- self.assertEqual(mail.outbox[0].subject, 'Greetings from a function action')
+ self.assertEqual(mail.outbox[0].subject, "Greetings from a function action")
def test_custom_function_action_with_redirect(self):
"""Another custom action defined in a function."""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'redirect_to',
- 'index': 0,
+ "action": "redirect_to",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_externalsubscriber_changelist'), action_data)
+ response = self.client.post(
+ reverse("admin:admin_views_externalsubscriber_changelist"), action_data
+ )
self.assertEqual(response.status_code, 302)
def test_default_redirect(self):
@@ -192,10 +236,10 @@ class AdminActionsTest(TestCase):
"""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'external_mail',
- 'index': 0,
+ "action": "external_mail",
+ "index": 0,
}
- url = reverse('admin:admin_views_externalsubscriber_changelist') + '?o=1'
+ url = reverse("admin:admin_views_externalsubscriber_changelist") + "?o=1"
response = self.client.post(url, action_data)
self.assertRedirects(response, url)
@@ -203,29 +247,37 @@ class AdminActionsTest(TestCase):
"""A custom action may return a StreamingHttpResponse."""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'download',
- 'index': 0,
+ "action": "download",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_externalsubscriber_changelist'), action_data)
- content = b''.join(response.streaming_content)
- self.assertEqual(content, b'This is the content of the file')
+ response = self.client.post(
+ reverse("admin:admin_views_externalsubscriber_changelist"), action_data
+ )
+ content = b"".join(response.streaming_content)
+ self.assertEqual(content, b"This is the content of the file")
self.assertEqual(response.status_code, 200)
def test_custom_function_action_no_perm_response(self):
"""A custom action may returns an HttpResponse with a 403 code."""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'no_perm',
- 'index': 0,
+ "action": "no_perm",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_externalsubscriber_changelist'), action_data)
+ response = self.client.post(
+ reverse("admin:admin_views_externalsubscriber_changelist"), action_data
+ )
self.assertEqual(response.status_code, 403)
- self.assertEqual(response.content, b'No permission to perform this action')
+ self.assertEqual(response.content, b"No permission to perform this action")
def test_actions_ordering(self):
"""Actions are ordered as expected."""
- response = self.client.get(reverse('admin:admin_views_externalsubscriber_changelist'))
- self.assertContains(response, '''<label>Action: <select name="action" required>
+ response = self.client.get(
+ reverse("admin:admin_views_externalsubscriber_changelist")
+ )
+ self.assertContains(
+ response,
+ """<label>Action: <select name="action" required>
<option value="" selected>---------</option>
<option value="delete_selected">Delete selected external
subscribers</option>
@@ -234,15 +286,20 @@ subscribers</option>
action)</option>
<option value="download">Download subscription</option>
<option value="no_perm">No permission to run</option>
-</select>''', html=True)
+</select>""",
+ html=True,
+ )
def test_model_without_action(self):
"""A ModelAdmin might not have any actions."""
- response = self.client.get(reverse('admin:admin_views_oldsubscriber_changelist'))
- self.assertIsNone(response.context['action_form'])
+ response = self.client.get(
+ reverse("admin:admin_views_oldsubscriber_changelist")
+ )
+ self.assertIsNone(response.context["action_form"])
self.assertNotContains(
- response, '<input type="checkbox" class="action-select"',
- msg_prefix='Found an unexpected action toggle checkboxbox in response'
+ response,
+ '<input type="checkbox" class="action-select"',
+ msg_prefix="Found an unexpected action toggle checkboxbox in response",
)
self.assertNotContains(response, '<input type="checkbox" class="action-select"')
@@ -250,18 +307,21 @@ action)</option>
"""
A ModelAdmin without any actions still has jQuery included on the page.
"""
- response = self.client.get(reverse('admin:admin_views_oldsubscriber_changelist'))
- self.assertIsNone(response.context['action_form'])
+ response = self.client.get(
+ reverse("admin:admin_views_oldsubscriber_changelist")
+ )
+ self.assertIsNone(response.context["action_form"])
self.assertContains(
- response, 'jquery.min.js',
- msg_prefix='jQuery missing from admin pages for model with no admin actions'
+ response,
+ "jquery.min.js",
+ msg_prefix="jQuery missing from admin pages for model with no admin actions",
)
def test_action_column_class(self):
"""The checkbox column class is present in the response."""
- response = self.client.get(reverse('admin:admin_views_subscriber_changelist'))
- self.assertIsNotNone(response.context['action_form'])
- self.assertContains(response, 'action-checkbox-column')
+ response = self.client.get(reverse("admin:admin_views_subscriber_changelist"))
+ self.assertIsNotNone(response.context["action_form"])
+ self.assertContains(response, "action-checkbox-column")
def test_multiple_actions_form(self):
"""
@@ -270,24 +330,26 @@ action)</option>
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
# Two different actions selected on the two forms...
- 'action': ['external_mail', 'delete_selected'],
+ "action": ["external_mail", "delete_selected"],
# ...but "go" was clicked on the top form.
- 'index': 0
+ "index": 0,
}
- self.client.post(reverse('admin:admin_views_externalsubscriber_changelist'), action_data)
+ self.client.post(
+ reverse("admin:admin_views_externalsubscriber_changelist"), action_data
+ )
# The action sends mail rather than deletes.
self.assertEqual(len(mail.outbox), 1)
- self.assertEqual(mail.outbox[0].subject, 'Greetings from a function action')
+ self.assertEqual(mail.outbox[0].subject, "Greetings from a function action")
def test_media_from_actions_form(self):
"""
The action form's media is included in the changelist view's media.
"""
- response = self.client.get(reverse('admin:admin_views_subscriber_changelist'))
+ response = self.client.get(reverse("admin:admin_views_subscriber_changelist"))
media_path = MediaActionForm.Media.js[0]
- self.assertIsInstance(response.context['action_form'], MediaActionForm)
- self.assertIn('media', response.context)
- self.assertIn(media_path, response.context['media']._js)
+ self.assertIsInstance(response.context["action_form"], MediaActionForm)
+ self.assertIn("media", response.context)
+ self.assertIn(media_path, response.context["media"]._js)
self.assertContains(response, media_path)
def test_user_message_on_none_selected(self):
@@ -296,14 +358,14 @@ action)</option>
"""
action_data = {
ACTION_CHECKBOX_NAME: [],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
- url = reverse('admin:admin_views_subscriber_changelist')
+ url = reverse("admin:admin_views_subscriber_changelist")
response = self.client.post(url, action_data)
self.assertRedirects(response, url, fetch_redirect_response=False)
response = self.client.get(response.url)
- msg = 'Items must be selected in order to perform actions on them. No items have been changed.'
+ msg = "Items must be selected in order to perform actions on them. No items have been changed."
self.assertContains(response, msg)
self.assertEqual(Subscriber.objects.count(), 2)
@@ -313,28 +375,28 @@ action)</option>
"""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
- 'action': '',
- 'index': 0,
+ "action": "",
+ "index": 0,
}
- url = reverse('admin:admin_views_subscriber_changelist')
+ url = reverse("admin:admin_views_subscriber_changelist")
response = self.client.post(url, action_data)
self.assertRedirects(response, url, fetch_redirect_response=False)
response = self.client.get(response.url)
- self.assertContains(response, 'No action selected.')
+ self.assertContains(response, "No action selected.")
self.assertEqual(Subscriber.objects.count(), 2)
def test_selection_counter(self):
"""The selection counter is there."""
- response = self.client.get(reverse('admin:admin_views_subscriber_changelist'))
- self.assertContains(response, '0 of 2 selected')
+ response = self.client.get(reverse("admin:admin_views_subscriber_changelist"))
+ self.assertContains(response, "0 of 2 selected")
def test_popup_actions(self):
- """ Actions aren't shown in popups."""
- changelist_url = reverse('admin:admin_views_subscriber_changelist')
+ """Actions aren't shown in popups."""
+ changelist_url = reverse("admin:admin_views_subscriber_changelist")
response = self.client.get(changelist_url)
- self.assertIsNotNone(response.context['action_form'])
- response = self.client.get(changelist_url + '?%s' % IS_POPUP_VAR)
- self.assertIsNone(response.context['action_form'])
+ self.assertIsNotNone(response.context["action_form"])
+ response = self.client.get(changelist_url + "?%s" % IS_POPUP_VAR)
+ self.assertIsNone(response.context["action_form"])
def test_popup_template_response_on_add(self):
"""
@@ -342,78 +404,90 @@ action)</option>
easy customization.
"""
response = self.client.post(
- reverse('admin:admin_views_actor_add') + '?%s=1' % IS_POPUP_VAR,
- {'name': 'Troy McClure', 'age': '55', IS_POPUP_VAR: '1'}
+ reverse("admin:admin_views_actor_add") + "?%s=1" % IS_POPUP_VAR,
+ {"name": "Troy McClure", "age": "55", IS_POPUP_VAR: "1"},
)
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.template_name, [
- 'admin/admin_views/actor/popup_response.html',
- 'admin/admin_views/popup_response.html',
- 'admin/popup_response.html',
- ])
- self.assertTemplateUsed(response, 'admin/popup_response.html')
+ self.assertEqual(
+ response.template_name,
+ [
+ "admin/admin_views/actor/popup_response.html",
+ "admin/admin_views/popup_response.html",
+ "admin/popup_response.html",
+ ],
+ )
+ self.assertTemplateUsed(response, "admin/popup_response.html")
def test_popup_template_response_on_change(self):
- instance = Actor.objects.create(name='David Tennant', age=45)
+ instance = Actor.objects.create(name="David Tennant", age=45)
response = self.client.post(
- reverse('admin:admin_views_actor_change', args=(instance.pk,)) + '?%s=1' % IS_POPUP_VAR,
- {'name': 'David Tennant', 'age': '46', IS_POPUP_VAR: '1'}
+ reverse("admin:admin_views_actor_change", args=(instance.pk,))
+ + "?%s=1" % IS_POPUP_VAR,
+ {"name": "David Tennant", "age": "46", IS_POPUP_VAR: "1"},
)
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.template_name, [
- 'admin/admin_views/actor/popup_response.html',
- 'admin/admin_views/popup_response.html',
- 'admin/popup_response.html',
- ])
- self.assertTemplateUsed(response, 'admin/popup_response.html')
+ self.assertEqual(
+ response.template_name,
+ [
+ "admin/admin_views/actor/popup_response.html",
+ "admin/admin_views/popup_response.html",
+ "admin/popup_response.html",
+ ],
+ )
+ self.assertTemplateUsed(response, "admin/popup_response.html")
def test_popup_template_response_on_delete(self):
- instance = Actor.objects.create(name='David Tennant', age=45)
+ instance = Actor.objects.create(name="David Tennant", age=45)
response = self.client.post(
- reverse('admin:admin_views_actor_delete', args=(instance.pk,)) + '?%s=1' % IS_POPUP_VAR,
- {IS_POPUP_VAR: '1'}
+ reverse("admin:admin_views_actor_delete", args=(instance.pk,))
+ + "?%s=1" % IS_POPUP_VAR,
+ {IS_POPUP_VAR: "1"},
)
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.template_name, [
- 'admin/admin_views/actor/popup_response.html',
- 'admin/admin_views/popup_response.html',
- 'admin/popup_response.html',
- ])
- self.assertTemplateUsed(response, 'admin/popup_response.html')
+ self.assertEqual(
+ response.template_name,
+ [
+ "admin/admin_views/actor/popup_response.html",
+ "admin/admin_views/popup_response.html",
+ "admin/popup_response.html",
+ ],
+ )
+ self.assertTemplateUsed(response, "admin/popup_response.html")
def test_popup_template_escaping(self):
- popup_response_data = json.dumps({
- 'new_value': 'new_value\\',
- 'obj': 'obj\\',
- 'value': 'value\\',
- })
+ popup_response_data = json.dumps(
+ {
+ "new_value": "new_value\\",
+ "obj": "obj\\",
+ "value": "value\\",
+ }
+ )
context = {
- 'popup_response_data': popup_response_data,
+ "popup_response_data": popup_response_data,
}
- output = render_to_string('admin/popup_response.html', context)
- self.assertIn(
- r'&quot;value\\&quot;', output
- )
- self.assertIn(
- r'&quot;new_value\\&quot;', output
- )
- self.assertIn(
- r'&quot;obj\\&quot;', output
- )
+ output = render_to_string("admin/popup_response.html", context)
+ self.assertIn(r"&quot;value\\&quot;", output)
+ self.assertIn(r"&quot;new_value\\&quot;", output)
+ self.assertIn(r"&quot;obj\\&quot;", output)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminActionsPermissionTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.s1 = ExternalSubscriber.objects.create(name='John Doe', email='john@example.org')
- cls.s2 = Subscriber.objects.create(name='Max Mustermann', email='max@example.org')
+ cls.s1 = ExternalSubscriber.objects.create(
+ name="John Doe", email="john@example.org"
+ )
+ cls.s2 = Subscriber.objects.create(
+ name="Max Mustermann", email="max@example.org"
+ )
cls.user = User.objects.create_user(
- username='user', password='secret', email='user@example.com',
+ username="user",
+ password="secret",
+ email="user@example.com",
is_staff=True,
)
- permission = Permission.objects.get(codename='change_subscriber')
+ permission = Permission.objects.get(codename="change_subscriber")
cls.user.user_permissions.add(permission)
def setUp(self):
@@ -426,25 +500,27 @@ class AdminActionsPermissionTests(TestCase):
"""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'delete_selected',
+ "action": "delete_selected",
}
- url = reverse('admin:admin_views_subscriber_changelist')
+ url = reverse("admin:admin_views_subscriber_changelist")
response = self.client.post(url, action_data)
self.assertRedirects(response, url, fetch_redirect_response=False)
response = self.client.get(response.url)
- self.assertContains(response, 'No action selected.')
+ self.assertContains(response, "No action selected.")
def test_model_admin_no_delete_permission_externalsubscriber(self):
"""
Permission is denied if the user doesn't have delete permission for a
related model (ExternalSubscriber).
"""
- permission = Permission.objects.get(codename='delete_subscriber')
+ permission = Permission.objects.get(codename="delete_subscriber")
self.user.user_permissions.add(permission)
delete_confirmation_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
- 'action': 'delete_selected',
- 'post': 'yes',
+ "action": "delete_selected",
+ "post": "yes",
}
- response = self.client.post(reverse('admin:admin_views_subscriber_changelist'), delete_confirmation_data)
+ response = self.client.post(
+ reverse("admin:admin_views_subscriber_changelist"), delete_confirmation_data
+ )
self.assertEqual(response.status_code, 403)
diff --git a/tests/admin_views/test_adminsite.py b/tests/admin_views/test_adminsite.py
index 4874bc48c8..68a32567d8 100644
--- a/tests/admin_views/test_adminsite.py
+++ b/tests/admin_views/test_adminsite.py
@@ -12,71 +12,76 @@ site.register(User)
site.register(Article)
urlpatterns = [
- path('test_admin/admin/', site.urls),
+ path("test_admin/admin/", site.urls),
]
-@override_settings(ROOT_URLCONF='admin_views.test_adminsite')
+@override_settings(ROOT_URLCONF="admin_views.test_adminsite")
class SiteEachContextTest(TestCase):
"""
Check each_context contains the documented variables and that available_apps context
variable structure is the expected one.
"""
+
request_factory = RequestFactory()
@classmethod
def setUpTestData(cls):
- cls.u1 = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.u1 = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
- request = self.request_factory.get(reverse('test_adminsite:index'))
+ request = self.request_factory.get(reverse("test_adminsite:index"))
request.user = self.u1
self.ctx = site.each_context(request)
def test_each_context(self):
ctx = self.ctx
- self.assertEqual(ctx['site_header'], 'Django administration')
- self.assertEqual(ctx['site_title'], 'Django site admin')
- self.assertEqual(ctx['site_url'], '/')
- self.assertIs(ctx['has_permission'], True)
+ self.assertEqual(ctx["site_header"], "Django administration")
+ self.assertEqual(ctx["site_title"], "Django site admin")
+ self.assertEqual(ctx["site_url"], "/")
+ self.assertIs(ctx["has_permission"], True)
def test_each_context_site_url_with_script_name(self):
- request = self.request_factory.get(reverse('test_adminsite:index'), SCRIPT_NAME='/my-script-name/')
+ request = self.request_factory.get(
+ reverse("test_adminsite:index"), SCRIPT_NAME="/my-script-name/"
+ )
request.user = self.u1
- self.assertEqual(site.each_context(request)['site_url'], '/my-script-name/')
+ self.assertEqual(site.each_context(request)["site_url"], "/my-script-name/")
def test_available_apps(self):
ctx = self.ctx
- apps = ctx['available_apps']
+ apps = ctx["available_apps"]
# we have registered two models from two different apps
self.assertEqual(len(apps), 2)
# admin_views.Article
admin_views = apps[0]
- self.assertEqual(admin_views['app_label'], 'admin_views')
- self.assertEqual(len(admin_views['models']), 1)
- article = admin_views['models'][0]
- self.assertEqual(article['object_name'], 'Article')
- self.assertEqual(article['model'], Article)
+ self.assertEqual(admin_views["app_label"], "admin_views")
+ self.assertEqual(len(admin_views["models"]), 1)
+ article = admin_views["models"][0]
+ self.assertEqual(article["object_name"], "Article")
+ self.assertEqual(article["model"], Article)
# auth.User
auth = apps[1]
- self.assertEqual(auth['app_label'], 'auth')
- self.assertEqual(len(auth['models']), 1)
- user = auth['models'][0]
- self.assertEqual(user['object_name'], 'User')
- self.assertEqual(user['model'], User)
+ self.assertEqual(auth["app_label"], "auth")
+ self.assertEqual(len(auth["models"]), 1)
+ user = auth["models"][0]
+ self.assertEqual(user["object_name"], "User")
+ self.assertEqual(user["model"], User)
- self.assertEqual(auth['app_url'], '/test_admin/admin/auth/')
- self.assertIs(auth['has_module_perms'], True)
+ self.assertEqual(auth["app_url"], "/test_admin/admin/auth/")
+ self.assertIs(auth["has_module_perms"], True)
- self.assertIn('perms', user)
- self.assertIs(user['perms']['add'], True)
- self.assertIs(user['perms']['change'], True)
- self.assertIs(user['perms']['delete'], True)
- self.assertEqual(user['admin_url'], '/test_admin/admin/auth/user/')
- self.assertEqual(user['add_url'], '/test_admin/admin/auth/user/add/')
- self.assertEqual(user['name'], 'Users')
+ self.assertIn("perms", user)
+ self.assertIs(user["perms"]["add"], True)
+ self.assertIs(user["perms"]["change"], True)
+ self.assertIs(user["perms"]["delete"], True)
+ self.assertEqual(user["admin_url"], "/test_admin/admin/auth/user/")
+ self.assertEqual(user["add_url"], "/test_admin/admin/auth/user/add/")
+ self.assertEqual(user["name"], "Users")
class SiteActionsTests(SimpleTestCase):
@@ -86,11 +91,12 @@ class SiteActionsTests(SimpleTestCase):
def test_add_action(self):
def test_action():
pass
+
self.site.add_action(test_action)
- self.assertEqual(self.site.get_action('test_action'), test_action)
+ self.assertEqual(self.site.get_action("test_action"), test_action)
def test_disable_action(self):
- action_name = 'delete_selected'
+ action_name = "delete_selected"
self.assertEqual(self.site._actions[action_name], delete_selected)
self.site.disable_action(action_name)
with self.assertRaises(KeyError):
@@ -98,7 +104,7 @@ class SiteActionsTests(SimpleTestCase):
def test_get_action(self):
"""AdminSite.get_action() returns an action even if it's disabled."""
- action_name = 'delete_selected'
+ action_name = "delete_selected"
self.assertEqual(self.site.get_action(action_name), delete_selected)
self.site.disable_action(action_name)
self.assertEqual(self.site.get_action(action_name), delete_selected)
diff --git a/tests/admin_views/test_autocomplete_view.py b/tests/admin_views/test_autocomplete_view.py
index dfaba42009..febddc1547 100644
--- a/tests/admin_views/test_autocomplete_view.py
+++ b/tests/admin_views/test_autocomplete_view.py
@@ -14,8 +14,18 @@ from django.urls import reverse, reverse_lazy
from .admin import AnswerAdmin, QuestionAdmin
from .models import (
- Answer, Author, Authorship, Bonus, Book, Employee, Manager, Parent,
- PKChild, Question, Toy, WorkHour,
+ Answer,
+ Author,
+ Authorship,
+ Bonus,
+ Book,
+ Employee,
+ Manager,
+ Parent,
+ PKChild,
+ Question,
+ Toy,
+ WorkHour,
)
from .tests import AdminViewBasicTestCase
@@ -23,30 +33,30 @@ PAGINATOR_SIZE = AutocompleteJsonView.paginate_by
class AuthorAdmin(admin.ModelAdmin):
- ordering = ['id']
- search_fields = ['id']
+ ordering = ["id"]
+ search_fields = ["id"]
class AuthorshipInline(admin.TabularInline):
model = Authorship
- autocomplete_fields = ['author']
+ autocomplete_fields = ["author"]
class BookAdmin(admin.ModelAdmin):
inlines = [AuthorshipInline]
-site = admin.AdminSite(name='autocomplete_admin')
+site = admin.AdminSite(name="autocomplete_admin")
site.register(Question, QuestionAdmin)
site.register(Answer, AnswerAdmin)
site.register(Author, AuthorAdmin)
site.register(Book, BookAdmin)
-site.register(Employee, search_fields=['name'])
-site.register(WorkHour, autocomplete_fields=['employee'])
-site.register(Manager, search_fields=['name'])
-site.register(Bonus, autocomplete_fields=['recipient'])
-site.register(PKChild, search_fields=['name'])
-site.register(Toy, autocomplete_fields=['child'])
+site.register(Employee, search_fields=["name"])
+site.register(WorkHour, autocomplete_fields=["employee"])
+site.register(Manager, search_fields=["name"])
+site.register(Bonus, autocomplete_fields=["recipient"])
+site.register(PKChild, search_fields=["name"])
+site.register(Toy, autocomplete_fields=["child"])
@contextmanager
@@ -63,70 +73,87 @@ def model_admin(model, model_admin, admin_site=site):
class AutocompleteJsonViewTests(AdminViewBasicTestCase):
- as_view_args = {'admin_site': site}
+ as_view_args = {"admin_site": site}
opts = {
- 'app_label': Answer._meta.app_label,
- 'model_name': Answer._meta.model_name,
- 'field_name': 'question'
+ "app_label": Answer._meta.app_label,
+ "model_name": Answer._meta.model_name,
+ "field_name": "question",
}
factory = RequestFactory()
- url = reverse_lazy('autocomplete_admin:autocomplete')
+ url = reverse_lazy("autocomplete_admin:autocomplete")
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user(
- username='user', password='secret',
- email='user@example.com', is_staff=True,
+ username="user",
+ password="secret",
+ email="user@example.com",
+ is_staff=True,
)
super().setUpTestData()
def test_success(self):
- q = Question.objects.create(question='Is this a question?')
- request = self.factory.get(self.url, {'term': 'is', **self.opts})
+ q = Question.objects.create(question="Is this a question?")
+ request = self.factory.get(self.url, {"term": "is", **self.opts})
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.pk), 'text': q.question}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(q.pk), "text": q.question}],
+ "pagination": {"more": False},
+ },
+ )
def test_custom_to_field(self):
- q = Question.objects.create(question='Is this a question?')
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'question_with_to_field'})
+ q = Question.objects.create(question="Is this a question?")
+ request = self.factory.get(
+ self.url,
+ {"term": "is", **self.opts, "field_name": "question_with_to_field"},
+ )
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.uuid), 'text': q.question}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(q.uuid), "text": q.question}],
+ "pagination": {"more": False},
+ },
+ )
def test_custom_to_field_permission_denied(self):
- Question.objects.create(question='Is this a question?')
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'question_with_to_field'})
+ Question.objects.create(question="Is this a question?")
+ request = self.factory.get(
+ self.url,
+ {"term": "is", **self.opts, "field_name": "question_with_to_field"},
+ )
request.user = self.user
with self.assertRaises(PermissionDenied):
AutocompleteJsonView.as_view(**self.as_view_args)(request)
def test_custom_to_field_custom_pk(self):
- q = Question.objects.create(question='Is this a question?')
+ q = Question.objects.create(question="Is this a question?")
opts = {
- 'app_label': Question._meta.app_label,
- 'model_name': Question._meta.model_name,
- 'field_name': 'related_questions',
+ "app_label": Question._meta.app_label,
+ "model_name": Question._meta.model_name,
+ "field_name": "related_questions",
}
- request = self.factory.get(self.url, {'term': 'is', **opts})
+ request = self.factory.get(self.url, {"term": "is", **opts})
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.big_id), 'text': q.question}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(q.big_id), "text": q.question}],
+ "pagination": {"more": False},
+ },
+ )
def test_to_field_resolution_with_mti(self):
"""
@@ -134,59 +161,75 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase):
MTI. Tests for single and multi-level cases.
"""
tests = [
- (Employee, WorkHour, 'employee'),
- (Manager, Bonus, 'recipient'),
+ (Employee, WorkHour, "employee"),
+ (Manager, Bonus, "recipient"),
]
for Target, Remote, related_name in tests:
- with self.subTest(target_model=Target, remote_model=Remote, related_name=related_name):
- o = Target.objects.create(name="Frida Kahlo", gender=2, code="painter", alive=False)
+ with self.subTest(
+ target_model=Target, remote_model=Remote, related_name=related_name
+ ):
+ o = Target.objects.create(
+ name="Frida Kahlo", gender=2, code="painter", alive=False
+ )
opts = {
- 'app_label': Remote._meta.app_label,
- 'model_name': Remote._meta.model_name,
- 'field_name': related_name,
+ "app_label": Remote._meta.app_label,
+ "model_name": Remote._meta.model_name,
+ "field_name": related_name,
}
- request = self.factory.get(self.url, {'term': 'frida', **opts})
+ request = self.factory.get(self.url, {"term": "frida", **opts})
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(o.pk), 'text': o.name}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(o.pk), "text": o.name}],
+ "pagination": {"more": False},
+ },
+ )
def test_to_field_resolution_with_fk_pk(self):
p = Parent.objects.create(name="Bertie")
c = PKChild.objects.create(parent=p, name="Anna")
opts = {
- 'app_label': Toy._meta.app_label,
- 'model_name': Toy._meta.model_name,
- 'field_name': 'child',
+ "app_label": Toy._meta.app_label,
+ "model_name": Toy._meta.model_name,
+ "field_name": "child",
}
- request = self.factory.get(self.url, {'term': 'anna', **opts})
+ request = self.factory.get(self.url, {"term": "anna", **opts})
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(c.pk), 'text': c.name}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(c.pk), "text": c.name}],
+ "pagination": {"more": False},
+ },
+ )
def test_field_does_not_exist(self):
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'does_not_exist'})
+ request = self.factory.get(
+ self.url, {"term": "is", **self.opts, "field_name": "does_not_exist"}
+ )
request.user = self.superuser
with self.assertRaises(PermissionDenied):
AutocompleteJsonView.as_view(**self.as_view_args)(request)
def test_field_no_related_field(self):
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'answer'})
+ request = self.factory.get(
+ self.url, {"term": "is", **self.opts, "field_name": "answer"}
+ )
request.user = self.superuser
with self.assertRaises(PermissionDenied):
AutocompleteJsonView.as_view(**self.as_view_args)(request)
def test_field_does_not_allowed(self):
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'related_questions'})
+ request = self.factory.get(
+ self.url, {"term": "is", **self.opts, "field_name": "related_questions"}
+ )
request.user = self.superuser
with self.assertRaises(PermissionDenied):
AutocompleteJsonView.as_view(**self.as_view_args)(request)
@@ -194,23 +237,29 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase):
def test_limit_choices_to(self):
# Answer.question_with_to_field defines limit_choices_to to "those not
# starting with 'not'".
- q = Question.objects.create(question='Is this a question?')
- Question.objects.create(question='Not a question.')
- request = self.factory.get(self.url, {'term': 'is', **self.opts, 'field_name': 'question_with_to_field'})
+ q = Question.objects.create(question="Is this a question?")
+ Question.objects.create(question="Not a question.")
+ request = self.factory.get(
+ self.url,
+ {"term": "is", **self.opts, "field_name": "question_with_to_field"},
+ )
request.user = self.superuser
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.uuid), 'text': q.question}],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [{"id": str(q.uuid), "text": q.question}],
+ "pagination": {"more": False},
+ },
+ )
def test_must_be_logged_in(self):
- response = self.client.get(self.url, {'term': '', **self.opts})
+ response = self.client.get(self.url, {"term": "", **self.opts})
self.assertEqual(response.status_code, 200)
self.client.logout()
- response = self.client.get(self.url, {'term': '', **self.opts})
+ response = self.client.get(self.url, {"term": "", **self.opts})
self.assertEqual(response.status_code, 302)
def test_has_view_or_change_permission_required(self):
@@ -218,16 +267,16 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase):
Users require the change permission for the related model to the
autocomplete view for it.
"""
- request = self.factory.get(self.url, {'term': 'is', **self.opts})
+ request = self.factory.get(self.url, {"term": "is", **self.opts})
request.user = self.user
with self.assertRaises(PermissionDenied):
AutocompleteJsonView.as_view(**self.as_view_args)(request)
- for permission in ('view', 'change'):
+ for permission in ("view", "change"):
with self.subTest(permission=permission):
self.user.user_permissions.clear()
p = Permission.objects.get(
content_type=ContentType.objects.get_for_model(Question),
- codename='%s_question' % permission,
+ codename="%s_question" % permission,
)
self.user.user_permissions.add(p)
request.user = User.objects.get(pk=self.user.pk)
@@ -239,106 +288,134 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase):
Searching across model relations use QuerySet.distinct() to avoid
duplicates.
"""
- q1 = Question.objects.create(question='question 1')
- q2 = Question.objects.create(question='question 2')
+ q1 = Question.objects.create(question="question 1")
+ q2 = Question.objects.create(question="question 2")
q2.related_questions.add(q1)
- q3 = Question.objects.create(question='question 3')
+ q3 = Question.objects.create(question="question 3")
q3.related_questions.add(q1)
- request = self.factory.get(self.url, {'term': 'question', **self.opts})
+ request = self.factory.get(self.url, {"term": "question", **self.opts})
request.user = self.superuser
class DistinctQuestionAdmin(QuestionAdmin):
- search_fields = ['related_questions__question', 'question']
+ search_fields = ["related_questions__question", "question"]
with model_admin(Question, DistinctQuestionAdmin):
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(len(data['results']), 3)
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(len(data["results"]), 3)
def test_missing_search_fields(self):
class EmptySearchAdmin(QuestionAdmin):
search_fields = []
with model_admin(Question, EmptySearchAdmin):
- msg = 'EmptySearchAdmin must have search_fields for the autocomplete_view.'
+ msg = "EmptySearchAdmin must have search_fields for the autocomplete_view."
with self.assertRaisesMessage(Http404, msg):
- site.autocomplete_view(self.factory.get(self.url, {'term': '', **self.opts}))
+ site.autocomplete_view(
+ self.factory.get(self.url, {"term": "", **self.opts})
+ )
def test_get_paginator(self):
"""Search results are paginated."""
+
class PKOrderingQuestionAdmin(QuestionAdmin):
- ordering = ['pk']
+ ordering = ["pk"]
- Question.objects.bulk_create(Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10))
+ Question.objects.bulk_create(
+ Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10)
+ )
# The first page of results.
- request = self.factory.get(self.url, {'term': '', **self.opts})
+ request = self.factory.get(self.url, {"term": "", **self.opts})
request.user = self.superuser
with model_admin(Question, PKOrderingQuestionAdmin):
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.pk), 'text': q.question} for q in Question.objects.all()[:PAGINATOR_SIZE]],
- 'pagination': {'more': True},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [
+ {"id": str(q.pk), "text": q.question}
+ for q in Question.objects.all()[:PAGINATOR_SIZE]
+ ],
+ "pagination": {"more": True},
+ },
+ )
# The second page of results.
- request = self.factory.get(self.url, {'term': '', 'page': '2', **self.opts})
+ request = self.factory.get(self.url, {"term": "", "page": "2", **self.opts})
request.user = self.superuser
with model_admin(Question, PKOrderingQuestionAdmin):
response = AutocompleteJsonView.as_view(**self.as_view_args)(request)
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [{'id': str(q.pk), 'text': q.question} for q in Question.objects.all()[PAGINATOR_SIZE:]],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [
+ {"id": str(q.pk), "text": q.question}
+ for q in Question.objects.all()[PAGINATOR_SIZE:]
+ ],
+ "pagination": {"more": False},
+ },
+ )
def test_serialize_result(self):
class AutocompleteJsonSerializeResultView(AutocompleteJsonView):
def serialize_result(self, obj, to_field_name):
return {
**super().serialize_result(obj, to_field_name),
- 'posted': str(obj.posted),
+ "posted": str(obj.posted),
}
- Question.objects.create(question='Question 1', posted=datetime.date(2021, 8, 9))
- Question.objects.create(question='Question 2', posted=datetime.date(2021, 8, 7))
- request = self.factory.get(self.url, {'term': 'question', **self.opts})
+ Question.objects.create(question="Question 1", posted=datetime.date(2021, 8, 9))
+ Question.objects.create(question="Question 2", posted=datetime.date(2021, 8, 7))
+ request = self.factory.get(self.url, {"term": "question", **self.opts})
request.user = self.superuser
- response = AutocompleteJsonSerializeResultView.as_view(**self.as_view_args)(request)
+ response = AutocompleteJsonSerializeResultView.as_view(**self.as_view_args)(
+ request
+ )
self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data, {
- 'results': [
- {'id': str(q.pk), 'text': q.question, 'posted': str(q.posted)}
- for q in Question.objects.order_by('-posted')
- ],
- 'pagination': {'more': False},
- })
+ data = json.loads(response.content.decode("utf-8"))
+ self.assertEqual(
+ data,
+ {
+ "results": [
+ {"id": str(q.pk), "text": q.question, "posted": str(q.posted)}
+ for q in Question.objects.order_by("-posted")
+ ],
+ "pagination": {"more": False},
+ },
+ )
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class SeleniumTests(AdminSeleniumTestCase):
- available_apps = ['admin_views'] + AdminSeleniumTestCase.available_apps
+ available_apps = ["admin_views"] + AdminSeleniumTestCase.available_apps
def setUp(self):
self.superuser = User.objects.create_superuser(
- username='super', password='secret', email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
+ )
+ self.admin_login(
+ username="super",
+ password="secret",
+ login_url=reverse("autocomplete_admin:index"),
)
- self.admin_login(username='super', password='secret', login_url=reverse('autocomplete_admin:index'))
@contextmanager
def select2_ajax_wait(self, timeout=10):
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
+
yield
with self.disable_implicit_wait():
try:
loading_element = self.selenium.find_element(
- By.CSS_SELECTOR,
- 'li.select2-results__option.loading-results'
+ By.CSS_SELECTOR, "li.select2-results__option.loading-results"
)
except NoSuchElementException:
pass
@@ -349,109 +426,146 @@ class SeleniumTests(AdminSeleniumTestCase):
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
- self.selenium.get(self.live_server_url + reverse('autocomplete_admin:admin_views_answer_add'))
- elem = self.selenium.find_element(By.CSS_SELECTOR, '.select2-selection')
+
+ self.selenium.get(
+ self.live_server_url + reverse("autocomplete_admin:admin_views_answer_add")
+ )
+ elem = self.selenium.find_element(By.CSS_SELECTOR, ".select2-selection")
elem.click() # Open the autocomplete dropdown.
- results = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results')
+ results = self.selenium.find_element(By.CSS_SELECTOR, ".select2-results")
self.assertTrue(results.is_displayed())
- option = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results__option')
- self.assertEqual(option.text, 'No results found')
+ option = self.selenium.find_element(By.CSS_SELECTOR, ".select2-results__option")
+ self.assertEqual(option.text, "No results found")
elem.click() # Close the autocomplete dropdown.
- q1 = Question.objects.create(question='Who am I?')
- Question.objects.bulk_create(Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10))
+ q1 = Question.objects.create(question="Who am I?")
+ Question.objects.bulk_create(
+ Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10)
+ )
elem.click() # Reopen the dropdown now that some objects exist.
- result_container = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results')
+ result_container = self.selenium.find_element(
+ By.CSS_SELECTOR, ".select2-results"
+ )
self.assertTrue(result_container.is_displayed())
# PAGINATOR_SIZE results and "Loading more results".
- self.assertCountSeleniumElements('.select2-results__option', PAGINATOR_SIZE + 1, root_element=result_container)
- search = self.selenium.find_element(By.CSS_SELECTOR, '.select2-search__field')
+ self.assertCountSeleniumElements(
+ ".select2-results__option",
+ PAGINATOR_SIZE + 1,
+ root_element=result_container,
+ )
+ search = self.selenium.find_element(By.CSS_SELECTOR, ".select2-search__field")
# Load next page of results by scrolling to the bottom of the list.
with self.select2_ajax_wait():
for _ in range(PAGINATOR_SIZE + 1):
search.send_keys(Keys.ARROW_DOWN)
# All objects are now loaded.
self.assertCountSeleniumElements(
- '.select2-results__option',
+ ".select2-results__option",
PAGINATOR_SIZE + 11,
root_element=result_container,
)
# Limit the results with the search field.
with self.select2_ajax_wait():
- search.send_keys('Who')
+ search.send_keys("Who")
# Ajax request is delayed.
self.assertTrue(result_container.is_displayed())
self.assertCountSeleniumElements(
- '.select2-results__option',
+ ".select2-results__option",
PAGINATOR_SIZE + 12,
root_element=result_container,
)
self.assertTrue(result_container.is_displayed())
- self.assertCountSeleniumElements('.select2-results__option', 1, root_element=result_container)
+ self.assertCountSeleniumElements(
+ ".select2-results__option", 1, root_element=result_container
+ )
# Select the result.
search.send_keys(Keys.RETURN)
- select = Select(self.selenium.find_element(By.ID, 'id_question'))
- self.assertEqual(select.first_selected_option.get_attribute('value'), str(q1.pk))
+ select = Select(self.selenium.find_element(By.ID, "id_question"))
+ self.assertEqual(
+ select.first_selected_option.get_attribute("value"), str(q1.pk)
+ )
def test_select_multiple(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
- self.selenium.get(self.live_server_url + reverse('autocomplete_admin:admin_views_question_add'))
- elem = self.selenium.find_element(By.CSS_SELECTOR, '.select2-selection')
+
+ self.selenium.get(
+ self.live_server_url
+ + reverse("autocomplete_admin:admin_views_question_add")
+ )
+ elem = self.selenium.find_element(By.CSS_SELECTOR, ".select2-selection")
elem.click() # Open the autocomplete dropdown.
- results = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results')
+ results = self.selenium.find_element(By.CSS_SELECTOR, ".select2-results")
self.assertTrue(results.is_displayed())
- option = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results__option')
- self.assertEqual(option.text, 'No results found')
+ option = self.selenium.find_element(By.CSS_SELECTOR, ".select2-results__option")
+ self.assertEqual(option.text, "No results found")
elem.click() # Close the autocomplete dropdown.
- Question.objects.create(question='Who am I?')
- Question.objects.bulk_create(Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10))
+ Question.objects.create(question="Who am I?")
+ Question.objects.bulk_create(
+ Question(question=str(i)) for i in range(PAGINATOR_SIZE + 10)
+ )
elem.click() # Reopen the dropdown now that some objects exist.
- result_container = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results')
+ result_container = self.selenium.find_element(
+ By.CSS_SELECTOR, ".select2-results"
+ )
self.assertTrue(result_container.is_displayed())
- self.assertCountSeleniumElements('.select2-results__option', PAGINATOR_SIZE + 1, root_element=result_container)
- search = self.selenium.find_element(By.CSS_SELECTOR, '.select2-search__field')
+ self.assertCountSeleniumElements(
+ ".select2-results__option",
+ PAGINATOR_SIZE + 1,
+ root_element=result_container,
+ )
+ search = self.selenium.find_element(By.CSS_SELECTOR, ".select2-search__field")
# Load next page of results by scrolling to the bottom of the list.
with self.select2_ajax_wait():
for _ in range(PAGINATOR_SIZE + 1):
search.send_keys(Keys.ARROW_DOWN)
- self.assertCountSeleniumElements('.select2-results__option', 31, root_element=result_container)
+ self.assertCountSeleniumElements(
+ ".select2-results__option", 31, root_element=result_container
+ )
# Limit the results with the search field.
with self.select2_ajax_wait():
- search.send_keys('Who')
+ search.send_keys("Who")
# Ajax request is delayed.
self.assertTrue(result_container.is_displayed())
- self.assertCountSeleniumElements('.select2-results__option', 32, root_element=result_container)
+ self.assertCountSeleniumElements(
+ ".select2-results__option", 32, root_element=result_container
+ )
self.assertTrue(result_container.is_displayed())
- self.assertCountSeleniumElements('.select2-results__option', 1, root_element=result_container)
+ self.assertCountSeleniumElements(
+ ".select2-results__option", 1, root_element=result_container
+ )
# Select the result.
search.send_keys(Keys.RETURN)
# Reopen the dropdown and add the first result to the selection.
elem.click()
search.send_keys(Keys.ARROW_DOWN)
search.send_keys(Keys.RETURN)
- select = Select(self.selenium.find_element(By.ID, 'id_related_questions'))
+ select = Select(self.selenium.find_element(By.ID, "id_related_questions"))
self.assertEqual(len(select.all_selected_options), 2)
def test_inline_add_another_widgets(self):
from selenium.webdriver.common.by import By
def assertNoResults(row):
- elem = row.find_element(By.CSS_SELECTOR, '.select2-selection')
+ elem = row.find_element(By.CSS_SELECTOR, ".select2-selection")
elem.click() # Open the autocomplete dropdown.
- results = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results')
+ results = self.selenium.find_element(By.CSS_SELECTOR, ".select2-results")
self.assertTrue(results.is_displayed())
- option = self.selenium.find_element(By.CSS_SELECTOR, '.select2-results__option')
- self.assertEqual(option.text, 'No results found')
+ option = self.selenium.find_element(
+ By.CSS_SELECTOR, ".select2-results__option"
+ )
+ self.assertEqual(option.text, "No results found")
# Autocomplete works in rows present when the page loads.
- self.selenium.get(self.live_server_url + reverse('autocomplete_admin:admin_views_book_add'))
- rows = self.selenium.find_elements(By.CSS_SELECTOR, '.dynamic-authorship_set')
+ self.selenium.get(
+ self.live_server_url + reverse("autocomplete_admin:admin_views_book_add")
+ )
+ rows = self.selenium.find_elements(By.CSS_SELECTOR, ".dynamic-authorship_set")
self.assertEqual(len(rows), 3)
assertNoResults(rows[0])
# Autocomplete works in rows added using the "Add another" button.
- self.selenium.find_element(By.LINK_TEXT, 'Add another Authorship').click()
- rows = self.selenium.find_elements(By.CSS_SELECTOR, '.dynamic-authorship_set')
+ self.selenium.find_element(By.LINK_TEXT, "Add another Authorship").click()
+ rows = self.selenium.find_elements(By.CSS_SELECTOR, ".dynamic-authorship_set")
self.assertEqual(len(rows), 4)
assertNoResults(rows[-1])
diff --git a/tests/admin_views/test_forms.py b/tests/admin_views/test_forms.py
index f9a56c02af..91d504b4f9 100644
--- a/tests/admin_views/test_forms.py
+++ b/tests/admin_views/test_forms.py
@@ -8,28 +8,35 @@ from .admin import ArticleForm
# To verify that the login form rejects inactive users, use an authentication
# backend that allows them.
-@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend'])
+@override_settings(
+ AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.AllowAllUsersModelBackend"]
+)
class AdminAuthenticationFormTests(TestCase):
@classmethod
def setUpTestData(cls):
- User.objects.create_user(username='inactive', password='password', is_active=False)
+ User.objects.create_user(
+ username="inactive", password="password", is_active=False
+ )
def test_inactive_user(self):
data = {
- 'username': 'inactive',
- 'password': 'password',
+ "username": "inactive",
+ "password": "password",
}
form = AdminAuthenticationForm(None, data)
- self.assertEqual(form.non_field_errors(), ['This account is inactive.'])
+ self.assertEqual(form.non_field_errors(), ["This account is inactive."])
class AdminFormTests(SimpleTestCase):
def test_repr(self):
fieldsets = (
- ('My fields', {
- 'classes': ['collapse'],
- 'fields': ('url', 'title', 'content', 'sites'),
- }),
+ (
+ "My fields",
+ {
+ "classes": ["collapse"],
+ "fields": ("url", "title", "content", "sites"),
+ },
+ ),
)
form = ArticleForm()
admin_form = AdminForm(form, fieldsets, {})
diff --git a/tests/admin_views/test_history_view.py b/tests/admin_views/test_history_view.py
index c8d678476f..ddfdd56ca6 100644
--- a/tests/admin_views/test_history_view.py
+++ b/tests/admin_views/test_history_view.py
@@ -9,13 +9,14 @@ from django.urls import reverse
from .models import City, State
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminHistoryViewTests(TestCase):
-
@classmethod
def setUpTestData(cls):
cls.superuser = User.objects.create_superuser(
- username='super', password='secret', email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
)
def setUp(self):
@@ -26,35 +27,39 @@ class AdminHistoryViewTests(TestCase):
Admin's model history change messages use form labels instead of
field names.
"""
- state = State.objects.create(name='My State Name')
- city = City.objects.create(name='My City Name', state=state)
+ state = State.objects.create(name="My State Name")
+ city = City.objects.create(name="My City Name", state=state)
change_dict = {
- 'name': 'My State Name 2',
- 'nolabel_form_field': True,
- 'city_set-0-name': 'My City name 2',
- 'city_set-0-id': city.pk,
- 'city_set-TOTAL_FORMS': '3',
- 'city_set-INITIAL_FORMS': '1',
- 'city_set-MAX_NUM_FORMS': '0',
+ "name": "My State Name 2",
+ "nolabel_form_field": True,
+ "city_set-0-name": "My City name 2",
+ "city_set-0-id": city.pk,
+ "city_set-TOTAL_FORMS": "3",
+ "city_set-INITIAL_FORMS": "1",
+ "city_set-MAX_NUM_FORMS": "0",
}
- state_change_url = reverse('admin:admin_views_state_change', args=(state.pk,))
+ state_change_url = reverse("admin:admin_views_state_change", args=(state.pk,))
self.client.post(state_change_url, change_dict)
- logentry = LogEntry.objects.filter(content_type__model__iexact='state').latest('id')
+ logentry = LogEntry.objects.filter(content_type__model__iexact="state").latest(
+ "id"
+ )
self.assertEqual(
logentry.get_change_message(),
- 'Changed State name (from form’s Meta.labels), '
- 'nolabel_form_field and not_a_form_field. '
- 'Changed City verbose_name for city “%s”.' % city
+ "Changed State name (from form’s Meta.labels), "
+ "nolabel_form_field and not_a_form_field. "
+ "Changed City verbose_name for city “%s”." % city,
)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class SeleniumTests(AdminSeleniumTestCase):
- available_apps = ['admin_views'] + AdminSeleniumTestCase.available_apps
+ available_apps = ["admin_views"] + AdminSeleniumTestCase.available_apps
def setUp(self):
self.superuser = User.objects.create_superuser(
- username='super', password='secret', email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
)
content_type_pk = ContentType.objects.get_for_model(User).pk
for i in range(1, 1101):
@@ -64,34 +69,38 @@ class SeleniumTests(AdminSeleniumTestCase):
self.superuser.pk,
repr(self.superuser),
CHANGE,
- change_message=f'Changed something {i}',
+ change_message=f"Changed something {i}",
)
self.admin_login(
- username='super', password='secret', login_url=reverse('admin:index'),
+ username="super",
+ password="secret",
+ login_url=reverse("admin:index"),
)
def test_pagination(self):
from selenium.webdriver.common.by import By
- user_history_url = reverse('admin:auth_user_history', args=(self.superuser.pk,))
+ user_history_url = reverse("admin:auth_user_history", args=(self.superuser.pk,))
self.selenium.get(self.live_server_url + user_history_url)
- paginator = self.selenium.find_element(By.CSS_SELECTOR, '.paginator')
+ paginator = self.selenium.find_element(By.CSS_SELECTOR, ".paginator")
self.assertTrue(paginator.is_displayed())
- self.assertIn('%s entries' % LogEntry.objects.count(), paginator.text)
+ self.assertIn("%s entries" % LogEntry.objects.count(), paginator.text)
self.assertIn(str(Paginator.ELLIPSIS), paginator.text)
# The current page.
- current_page_link = self.selenium.find_element(By.CSS_SELECTOR, 'span.this-page')
- self.assertEqual(current_page_link.text, '1')
+ current_page_link = self.selenium.find_element(
+ By.CSS_SELECTOR, "span.this-page"
+ )
+ self.assertEqual(current_page_link.text, "1")
# The last page.
- last_page_link = self.selenium.find_element(By.CSS_SELECTOR, '.end')
- self.assertTrue(last_page_link.text, '20')
+ last_page_link = self.selenium.find_element(By.CSS_SELECTOR, ".end")
+ self.assertTrue(last_page_link.text, "20")
# Select the second page.
- pages = paginator.find_elements(By.TAG_NAME, 'a')
+ pages = paginator.find_elements(By.TAG_NAME, "a")
second_page_link = pages[0]
- self.assertEqual(second_page_link.text, '2')
+ self.assertEqual(second_page_link.text, "2")
second_page_link.click()
- self.assertIn('?p=2', self.selenium.current_url)
- rows = self.selenium.find_elements(By.CSS_SELECTOR, '#change-history tbody tr')
- self.assertIn('Changed something 101', rows[0].text)
- self.assertIn('Changed something 200', rows[-1].text)
+ self.assertIn("?p=2", self.selenium.current_url)
+ rows = self.selenium.find_elements(By.CSS_SELECTOR, "#change-history tbody tr")
+ self.assertIn("Changed something 101", rows[0].text)
+ self.assertIn("Changed something 200", rows[-1].text)
diff --git a/tests/admin_views/test_multidb.py b/tests/admin_views/test_multidb.py
index 7ff1f7f663..da5b6b9a59 100644
--- a/tests/admin_views/test_multidb.py
+++ b/tests/admin_views/test_multidb.py
@@ -17,17 +17,17 @@ class Router:
db_for_write = db_for_read
-site = admin.AdminSite(name='test_adminsite')
+site = admin.AdminSite(name="test_adminsite")
site.register(Book)
urlpatterns = [
- path('admin/', site.urls),
+ path("admin/", site.urls),
]
-@override_settings(ROOT_URLCONF=__name__, DATABASE_ROUTERS=['%s.Router' % __name__])
+@override_settings(ROOT_URLCONF=__name__, DATABASE_ROUTERS=["%s.Router" % __name__])
class MultiDatabaseTests(TestCase):
- databases = {'default', 'other'}
+ databases = {"default", "other"}
@classmethod
def setUpTestData(cls):
@@ -36,44 +36,52 @@ class MultiDatabaseTests(TestCase):
for db in cls.databases:
Router.target_db = db
cls.superusers[db] = User.objects.create_superuser(
- username='admin', password='something', email='test@test.org',
+ username="admin",
+ password="something",
+ email="test@test.org",
)
- b = Book(name='Test Book')
+ b = Book(name="Test Book")
b.save(using=db)
cls.test_book_ids[db] = b.id
- @mock.patch('django.contrib.admin.options.transaction')
+ @mock.patch("django.contrib.admin.options.transaction")
def test_add_view(self, mock):
for db in self.databases:
with self.subTest(db=db):
Router.target_db = db
self.client.force_login(self.superusers[db])
self.client.post(
- reverse('test_adminsite:admin_views_book_add'),
- {'name': 'Foobar: 5th edition'},
+ reverse("test_adminsite:admin_views_book_add"),
+ {"name": "Foobar: 5th edition"},
)
mock.atomic.assert_called_with(using=db)
- @mock.patch('django.contrib.admin.options.transaction')
+ @mock.patch("django.contrib.admin.options.transaction")
def test_change_view(self, mock):
for db in self.databases:
with self.subTest(db=db):
Router.target_db = db
self.client.force_login(self.superusers[db])
self.client.post(
- reverse('test_adminsite:admin_views_book_change', args=[self.test_book_ids[db]]),
- {'name': 'Test Book 2: Test more'},
+ reverse(
+ "test_adminsite:admin_views_book_change",
+ args=[self.test_book_ids[db]],
+ ),
+ {"name": "Test Book 2: Test more"},
)
mock.atomic.assert_called_with(using=db)
- @mock.patch('django.contrib.admin.options.transaction')
+ @mock.patch("django.contrib.admin.options.transaction")
def test_delete_view(self, mock):
for db in self.databases:
with self.subTest(db=db):
Router.target_db = db
self.client.force_login(self.superusers[db])
self.client.post(
- reverse('test_adminsite:admin_views_book_delete', args=[self.test_book_ids[db]]),
- {'post': 'yes'},
+ reverse(
+ "test_adminsite:admin_views_book_delete",
+ args=[self.test_book_ids[db]],
+ ),
+ {"post": "yes"},
)
mock.atomic.assert_called_with(using=db)
diff --git a/tests/admin_views/test_nav_sidebar.py b/tests/admin_views/test_nav_sidebar.py
index 329fe34b28..a58193c550 100644
--- a/tests/admin_views/test_nav_sidebar.py
+++ b/tests/admin_views/test_nav_sidebar.py
@@ -15,165 +15,204 @@ class AdminSiteWithoutSidebar(admin.AdminSite):
enable_nav_sidebar = False
-site_with_sidebar = AdminSiteWithSidebar(name='test_with_sidebar')
-site_without_sidebar = AdminSiteWithoutSidebar(name='test_without_sidebar')
+site_with_sidebar = AdminSiteWithSidebar(name="test_with_sidebar")
+site_without_sidebar = AdminSiteWithoutSidebar(name="test_without_sidebar")
site_with_sidebar.register(User)
site_with_sidebar.register(Héllo)
urlpatterns = [
- path('test_sidebar/admin/', site_with_sidebar.urls),
- path('test_wihout_sidebar/admin/', site_without_sidebar.urls),
+ path("test_sidebar/admin/", site_with_sidebar.urls),
+ path("test_wihout_sidebar/admin/", site_without_sidebar.urls),
]
-@override_settings(ROOT_URLCONF='admin_views.test_nav_sidebar')
+@override_settings(ROOT_URLCONF="admin_views.test_nav_sidebar")
class AdminSidebarTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.superuser = User.objects.create_superuser(
- username='super',
- password='secret',
- email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
)
def setUp(self):
self.client.force_login(self.superuser)
def test_sidebar_not_on_index(self):
- response = self.client.get(reverse('test_with_sidebar:index'))
+ response = self.client.get(reverse("test_with_sidebar:index"))
self.assertContains(response, '<div class="main" id="main">')
self.assertNotContains(response, '<nav class="sticky" id="nav-sidebar">')
def test_sidebar_disabled(self):
- response = self.client.get(reverse('test_without_sidebar:index'))
+ response = self.client.get(reverse("test_without_sidebar:index"))
self.assertNotContains(response, '<nav class="sticky" id="nav-sidebar">')
def test_sidebar_unauthenticated(self):
self.client.logout()
- response = self.client.get(reverse('test_with_sidebar:login'))
+ response = self.client.get(reverse("test_with_sidebar:login"))
self.assertNotContains(response, '<nav class="sticky" id="nav-sidebar">')
def test_sidebar_aria_current_page(self):
- url = reverse('test_with_sidebar:auth_user_changelist')
+ url = reverse("test_with_sidebar:auth_user_changelist")
response = self.client.get(url)
self.assertContains(response, '<nav class="sticky" id="nav-sidebar">')
- self.assertContains(response, '<a href="%s" aria-current="page">Users</a>' % url)
+ self.assertContains(
+ response, '<a href="%s" aria-current="page">Users</a>' % url
+ )
@override_settings(
- 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',
- ],
- },
- }]
+ 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",
+ ],
+ },
+ }
+ ]
)
def test_sidebar_aria_current_page_missing_without_request_context_processor(self):
- url = reverse('test_with_sidebar:auth_user_changelist')
+ url = reverse("test_with_sidebar:auth_user_changelist")
response = self.client.get(url)
self.assertContains(response, '<nav class="sticky" id="nav-sidebar">')
# Does not include aria-current attribute.
self.assertContains(response, '<a href="%s">Users</a>' % url)
- self.assertNotContains(response, 'aria-current')
+ self.assertNotContains(response, "aria-current")
@override_settings(DEBUG=True)
def test_included_app_list_template_context_fully_set(self):
# All context variables should be set when rendering the sidebar.
- url = reverse('test_with_sidebar:auth_user_changelist')
- with self.assertNoLogs('django.template', 'DEBUG'):
+ url = reverse("test_with_sidebar:auth_user_changelist")
+ with self.assertNoLogs("django.template", "DEBUG"):
self.client.get(url)
def test_sidebar_model_name_non_ascii(self):
- url = reverse('test_with_sidebar:admin_views_héllo_changelist')
+ url = reverse("test_with_sidebar:admin_views_héllo_changelist")
response = self.client.get(url)
- self.assertContains(response, '<div class="app-admin_views module current-app">')
+ self.assertContains(
+ response, '<div class="app-admin_views module current-app">'
+ )
self.assertContains(response, '<tr class="model-héllo current-model">')
self.assertContains(
response,
'<th scope="row">'
'<a href="/test_sidebar/admin/admin_views/h%C3%A9llo/" aria-current="page">'
- 'Héllos</a></th>'
+ "Héllos</a></th>",
)
-@override_settings(ROOT_URLCONF='admin_views.test_nav_sidebar')
+@override_settings(ROOT_URLCONF="admin_views.test_nav_sidebar")
class SeleniumTests(AdminSeleniumTestCase):
- available_apps = ['admin_views'] + AdminSeleniumTestCase.available_apps
+ available_apps = ["admin_views"] + AdminSeleniumTestCase.available_apps
def setUp(self):
self.superuser = User.objects.create_superuser(
- username='super',
- password='secret',
- email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
+ )
+ self.admin_login(
+ username="super",
+ password="secret",
+ login_url=reverse("test_with_sidebar:index"),
+ )
+ self.selenium.execute_script(
+ "localStorage.removeItem('django.admin.navSidebarIsOpen')"
)
- self.admin_login(username='super', password='secret', login_url=reverse('test_with_sidebar:index'))
- self.selenium.execute_script("localStorage.removeItem('django.admin.navSidebarIsOpen')")
def test_sidebar_starts_open(self):
from selenium.webdriver.common.by import By
- self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
- main_element = self.selenium.find_element(By.CSS_SELECTOR, '#main')
- self.assertIn('shifted', main_element.get_attribute('class').split())
+
+ self.selenium.get(
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
+ )
+ main_element = self.selenium.find_element(By.CSS_SELECTOR, "#main")
+ self.assertIn("shifted", main_element.get_attribute("class").split())
def test_sidebar_can_be_closed(self):
from selenium.webdriver.common.by import By
- self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
- toggle_button = self.selenium.find_element(By.CSS_SELECTOR, '#toggle-nav-sidebar')
- self.assertEqual(toggle_button.tag_name, 'button')
- self.assertEqual(toggle_button.get_attribute('aria-label'), 'Toggle navigation')
- for link in self.selenium.find_elements(By.CSS_SELECTOR, '#nav-sidebar a'):
- self.assertEqual(link.get_attribute('tabIndex'), '0')
+
+ self.selenium.get(
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
+ )
+ toggle_button = self.selenium.find_element(
+ By.CSS_SELECTOR, "#toggle-nav-sidebar"
+ )
+ self.assertEqual(toggle_button.tag_name, "button")
+ self.assertEqual(toggle_button.get_attribute("aria-label"), "Toggle navigation")
+ for link in self.selenium.find_elements(By.CSS_SELECTOR, "#nav-sidebar a"):
+ self.assertEqual(link.get_attribute("tabIndex"), "0")
toggle_button.click()
# Hidden sidebar is not reachable via keyboard navigation.
- for link in self.selenium.find_elements(By.CSS_SELECTOR, '#nav-sidebar a'):
- self.assertEqual(link.get_attribute('tabIndex'), '-1')
- main_element = self.selenium.find_element(By.CSS_SELECTOR, '#main')
- self.assertNotIn('shifted', main_element.get_attribute('class').split())
+ for link in self.selenium.find_elements(By.CSS_SELECTOR, "#nav-sidebar a"):
+ self.assertEqual(link.get_attribute("tabIndex"), "-1")
+ main_element = self.selenium.find_element(By.CSS_SELECTOR, "#main")
+ self.assertNotIn("shifted", main_element.get_attribute("class").split())
def test_sidebar_state_persists(self):
from selenium.webdriver.common.by import By
- self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
- self.assertIsNone(self.selenium.execute_script("return localStorage.getItem('django.admin.navSidebarIsOpen')"))
- toggle_button = self.selenium.find_element(By.CSS_SELECTOR, '#toggle-nav-sidebar')
+
+ self.selenium.get(
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
+ )
+ self.assertIsNone(
+ self.selenium.execute_script(
+ "return localStorage.getItem('django.admin.navSidebarIsOpen')"
+ )
+ )
+ toggle_button = self.selenium.find_element(
+ By.CSS_SELECTOR, "#toggle-nav-sidebar"
+ )
toggle_button.click()
self.assertEqual(
- self.selenium.execute_script("return localStorage.getItem('django.admin.navSidebarIsOpen')"),
- 'false',
+ self.selenium.execute_script(
+ "return localStorage.getItem('django.admin.navSidebarIsOpen')"
+ ),
+ "false",
)
- self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
- main_element = self.selenium.find_element(By.CSS_SELECTOR, '#main')
- self.assertNotIn('shifted', main_element.get_attribute('class').split())
+ self.selenium.get(
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
+ )
+ main_element = self.selenium.find_element(By.CSS_SELECTOR, "#main")
+ self.assertNotIn("shifted", main_element.get_attribute("class").split())
- toggle_button = self.selenium.find_element(By.CSS_SELECTOR, '#toggle-nav-sidebar')
+ toggle_button = self.selenium.find_element(
+ By.CSS_SELECTOR, "#toggle-nav-sidebar"
+ )
# Hidden sidebar is not reachable via keyboard navigation.
- for link in self.selenium.find_elements(By.CSS_SELECTOR, '#nav-sidebar a'):
- self.assertEqual(link.get_attribute('tabIndex'), '-1')
+ for link in self.selenium.find_elements(By.CSS_SELECTOR, "#nav-sidebar a"):
+ self.assertEqual(link.get_attribute("tabIndex"), "-1")
toggle_button.click()
- for link in self.selenium.find_elements(By.CSS_SELECTOR, '#nav-sidebar a'):
- self.assertEqual(link.get_attribute('tabIndex'), '0')
+ for link in self.selenium.find_elements(By.CSS_SELECTOR, "#nav-sidebar a"):
+ self.assertEqual(link.get_attribute("tabIndex"), "0")
self.assertEqual(
- self.selenium.execute_script("return localStorage.getItem('django.admin.navSidebarIsOpen')"),
- 'true',
+ self.selenium.execute_script(
+ "return localStorage.getItem('django.admin.navSidebarIsOpen')"
+ ),
+ "true",
)
- self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
- main_element = self.selenium.find_element(By.CSS_SELECTOR, '#main')
- self.assertIn('shifted', main_element.get_attribute('class').split())
+ self.selenium.get(
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
+ )
+ main_element = self.selenium.find_element(By.CSS_SELECTOR, "#main")
+ self.assertIn("shifted", main_element.get_attribute("class").split())
def test_sidebar_filter_persists(self):
from selenium.webdriver.common.by import By
+
self.selenium.get(
- self.live_server_url +
- reverse('test_with_sidebar:auth_user_changelist')
+ self.live_server_url + reverse("test_with_sidebar:auth_user_changelist")
)
filter_value_script = (
"return sessionStorage.getItem('django.admin.navSidebarFilterValue')"
)
self.assertIsNone(self.selenium.execute_script(filter_value_script))
- filter_input = self.selenium.find_element(By.CSS_SELECTOR, '#nav-filter')
- filter_input.send_keys('users')
- self.assertEqual(self.selenium.execute_script(filter_value_script), 'users')
+ filter_input = self.selenium.find_element(By.CSS_SELECTOR, "#nav-filter")
+ filter_input.send_keys("users")
+ self.assertEqual(self.selenium.execute_script(filter_value_script), "users")
diff --git a/tests/admin_views/test_templatetags.py b/tests/admin_views/test_templatetags.py
index 14c3fcead5..a13133095b 100644
--- a/tests/admin_views/test_templatetags.py
+++ b/tests/admin_views/test_templatetags.py
@@ -20,24 +20,28 @@ class AdminTemplateTagsTest(AdminViewBasicTestCase):
"""
submit_row template tag should pass whole context.
"""
- request = self.request_factory.get(reverse('admin:auth_user_change', args=[self.superuser.pk]))
+ request = self.request_factory.get(
+ reverse("admin:auth_user_change", args=[self.superuser.pk])
+ )
request.user = self.superuser
admin = UserAdmin(User, site)
- extra_context = {'extra': True}
- response = admin.change_view(request, str(self.superuser.pk), extra_context=extra_context)
+ extra_context = {"extra": True}
+ response = admin.change_view(
+ request, str(self.superuser.pk), extra_context=extra_context
+ )
template_context = submit_row(response.context_data)
- self.assertIs(template_context['extra'], True)
- self.assertIs(template_context['show_save'], True)
+ self.assertIs(template_context["extra"], True)
+ self.assertIs(template_context["show_save"], True)
def test_override_show_save_and_add_another(self):
request = self.request_factory.get(
- reverse('admin:auth_user_change', args=[self.superuser.pk]),
+ reverse("admin:auth_user_change", args=[self.superuser.pk]),
)
request.user = self.superuser
admin = UserAdmin(User, site)
for extra_context, expected_flag in (
({}, True), # Default.
- ({'show_save_and_add_another': False}, False),
+ ({"show_save_and_add_another": False}, False),
):
with self.subTest(show_save_and_add_another=expected_flag):
response = admin.change_view(
@@ -46,7 +50,9 @@ class AdminTemplateTagsTest(AdminViewBasicTestCase):
extra_context=extra_context,
)
template_context = submit_row(response.context_data)
- self.assertIs(template_context['show_save_and_add_another'], expected_flag)
+ self.assertIs(
+ template_context["show_save_and_add_another"], expected_flag
+ )
def test_override_change_form_template_tags(self):
"""
@@ -54,37 +60,43 @@ class AdminTemplateTagsTest(AdminViewBasicTestCase):
admin/app_label/model/template.html.
"""
article = Article.objects.all()[0]
- request = self.request_factory.get(reverse('admin:admin_views_article_change', args=[article.pk]))
+ request = self.request_factory.get(
+ reverse("admin:admin_views_article_change", args=[article.pk])
+ )
request.user = self.superuser
admin = ArticleAdmin(Article, site)
- extra_context = {'show_publish': True, 'extra': True}
- response = admin.change_view(request, str(article.pk), extra_context=extra_context)
+ extra_context = {"show_publish": True, "extra": True}
+ response = admin.change_view(
+ request, str(article.pk), extra_context=extra_context
+ )
response.render()
- self.assertIs(response.context_data['show_publish'], True)
- self.assertIs(response.context_data['extra'], True)
+ self.assertIs(response.context_data["show_publish"], True)
+ self.assertIs(response.context_data["extra"], True)
self.assertContains(response, 'name="_save"')
self.assertContains(response, 'name="_publish"')
- self.assertContains(response, 'override-change_form_object_tools')
- self.assertContains(response, 'override-prepopulated_fields_js')
+ self.assertContains(response, "override-change_form_object_tools")
+ self.assertContains(response, "override-prepopulated_fields_js")
def test_override_change_list_template_tags(self):
"""
admin_list template tags follow the standard search pattern
admin/app_label/model/template.html.
"""
- request = self.request_factory.get(reverse('admin:admin_views_article_changelist'))
+ request = self.request_factory.get(
+ reverse("admin:admin_views_article_changelist")
+ )
request.user = self.superuser
admin = ArticleAdmin(Article, site)
- admin.date_hierarchy = 'date'
- admin.search_fields = ('title', 'content')
+ admin.date_hierarchy = "date"
+ admin.search_fields = ("title", "content")
response = admin.changelist_view(request)
response.render()
- self.assertContains(response, 'override-actions')
- self.assertContains(response, 'override-change_list_object_tools')
- self.assertContains(response, 'override-change_list_results')
- self.assertContains(response, 'override-date_hierarchy')
- self.assertContains(response, 'override-pagination')
- self.assertContains(response, 'override-search_form')
+ self.assertContains(response, "override-actions")
+ self.assertContains(response, "override-change_list_object_tools")
+ self.assertContains(response, "override-change_list_results")
+ self.assertContains(response, "override-date_hierarchy")
+ self.assertContains(response, "override-pagination")
+ self.assertContains(response, "override-search_form")
class DateHierarchyTests(TestCase):
@@ -92,11 +104,13 @@ class DateHierarchyTests(TestCase):
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def test_choice_links(self):
modeladmin = ModelAdmin(Question, site)
- modeladmin.date_hierarchy = 'posted'
+ modeladmin.date_hierarchy = "posted"
posted_dates = (
datetime.date(2017, 10, 1),
@@ -106,67 +120,82 @@ class DateHierarchyTests(TestCase):
datetime.date(2017, 12, 31),
datetime.date(2018, 2, 1),
)
- Question.objects.bulk_create(Question(question='q', posted=posted) for posted in posted_dates)
+ Question.objects.bulk_create(
+ Question(question="q", posted=posted) for posted in posted_dates
+ )
tests = (
- ({}, [['year=2017'], ['year=2018']]),
- ({'year': 2016}, []),
- ({'year': 2017}, [['month=10', 'year=2017'], ['month=12', 'year=2017']]),
- ({'year': 2017, 'month': 9}, []),
- ({'year': 2017, 'month': 12}, [['day=15', 'month=12', 'year=2017'], ['day=31', 'month=12', 'year=2017']]),
+ ({}, [["year=2017"], ["year=2018"]]),
+ ({"year": 2016}, []),
+ ({"year": 2017}, [["month=10", "year=2017"], ["month=12", "year=2017"]]),
+ ({"year": 2017, "month": 9}, []),
+ (
+ {"year": 2017, "month": 12},
+ [
+ ["day=15", "month=12", "year=2017"],
+ ["day=31", "month=12", "year=2017"],
+ ],
+ ),
)
for query, expected_choices in tests:
with self.subTest(query=query):
- query = {'posted__%s' % q: val for q, val in query.items()}
- request = self.factory.get('/', query)
+ query = {"posted__%s" % q: val for q, val in query.items()}
+ request = self.factory.get("/", query)
request.user = self.superuser
changelist = modeladmin.get_changelist_instance(request)
spec = date_hierarchy(changelist)
- choices = [choice['link'] for choice in spec['choices']]
+ choices = [choice["link"] for choice in spec["choices"]]
expected_choices = [
- '&'.join('posted__%s' % c for c in choice) for choice in expected_choices
+ "&".join("posted__%s" % c for c in choice)
+ for choice in expected_choices
+ ]
+ expected_choices = [
+ ("?" + choice) if choice else "" for choice in expected_choices
]
- expected_choices = [('?' + choice) if choice else '' for choice in expected_choices]
self.assertEqual(choices, expected_choices)
def test_choice_links_datetime(self):
modeladmin = ModelAdmin(Question, site)
- modeladmin.date_hierarchy = 'expires'
- Question.objects.bulk_create([
- Question(question='q1', expires=datetime.datetime(2017, 10, 1)),
- Question(question='q2', expires=datetime.datetime(2017, 10, 1)),
- Question(question='q3', expires=datetime.datetime(2017, 12, 15)),
- Question(question='q4', expires=datetime.datetime(2017, 12, 15)),
- Question(question='q5', expires=datetime.datetime(2017, 12, 31)),
- Question(question='q6', expires=datetime.datetime(2018, 2, 1)),
- ])
+ modeladmin.date_hierarchy = "expires"
+ Question.objects.bulk_create(
+ [
+ Question(question="q1", expires=datetime.datetime(2017, 10, 1)),
+ Question(question="q2", expires=datetime.datetime(2017, 10, 1)),
+ Question(question="q3", expires=datetime.datetime(2017, 12, 15)),
+ Question(question="q4", expires=datetime.datetime(2017, 12, 15)),
+ Question(question="q5", expires=datetime.datetime(2017, 12, 31)),
+ Question(question="q6", expires=datetime.datetime(2018, 2, 1)),
+ ]
+ )
tests = [
- ({}, [['year=2017'], ['year=2018']]),
- ({'year': 2016}, []),
+ ({}, [["year=2017"], ["year=2018"]]),
+ ({"year": 2016}, []),
(
- {'year': 2017}, [
- ['month=10', 'year=2017'],
- ['month=12', 'year=2017'],
+ {"year": 2017},
+ [
+ ["month=10", "year=2017"],
+ ["month=12", "year=2017"],
],
),
- ({'year': 2017, 'month': 9}, []),
+ ({"year": 2017, "month": 9}, []),
(
- {'year': 2017, 'month': 12}, [
- ['day=15', 'month=12', 'year=2017'],
- ['day=31', 'month=12', 'year=2017'],
+ {"year": 2017, "month": 12},
+ [
+ ["day=15", "month=12", "year=2017"],
+ ["day=31", "month=12", "year=2017"],
],
),
]
for query, expected_choices in tests:
with self.subTest(query=query):
- query = {'expires__%s' % q: val for q, val in query.items()}
- request = self.factory.get('/', query)
+ query = {"expires__%s" % q: val for q, val in query.items()}
+ request = self.factory.get("/", query)
request.user = self.superuser
changelist = modeladmin.get_changelist_instance(request)
spec = date_hierarchy(changelist)
- choices = [choice['link'] for choice in spec['choices']]
+ choices = [choice["link"] for choice in spec["choices"]]
expected_choices = [
- '?' + '&'.join('expires__%s' % c for c in choice)
+ "?" + "&".join("expires__%s" % c for c in choice)
for choice in expected_choices
]
self.assertEqual(choices, expected_choices)
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 6d73d56625..4935b58823 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -33,7 +33,10 @@ from django.core.files import temp as tempfile
from django.forms.utils import ErrorList
from django.template.response import TemplateResponse
from django.test import (
- TestCase, modify_settings, override_settings, skipUnlessDBFeature,
+ TestCase,
+ modify_settings,
+ override_settings,
+ skipUnlessDBFeature,
)
from django.test.utils import override_script_prefix
from django.urls import NoReverseMatch, resolve, reverse
@@ -46,23 +49,101 @@ from django.utils.http import urlencode
from . import customadmin
from .admin import CityAdmin, site, site2
from .models import (
- Actor, AdminOrderedAdminMethod, AdminOrderedCallable, AdminOrderedField,
- AdminOrderedModelMethod, Album, Answer, Answer2, Article, BarAccount, Book,
- Bookmark, Box, Category, Chapter, ChapterXtra1, ChapterXtra2, Character,
- Child, Choice, City, Collector, Color, ComplexSortedPerson, CoverLetter,
- CustomArticle, CyclicOne, CyclicTwo, DooHickey, Employee, EmptyModel,
- Fabric, FancyDoodad, FieldOverridePost, FilteredManager, FooAccount,
- FoodDelivery, FunkyTag, Gallery, Grommet, Inquisition, Language, Link,
- MainPrepopulated, Media, ModelWithStringPrimaryKey, OtherStory, Paper,
- Parent, ParentWithDependentChildren, ParentWithUUIDPK, Person, Persona,
- Picture, Pizza, Plot, PlotDetails, PluggableSearchPerson, Podcast, Post,
- PrePopulatedPost, Promo, Question, ReadablePizza, ReadOnlyPizza,
- ReadOnlyRelatedField, Recommendation, Recommender, RelatedPrepopulated,
- RelatedWithUUIDPKModel, Report, Restaurant, RowLevelChangePermissionModel,
- SecretHideout, Section, ShortMessage, Simple, Song, State, Story,
- SuperSecretHideout, SuperVillain, Telegram, TitleTranslation, Topping,
- UnchangeableObject, UndeletableObject, UnorderedObject, UserProxy, Villain,
- Vodcast, Whatsit, Widget, Worker, WorkHour,
+ Actor,
+ AdminOrderedAdminMethod,
+ AdminOrderedCallable,
+ AdminOrderedField,
+ AdminOrderedModelMethod,
+ Album,
+ Answer,
+ Answer2,
+ Article,
+ BarAccount,
+ Book,
+ Bookmark,
+ Box,
+ Category,
+ Chapter,
+ ChapterXtra1,
+ ChapterXtra2,
+ Character,
+ Child,
+ Choice,
+ City,
+ Collector,
+ Color,
+ ComplexSortedPerson,
+ CoverLetter,
+ CustomArticle,
+ CyclicOne,
+ CyclicTwo,
+ DooHickey,
+ Employee,
+ EmptyModel,
+ Fabric,
+ FancyDoodad,
+ FieldOverridePost,
+ FilteredManager,
+ FooAccount,
+ FoodDelivery,
+ FunkyTag,
+ Gallery,
+ Grommet,
+ Inquisition,
+ Language,
+ Link,
+ MainPrepopulated,
+ Media,
+ ModelWithStringPrimaryKey,
+ OtherStory,
+ Paper,
+ Parent,
+ ParentWithDependentChildren,
+ ParentWithUUIDPK,
+ Person,
+ Persona,
+ Picture,
+ Pizza,
+ Plot,
+ PlotDetails,
+ PluggableSearchPerson,
+ Podcast,
+ Post,
+ PrePopulatedPost,
+ Promo,
+ Question,
+ ReadablePizza,
+ ReadOnlyPizza,
+ ReadOnlyRelatedField,
+ Recommendation,
+ Recommender,
+ RelatedPrepopulated,
+ RelatedWithUUIDPKModel,
+ Report,
+ Restaurant,
+ RowLevelChangePermissionModel,
+ SecretHideout,
+ Section,
+ ShortMessage,
+ Simple,
+ Song,
+ State,
+ Story,
+ SuperSecretHideout,
+ SuperVillain,
+ Telegram,
+ TitleTranslation,
+ Topping,
+ UnchangeableObject,
+ UndeletableObject,
+ UnorderedObject,
+ UserProxy,
+ Villain,
+ Vodcast,
+ Whatsit,
+ Widget,
+ Worker,
+ WorkHour,
)
ERROR_MESSAGE = "Please enter the correct username and password \
@@ -83,12 +164,13 @@ class AdminFieldExtractionMixin:
"""
Helper methods for extracting data from AdminForm.
"""
+
def get_admin_form_fields(self, response):
"""
Return a list of AdminFields for the AdminForm in the response.
"""
fields = []
- for fieldset in response.context['adminform']:
+ for fieldset in response.context["adminform"]:
for field_line in fieldset:
fields.extend(field_line)
return fields
@@ -105,51 +187,64 @@ class AdminFieldExtractionMixin:
"""
admin_readonly_fields = self.get_admin_readonly_fields(response)
for field in admin_readonly_fields:
- if field.field['name'] == field_name:
+ if field.field["name"] == field_name:
return field
-@override_settings(ROOT_URLCONF='admin_views.urls', USE_I18N=True, LANGUAGE_CODE='en')
+@override_settings(ROOT_URLCONF="admin_views.urls", USE_I18N=True, LANGUAGE_CODE="en")
class AdminViewBasicTestCase(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>',
+ content="<p>Middle content</p>",
date=datetime.datetime(2008, 3, 18, 11, 54, 58),
section=cls.s1,
- title='Article 1',
+ title="Article 1",
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>',
+ content="<p>Oldest content</p>",
date=datetime.datetime(2000, 3, 18, 11, 54, 58),
section=cls.s1,
- title='Article 2',
+ title="Article 2",
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
- )
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
- cls.color1 = Color.objects.create(value='Red', warm=True)
- cls.color2 = Color.objects.create(value='Orange', warm=True)
- cls.color3 = Color.objects.create(value='Blue', warm=False)
- cls.color4 = Color.objects.create(value='Green', warm=False)
- cls.fab1 = Fabric.objects.create(surface='x')
- cls.fab2 = Fabric.objects.create(surface='y')
- cls.fab3 = Fabric.objects.create(surface='plain')
- cls.b1 = Book.objects.create(name='Book 1')
- cls.b2 = Book.objects.create(name='Book 2')
- cls.pro1 = Promo.objects.create(name='Promo 1', book=cls.b1)
- cls.pro1 = Promo.objects.create(name='Promo 2', book=cls.b2)
- cls.chap1 = Chapter.objects.create(title='Chapter 1', content='[ insert contents here ]', book=cls.b1)
- cls.chap2 = Chapter.objects.create(title='Chapter 2', content='[ insert contents here ]', book=cls.b1)
- cls.chap3 = Chapter.objects.create(title='Chapter 1', content='[ insert contents here ]', book=cls.b2)
- cls.chap4 = Chapter.objects.create(title='Chapter 2', content='[ insert contents here ]', book=cls.b2)
- cls.cx1 = ChapterXtra1.objects.create(chap=cls.chap1, xtra='ChapterXtra1 1')
- cls.cx2 = ChapterXtra1.objects.create(chap=cls.chap3, xtra='ChapterXtra1 2')
- Actor.objects.create(name='Palin', age=27)
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
+ )
+ cls.color1 = Color.objects.create(value="Red", warm=True)
+ cls.color2 = Color.objects.create(value="Orange", warm=True)
+ cls.color3 = Color.objects.create(value="Blue", warm=False)
+ cls.color4 = Color.objects.create(value="Green", warm=False)
+ cls.fab1 = Fabric.objects.create(surface="x")
+ cls.fab2 = Fabric.objects.create(surface="y")
+ cls.fab3 = Fabric.objects.create(surface="plain")
+ cls.b1 = Book.objects.create(name="Book 1")
+ cls.b2 = Book.objects.create(name="Book 2")
+ cls.pro1 = Promo.objects.create(name="Promo 1", book=cls.b1)
+ cls.pro1 = Promo.objects.create(name="Promo 2", book=cls.b2)
+ cls.chap1 = Chapter.objects.create(
+ title="Chapter 1", content="[ insert contents here ]", book=cls.b1
+ )
+ cls.chap2 = Chapter.objects.create(
+ title="Chapter 2", content="[ insert contents here ]", book=cls.b1
+ )
+ cls.chap3 = Chapter.objects.create(
+ title="Chapter 1", content="[ insert contents here ]", book=cls.b2
+ )
+ cls.chap4 = Chapter.objects.create(
+ title="Chapter 2", content="[ insert contents here ]", book=cls.b2
+ )
+ cls.cx1 = ChapterXtra1.objects.create(chap=cls.chap1, xtra="ChapterXtra1 1")
+ cls.cx2 = ChapterXtra1.objects.create(chap=cls.chap3, xtra="ChapterXtra1 2")
+ Actor.objects.create(name="Palin", age=27)
# Post data for edit inline
cls.inline_post_data = {
@@ -204,7 +299,9 @@ class AdminViewBasicTestCase(TestCase):
self.assertLess(
response.content.index(text1.encode()),
response.content.index(text2.encode()),
- (failing_msg or '') + '\nResponse:\n' + response.content.decode(response.charset)
+ (failing_msg or "")
+ + "\nResponse:\n"
+ + response.content.decode(response.charset),
)
@@ -213,7 +310,7 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"""
If you leave off the trailing slash, app should redirect and add it.
"""
- add_url = reverse('admin:admin_views_article_add')
+ add_url = reverse("admin:admin_views_article_add")
response = self.client.get(add_url[:-1])
self.assertRedirects(response, add_url, status_code=301)
@@ -221,22 +318,27 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"""
A smoke test to ensure GET on the add_view works.
"""
- response = self.client.get(reverse('admin:admin_views_section_add'))
+ response = self.client.get(reverse("admin:admin_views_section_add"))
self.assertIsInstance(response, TemplateResponse)
self.assertEqual(response.status_code, 200)
def test_add_with_GET_args(self):
- response = self.client.get(reverse('admin:admin_views_section_add'), {'name': 'My Section'})
+ response = self.client.get(
+ reverse("admin:admin_views_section_add"), {"name": "My Section"}
+ )
self.assertContains(
- response, 'value="My Section"',
- msg_prefix="Couldn't find an input with the right value in the response"
+ response,
+ 'value="My Section"',
+ msg_prefix="Couldn't find an input with the right value in the response",
)
def test_basic_edit_GET(self):
"""
A smoke test to ensure GET on the change_view works.
"""
- response = self.client.get(reverse('admin:admin_views_section_change', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,))
+ )
self.assertIsInstance(response, TemplateResponse)
self.assertEqual(response.status_code, 200)
@@ -246,11 +348,14 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
model with an integer PK field) redirects to the index page with a
message saying the object doesn't exist.
"""
- response = self.client.get(reverse('admin:admin_views_section_change', args=(quote("abc/<b>"),)), follow=True)
- self.assertRedirects(response, reverse('admin:index'))
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(quote("abc/<b>"),)),
+ follow=True,
+ )
+ self.assertRedirects(response, reverse("admin:index"))
self.assertEqual(
- [m.message for m in response.context['messages']],
- ['section with ID “abc/<b>” doesn’t exist. Perhaps it was deleted?']
+ [m.message for m in response.context["messages"]],
+ ["section with ID “abc/<b>” doesn’t exist. Perhaps it was deleted?"],
)
def test_basic_edit_GET_old_url_redirect(self):
@@ -258,20 +363,26 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
The change URL changed in Django 1.9, but the old one still redirects.
"""
response = self.client.get(
- reverse('admin:admin_views_section_change', args=(self.s1.pk,)).replace('change/', '')
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)).replace(
+ "change/", ""
+ )
+ )
+ self.assertRedirects(
+ response, reverse("admin:admin_views_section_change", args=(self.s1.pk,))
)
- self.assertRedirects(response, reverse('admin:admin_views_section_change', args=(self.s1.pk,)))
def test_basic_inheritance_GET_string_PK(self):
"""
GET on the change_view (for inherited models) redirects to the index
page with a message saying the object doesn't exist.
"""
- response = self.client.get(reverse('admin:admin_views_supervillain_change', args=('abc',)), follow=True)
- self.assertRedirects(response, reverse('admin:index'))
+ response = self.client.get(
+ reverse("admin:admin_views_supervillain_change", args=("abc",)), follow=True
+ )
+ self.assertRedirects(response, reverse("admin:index"))
self.assertEqual(
- [m.message for m in response.context['messages']],
- ['super villain with ID “abc” doesn’t exist. Perhaps it was deleted?']
+ [m.message for m in response.context["messages"]],
+ ["super villain with ID “abc” doesn’t exist. Perhaps it was deleted?"],
)
def test_basic_add_POST(self):
@@ -285,26 +396,26 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"article_set-INITIAL_FORMS": "0",
"article_set-MAX_NUM_FORMS": "0",
}
- response = self.client.post(reverse('admin:admin_views_section_add'), post_data)
+ response = self.client.post(reverse("admin:admin_views_section_add"), post_data)
self.assertEqual(response.status_code, 302) # redirect somewhere
def test_popup_add_POST(self):
"""HTTP response from a popup is properly escaped."""
post_data = {
- IS_POPUP_VAR: '1',
- 'title': 'title with a new\nline',
- 'content': 'some content',
- 'date_0': '2010-09-10',
- 'date_1': '14:55:39',
+ IS_POPUP_VAR: "1",
+ "title": "title with a new\nline",
+ "content": "some content",
+ "date_0": "2010-09-10",
+ "date_1": "14:55:39",
}
- response = self.client.post(reverse('admin:admin_views_article_add'), post_data)
- self.assertContains(response, 'title with a new\\nline')
+ response = self.client.post(reverse("admin:admin_views_article_add"), post_data)
+ self.assertContains(response, "title with a new\\nline")
def test_basic_edit_POST(self):
"""
A smoke test to ensure POST on edit_view works.
"""
- url = reverse('admin:admin_views_section_change', args=(self.s1.pk,))
+ url = reverse("admin:admin_views_section_change", args=(self.s1.pk,))
response = self.client.post(url, self.inline_post_data)
self.assertEqual(response.status_code, 302) # redirect somewhere
@@ -313,15 +424,19 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Test "save as".
"""
post_data = self.inline_post_data.copy()
- post_data.update({
- '_saveasnew': 'Save+as+new',
- "article_set-1-section": "1",
- "article_set-2-section": "1",
- "article_set-3-section": "1",
- "article_set-4-section": "1",
- "article_set-5-section": "1",
- })
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), post_data)
+ post_data.update(
+ {
+ "_saveasnew": "Save+as+new",
+ "article_set-1-section": "1",
+ "article_set-2-section": "1",
+ "article_set-3-section": "1",
+ "article_set-4-section": "1",
+ "article_set-5-section": "1",
+ }
+ )
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), post_data
+ )
self.assertEqual(response.status_code, 302) # redirect somewhere
def test_edit_save_as_delete_inline(self):
@@ -329,40 +444,50 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Should be able to "Save as new" while also deleting an inline.
"""
post_data = self.inline_post_data.copy()
- post_data.update({
- '_saveasnew': 'Save+as+new',
- "article_set-1-section": "1",
- "article_set-2-section": "1",
- "article_set-2-DELETE": "1",
- "article_set-3-section": "1",
- })
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), post_data)
+ post_data.update(
+ {
+ "_saveasnew": "Save+as+new",
+ "article_set-1-section": "1",
+ "article_set-2-section": "1",
+ "article_set-2-DELETE": "1",
+ "article_set-3-section": "1",
+ }
+ )
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), post_data
+ )
self.assertEqual(response.status_code, 302)
# started with 3 articles, one was deleted.
- self.assertEqual(Section.objects.latest('id').article_set.count(), 2)
+ self.assertEqual(Section.objects.latest("id").article_set.count(), 2)
def test_change_list_column_field_classes(self):
- response = self.client.get(reverse('admin:admin_views_article_changelist'))
+ response = self.client.get(reverse("admin:admin_views_article_changelist"))
# callables display the callable name.
- self.assertContains(response, 'column-callable_year')
- self.assertContains(response, 'field-callable_year')
+ self.assertContains(response, "column-callable_year")
+ self.assertContains(response, "field-callable_year")
# lambdas display as "lambda" + index that they appear in list_display.
- self.assertContains(response, 'column-lambda8')
- self.assertContains(response, 'field-lambda8')
+ self.assertContains(response, "column-lambda8")
+ self.assertContains(response, "field-lambda8")
def test_change_list_sorting_callable(self):
"""
Ensure we can sort on a list_display field that is a callable
(column 2 is callable_year in ArticleAdmin)
"""
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': 2})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": 2}
+ )
self.assertContentBefore(
- response, 'Oldest content', 'Middle content',
- "Results of sorting on callable are out of order."
+ response,
+ "Oldest content",
+ "Middle content",
+ "Results of sorting on callable are out of order.",
)
self.assertContentBefore(
- response, 'Middle content', 'Newest content',
- "Results of sorting on callable are out of order."
+ response,
+ "Middle content",
+ "Newest content",
+ "Results of sorting on callable are out of order.",
)
def test_change_list_sorting_property(self):
@@ -370,61 +495,71 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Sort on a list_display field that is a property (column 10 is
a property in Article model).
"""
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': 10})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": 10}
+ )
self.assertContentBefore(
response,
- 'Oldest content',
- 'Middle content',
- 'Results of sorting on property are out of order.',
+ "Oldest content",
+ "Middle content",
+ "Results of sorting on property are out of order.",
)
self.assertContentBefore(
response,
- 'Middle content',
- 'Newest content',
- 'Results of sorting on property are out of order.',
+ "Middle content",
+ "Newest content",
+ "Results of sorting on property are out of order.",
)
def test_change_list_sorting_callable_query_expression(self):
"""Query expressions may be used for admin_order_field."""
tests = [
- ('order_by_expression', 9),
- ('order_by_f_expression', 12),
- ('order_by_orderby_expression', 13),
+ ("order_by_expression", 9),
+ ("order_by_f_expression", 12),
+ ("order_by_orderby_expression", 13),
]
for admin_order_field, index in tests:
with self.subTest(admin_order_field):
response = self.client.get(
- reverse('admin:admin_views_article_changelist'),
- {'o': index},
+ reverse("admin:admin_views_article_changelist"),
+ {"o": index},
)
self.assertContentBefore(
- response, 'Oldest content', 'Middle content',
- 'Results of sorting on callable are out of order.'
+ response,
+ "Oldest content",
+ "Middle content",
+ "Results of sorting on callable are out of order.",
)
self.assertContentBefore(
- response, 'Middle content', 'Newest content',
- 'Results of sorting on callable are out of order.'
+ response,
+ "Middle content",
+ "Newest content",
+ "Results of sorting on callable are out of order.",
)
def test_change_list_sorting_callable_query_expression_reverse(self):
tests = [
- ('order_by_expression', -9),
- ('order_by_f_expression', -12),
- ('order_by_orderby_expression', -13),
+ ("order_by_expression", -9),
+ ("order_by_f_expression", -12),
+ ("order_by_orderby_expression", -13),
]
for admin_order_field, index in tests:
with self.subTest(admin_order_field):
response = self.client.get(
- reverse('admin:admin_views_article_changelist'),
- {'o': index},
+ reverse("admin:admin_views_article_changelist"),
+ {"o": index},
)
self.assertContentBefore(
- response, 'Middle content', 'Oldest content',
- 'Results of sorting on callable are out of order.'
+ response,
+ "Middle content",
+ "Oldest content",
+ "Results of sorting on callable are out of order.",
)
self.assertContentBefore(
- response, 'Newest content', 'Middle content',
- 'Results of sorting on callable are out of order.'
+ response,
+ "Newest content",
+ "Middle content",
+ "Results of sorting on callable are out of order.",
)
def test_change_list_sorting_model(self):
@@ -432,14 +567,20 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Ensure we can sort on a list_display field that is a Model method
(column 3 is 'model_year' in ArticleAdmin)
"""
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': '-3'})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": "-3"}
+ )
self.assertContentBefore(
- response, 'Newest content', 'Middle content',
- "Results of sorting on Model method are out of order."
+ response,
+ "Newest content",
+ "Middle content",
+ "Results of sorting on Model method are out of order.",
)
self.assertContentBefore(
- response, 'Middle content', 'Oldest content',
- "Results of sorting on Model method are out of order."
+ response,
+ "Middle content",
+ "Oldest content",
+ "Results of sorting on Model method are out of order.",
)
def test_change_list_sorting_model_admin(self):
@@ -447,14 +588,20 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Ensure we can sort on a list_display field that is a ModelAdmin method
(column 4 is 'modeladmin_year' in ArticleAdmin)
"""
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': '4'})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": "4"}
+ )
self.assertContentBefore(
- response, 'Oldest content', 'Middle content',
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ "Oldest content",
+ "Middle content",
+ "Results of sorting on ModelAdmin method are out of order.",
)
self.assertContentBefore(
- response, 'Middle content', 'Newest content',
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ "Middle content",
+ "Newest content",
+ "Results of sorting on ModelAdmin method are out of order.",
)
def test_change_list_sorting_model_admin_reverse(self):
@@ -465,42 +612,58 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"""
td = '<td class="field-model_property_year">%s</td>'
td_2000, td_2008, td_2009 = td % 2000, td % 2008, td % 2009
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': '6'})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": "6"}
+ )
self.assertContentBefore(
- response, td_2009, td_2008,
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ td_2009,
+ td_2008,
+ "Results of sorting on ModelAdmin method are out of order.",
)
self.assertContentBefore(
- response, td_2008, td_2000,
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ td_2008,
+ td_2000,
+ "Results of sorting on ModelAdmin method are out of order.",
)
# Let's make sure the ordering is right and that we don't get a
# FieldError when we change to descending order
- response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': '-6'})
+ response = self.client.get(
+ reverse("admin:admin_views_article_changelist"), {"o": "-6"}
+ )
self.assertContentBefore(
- response, td_2000, td_2008,
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ td_2000,
+ td_2008,
+ "Results of sorting on ModelAdmin method are out of order.",
)
self.assertContentBefore(
- response, td_2008, td_2009,
- "Results of sorting on ModelAdmin method are out of order."
+ response,
+ td_2008,
+ td_2009,
+ "Results of sorting on ModelAdmin method are out of order.",
)
def test_change_list_sorting_multiple(self):
p1 = Person.objects.create(name="Chris", gender=1, alive=True)
p2 = Person.objects.create(name="Chris", gender=2, alive=True)
p3 = Person.objects.create(name="Bob", gender=1, alive=True)
- link1 = reverse('admin:admin_views_person_change', args=(p1.pk,))
- link2 = reverse('admin:admin_views_person_change', args=(p2.pk,))
- link3 = reverse('admin:admin_views_person_change', args=(p3.pk,))
+ link1 = reverse("admin:admin_views_person_change", args=(p1.pk,))
+ link2 = reverse("admin:admin_views_person_change", args=(p2.pk,))
+ link3 = reverse("admin:admin_views_person_change", args=(p3.pk,))
# Sort by name, gender
- response = self.client.get(reverse('admin:admin_views_person_changelist'), {'o': '1.2'})
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist"), {"o": "1.2"}
+ )
self.assertContentBefore(response, link3, link1)
self.assertContentBefore(response, link1, link2)
# Sort by gender descending, name
- response = self.client.get(reverse('admin:admin_views_person_changelist'), {'o': '-2.1'})
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist"), {"o": "-2.1"}
+ )
self.assertContentBefore(response, link2, link3)
self.assertContentBefore(response, link3, link1)
@@ -514,27 +677,29 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
p1 = Person.objects.create(name="Amy", gender=1, alive=True, age=80)
p2 = Person.objects.create(name="Bob", gender=1, alive=True, age=70)
p3 = Person.objects.create(name="Chris", gender=2, alive=False, age=60)
- link1 = reverse('admin:admin_views_person_change', args=(p1.pk,))
- link2 = reverse('admin:admin_views_person_change', args=(p2.pk,))
- link3 = reverse('admin:admin_views_person_change', args=(p3.pk,))
+ link1 = reverse("admin:admin_views_person_change", args=(p1.pk,))
+ link2 = reverse("admin:admin_views_person_change", args=(p2.pk,))
+ link3 = reverse("admin:admin_views_person_change", args=(p3.pk,))
- response = self.client.get(reverse('admin:admin_views_person_changelist'), {})
+ response = self.client.get(reverse("admin:admin_views_person_changelist"), {})
self.assertContentBefore(response, link3, link2)
self.assertContentBefore(response, link2, link1)
def test_change_list_sorting_model_meta(self):
# Test ordering on Model Meta is respected
- l1 = Language.objects.create(iso='ur', name='Urdu')
- l2 = Language.objects.create(iso='ar', name='Arabic')
- link1 = reverse('admin:admin_views_language_change', args=(quote(l1.pk),))
- link2 = reverse('admin:admin_views_language_change', args=(quote(l2.pk),))
+ l1 = Language.objects.create(iso="ur", name="Urdu")
+ l2 = Language.objects.create(iso="ar", name="Arabic")
+ link1 = reverse("admin:admin_views_language_change", args=(quote(l1.pk),))
+ link2 = reverse("admin:admin_views_language_change", args=(quote(l2.pk),))
- response = self.client.get(reverse('admin:admin_views_language_changelist'), {})
+ response = self.client.get(reverse("admin:admin_views_language_changelist"), {})
self.assertContentBefore(response, link2, link1)
# Test we can override with query string
- response = self.client.get(reverse('admin:admin_views_language_changelist'), {'o': '-1'})
+ response = self.client.get(
+ reverse("admin:admin_views_language_changelist"), {"o": "-1"}
+ )
self.assertContentBefore(response, link1, link2)
def test_change_list_sorting_override_model_admin(self):
@@ -542,10 +707,10 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
dt = datetime.datetime.now()
p1 = Podcast.objects.create(name="A", release_date=dt)
p2 = Podcast.objects.create(name="B", release_date=dt - datetime.timedelta(10))
- link1 = reverse('admin:admin_views_podcast_change', args=(p1.pk,))
- link2 = reverse('admin:admin_views_podcast_change', args=(p2.pk,))
+ link1 = reverse("admin:admin_views_podcast_change", args=(p1.pk,))
+ link2 = reverse("admin:admin_views_podcast_change", args=(p2.pk,))
- response = self.client.get(reverse('admin:admin_views_podcast_changelist'), {})
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"), {})
self.assertContentBefore(response, link1, link2)
def test_multiple_sort_same_field(self):
@@ -554,26 +719,28 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
dt = datetime.datetime.now()
p1 = Podcast.objects.create(name="A", release_date=dt)
p2 = Podcast.objects.create(name="B", release_date=dt - datetime.timedelta(10))
- link1 = reverse('admin:admin_views_podcast_change', args=(quote(p1.pk),))
- link2 = reverse('admin:admin_views_podcast_change', args=(quote(p2.pk),))
+ link1 = reverse("admin:admin_views_podcast_change", args=(quote(p1.pk),))
+ link2 = reverse("admin:admin_views_podcast_change", args=(quote(p2.pk),))
- response = self.client.get(reverse('admin:admin_views_podcast_changelist'), {})
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"), {})
self.assertContentBefore(response, link1, link2)
p1 = ComplexSortedPerson.objects.create(name="Bob", age=10)
p2 = ComplexSortedPerson.objects.create(name="Amy", age=20)
- link1 = reverse('admin:admin_views_complexsortedperson_change', args=(p1.pk,))
- link2 = reverse('admin:admin_views_complexsortedperson_change', args=(p2.pk,))
+ link1 = reverse("admin:admin_views_complexsortedperson_change", args=(p1.pk,))
+ link2 = reverse("admin:admin_views_complexsortedperson_change", args=(p2.pk,))
- response = self.client.get(reverse('admin:admin_views_complexsortedperson_changelist'), {})
+ response = self.client.get(
+ reverse("admin:admin_views_complexsortedperson_changelist"), {}
+ )
# Should have 5 columns (including action checkbox col)
self.assertContains(response, '<th scope="col"', count=5)
- self.assertContains(response, 'Name')
- self.assertContains(response, 'Colored name')
+ self.assertContains(response, "Name")
+ self.assertContains(response, "Colored name")
# Check order
- self.assertContentBefore(response, 'Name', 'Colored name')
+ self.assertContentBefore(response, "Name", "Colored name")
# Check sorting - should be by name
self.assertContentBefore(response, link2, link1)
@@ -584,146 +751,170 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
fields: field names, method on the model admin and model itself, and
other callables. See #17252.
"""
- models = [(AdminOrderedField, 'adminorderedfield'),
- (AdminOrderedModelMethod, 'adminorderedmodelmethod'),
- (AdminOrderedAdminMethod, 'adminorderedadminmethod'),
- (AdminOrderedCallable, 'adminorderedcallable')]
+ models = [
+ (AdminOrderedField, "adminorderedfield"),
+ (AdminOrderedModelMethod, "adminorderedmodelmethod"),
+ (AdminOrderedAdminMethod, "adminorderedadminmethod"),
+ (AdminOrderedCallable, "adminorderedcallable"),
+ ]
for model, url in models:
- model.objects.create(stuff='The Last Item', order=3)
- model.objects.create(stuff='The First Item', order=1)
- model.objects.create(stuff='The Middle Item', order=2)
- response = self.client.get(reverse('admin:admin_views_%s_changelist' % url), {})
+ model.objects.create(stuff="The Last Item", order=3)
+ model.objects.create(stuff="The First Item", order=1)
+ model.objects.create(stuff="The Middle Item", order=2)
+ response = self.client.get(
+ reverse("admin:admin_views_%s_changelist" % url), {}
+ )
# Should have 3 columns including action checkbox col.
self.assertContains(response, '<th scope="col"', count=3, msg_prefix=url)
# Check if the correct column was selected. 2 is the index of the
# 'order' column in the model admin's 'list_display' with 0 being
# the implicit 'action_checkbox' and 1 being the column 'stuff'.
- self.assertEqual(response.context['cl'].get_ordering_field_columns(), {2: 'asc'})
+ self.assertEqual(
+ response.context["cl"].get_ordering_field_columns(), {2: "asc"}
+ )
# Check order of records.
- self.assertContentBefore(response, 'The First Item', 'The Middle Item')
- self.assertContentBefore(response, 'The Middle Item', 'The Last Item')
+ self.assertContentBefore(response, "The First Item", "The Middle Item")
+ self.assertContentBefore(response, "The Middle Item", "The Last Item")
def test_has_related_field_in_list_display_fk(self):
"""Joins shouldn't be performed for <FK>_id fields in list display."""
- state = State.objects.create(name='Karnataka')
- City.objects.create(state=state, name='Bangalore')
- response = self.client.get(reverse('admin:admin_views_city_changelist'), {})
+ state = State.objects.create(name="Karnataka")
+ City.objects.create(state=state, name="Bangalore")
+ response = self.client.get(reverse("admin:admin_views_city_changelist"), {})
- response.context['cl'].list_display = ['id', 'name', 'state']
- self.assertIs(response.context['cl'].has_related_field_in_list_display(), True)
+ response.context["cl"].list_display = ["id", "name", "state"]
+ self.assertIs(response.context["cl"].has_related_field_in_list_display(), True)
- response.context['cl'].list_display = ['id', 'name', 'state_id']
- self.assertIs(response.context['cl'].has_related_field_in_list_display(), False)
+ response.context["cl"].list_display = ["id", "name", "state_id"]
+ self.assertIs(response.context["cl"].has_related_field_in_list_display(), False)
def test_has_related_field_in_list_display_o2o(self):
"""Joins shouldn't be performed for <O2O>_id fields in list display."""
- media = Media.objects.create(name='Foo')
+ media = Media.objects.create(name="Foo")
Vodcast.objects.create(media=media)
- response = self.client.get(reverse('admin:admin_views_vodcast_changelist'), {})
+ response = self.client.get(reverse("admin:admin_views_vodcast_changelist"), {})
- response.context['cl'].list_display = ['media']
- self.assertIs(response.context['cl'].has_related_field_in_list_display(), True)
+ response.context["cl"].list_display = ["media"]
+ self.assertIs(response.context["cl"].has_related_field_in_list_display(), True)
- response.context['cl'].list_display = ['media_id']
- self.assertIs(response.context['cl'].has_related_field_in_list_display(), False)
+ response.context["cl"].list_display = ["media_id"]
+ self.assertIs(response.context["cl"].has_related_field_in_list_display(), False)
def test_limited_filter(self):
"""Ensure admin changelist filters do not contain objects excluded via limit_choices_to.
This also tests relation-spanning filters (e.g. 'color__value').
"""
- response = self.client.get(reverse('admin:admin_views_thing_changelist'))
+ response = self.client.get(reverse("admin:admin_views_thing_changelist"))
self.assertContains(
- response, '<div id="changelist-filter">',
- msg_prefix="Expected filter not found in changelist view"
+ response,
+ '<div id="changelist-filter">',
+ msg_prefix="Expected filter not found in changelist view",
)
self.assertNotContains(
- response, '<a href="?color__id__exact=3">Blue</a>',
- msg_prefix="Changelist filter not correctly limited by limit_choices_to"
+ response,
+ '<a href="?color__id__exact=3">Blue</a>',
+ msg_prefix="Changelist filter not correctly limited by limit_choices_to",
)
def test_relation_spanning_filters(self):
- changelist_url = reverse('admin:admin_views_chapterxtra1_changelist')
+ changelist_url = reverse("admin:admin_views_chapterxtra1_changelist")
response = self.client.get(changelist_url)
self.assertContains(response, '<div id="changelist-filter">')
filters = {
- 'chap__id__exact': {
- 'values': [c.id for c in Chapter.objects.all()],
- 'test': lambda obj, value: obj.chap.id == value,
+ "chap__id__exact": {
+ "values": [c.id for c in Chapter.objects.all()],
+ "test": lambda obj, value: obj.chap.id == value,
},
- 'chap__title': {
- 'values': [c.title for c in Chapter.objects.all()],
- 'test': lambda obj, value: obj.chap.title == value,
+ "chap__title": {
+ "values": [c.title for c in Chapter.objects.all()],
+ "test": lambda obj, value: obj.chap.title == value,
},
- 'chap__book__id__exact': {
- 'values': [b.id for b in Book.objects.all()],
- 'test': lambda obj, value: obj.chap.book.id == value,
+ "chap__book__id__exact": {
+ "values": [b.id for b in Book.objects.all()],
+ "test": lambda obj, value: obj.chap.book.id == value,
},
- 'chap__book__name': {
- 'values': [b.name for b in Book.objects.all()],
- 'test': lambda obj, value: obj.chap.book.name == value,
+ "chap__book__name": {
+ "values": [b.name for b in Book.objects.all()],
+ "test": lambda obj, value: obj.chap.book.name == value,
},
- 'chap__book__promo__id__exact': {
- 'values': [p.id for p in Promo.objects.all()],
- 'test': lambda obj, value: obj.chap.book.promo_set.filter(id=value).exists(),
+ "chap__book__promo__id__exact": {
+ "values": [p.id for p in Promo.objects.all()],
+ "test": lambda obj, value: obj.chap.book.promo_set.filter(
+ id=value
+ ).exists(),
},
- 'chap__book__promo__name': {
- 'values': [p.name for p in Promo.objects.all()],
- 'test': lambda obj, value: obj.chap.book.promo_set.filter(name=value).exists(),
+ "chap__book__promo__name": {
+ "values": [p.name for p in Promo.objects.all()],
+ "test": lambda obj, value: obj.chap.book.promo_set.filter(
+ name=value
+ ).exists(),
},
# A forward relation (book) after a reverse relation (promo).
- 'guest_author__promo__book__id__exact': {
- 'values': [p.id for p in Book.objects.all()],
- 'test': lambda obj, value: obj.guest_author.promo_set.filter(book=value).exists(),
+ "guest_author__promo__book__id__exact": {
+ "values": [p.id for p in Book.objects.all()],
+ "test": lambda obj, value: obj.guest_author.promo_set.filter(
+ book=value
+ ).exists(),
},
}
for filter_path, params in filters.items():
- for value in params['values']:
+ for value in params["values"]:
query_string = urlencode({filter_path: value})
# ensure filter link exists
self.assertContains(response, '<a href="?%s"' % query_string)
# ensure link works
- filtered_response = self.client.get('%s?%s' % (changelist_url, query_string))
+ filtered_response = self.client.get(
+ "%s?%s" % (changelist_url, query_string)
+ )
self.assertEqual(filtered_response.status_code, 200)
# ensure changelist contains only valid objects
- for obj in filtered_response.context['cl'].queryset.all():
- self.assertTrue(params['test'](obj, value))
+ for obj in filtered_response.context["cl"].queryset.all():
+ self.assertTrue(params["test"](obj, value))
def test_incorrect_lookup_parameters(self):
"""Ensure incorrect lookup parameters are handled gracefully."""
- changelist_url = reverse('admin:admin_views_thing_changelist')
- response = self.client.get(changelist_url, {'notarealfield': '5'})
- self.assertRedirects(response, '%s?e=1' % changelist_url)
+ changelist_url = reverse("admin:admin_views_thing_changelist")
+ response = self.client.get(changelist_url, {"notarealfield": "5"})
+ self.assertRedirects(response, "%s?e=1" % changelist_url)
# Spanning relationships through a nonexistent related object (Refs #16716)
- response = self.client.get(changelist_url, {'notarealfield__whatever': '5'})
- self.assertRedirects(response, '%s?e=1' % changelist_url)
+ response = self.client.get(changelist_url, {"notarealfield__whatever": "5"})
+ self.assertRedirects(response, "%s?e=1" % changelist_url)
- response = self.client.get(changelist_url, {'color__id__exact': 'StringNotInteger!'})
- self.assertRedirects(response, '%s?e=1' % changelist_url)
+ response = self.client.get(
+ changelist_url, {"color__id__exact": "StringNotInteger!"}
+ )
+ self.assertRedirects(response, "%s?e=1" % changelist_url)
# Regression test for #18530
- response = self.client.get(changelist_url, {'pub_date__gte': 'foo'})
- self.assertRedirects(response, '%s?e=1' % changelist_url)
+ response = self.client.get(changelist_url, {"pub_date__gte": "foo"})
+ self.assertRedirects(response, "%s?e=1" % changelist_url)
def test_isnull_lookups(self):
"""Ensure is_null is handled correctly."""
- Article.objects.create(title="I Could Go Anywhere", content="Versatile", date=datetime.datetime.now())
- changelist_url = reverse('admin:admin_views_article_changelist')
+ Article.objects.create(
+ title="I Could Go Anywhere",
+ content="Versatile",
+ date=datetime.datetime.now(),
+ )
+ changelist_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(changelist_url)
- self.assertContains(response, '4 articles')
- response = self.client.get(changelist_url, {'section__isnull': 'false'})
- self.assertContains(response, '3 articles')
- response = self.client.get(changelist_url, {'section__isnull': '0'})
- self.assertContains(response, '3 articles')
- response = self.client.get(changelist_url, {'section__isnull': 'true'})
- self.assertContains(response, '1 article')
- response = self.client.get(changelist_url, {'section__isnull': '1'})
- self.assertContains(response, '1 article')
+ self.assertContains(response, "4 articles")
+ response = self.client.get(changelist_url, {"section__isnull": "false"})
+ self.assertContains(response, "3 articles")
+ response = self.client.get(changelist_url, {"section__isnull": "0"})
+ self.assertContains(response, "3 articles")
+ response = self.client.get(changelist_url, {"section__isnull": "true"})
+ self.assertContains(response, "1 article")
+ response = self.client.get(changelist_url, {"section__isnull": "1"})
+ self.assertContains(response, "1 article")
def test_logout_and_password_change_URLs(self):
- response = self.client.get(reverse('admin:admin_views_article_changelist'))
- self.assertContains(response, '<a href="%s">' % reverse('admin:logout'))
- self.assertContains(response, '<a href="%s">' % reverse('admin:password_change'))
+ response = self.client.get(reverse("admin:admin_views_article_changelist"))
+ self.assertContains(response, '<a href="%s">' % reverse("admin:logout"))
+ self.assertContains(
+ response, '<a href="%s">' % reverse("admin:password_change")
+ )
def test_named_group_field_choices_change_list(self):
"""
@@ -731,49 +922,64 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
for rows corresponding to instances of a model in which a named group
has been used in the choices option of a field.
"""
- link1 = reverse('admin:admin_views_fabric_change', args=(self.fab1.pk,))
- link2 = reverse('admin:admin_views_fabric_change', args=(self.fab2.pk,))
- response = self.client.get(reverse('admin:admin_views_fabric_changelist'))
+ link1 = reverse("admin:admin_views_fabric_change", args=(self.fab1.pk,))
+ link2 = reverse("admin:admin_views_fabric_change", args=(self.fab2.pk,))
+ response = self.client.get(reverse("admin:admin_views_fabric_changelist"))
fail_msg = (
"Changelist table isn't showing the right human-readable values "
"set by a model field 'choices' option named group."
)
- self.assertContains(response, '<a href="%s">Horizontal</a>' % link1, msg_prefix=fail_msg, html=True)
- self.assertContains(response, '<a href="%s">Vertical</a>' % link2, msg_prefix=fail_msg, html=True)
+ self.assertContains(
+ response,
+ '<a href="%s">Horizontal</a>' % link1,
+ msg_prefix=fail_msg,
+ html=True,
+ )
+ self.assertContains(
+ response,
+ '<a href="%s">Vertical</a>' % link2,
+ msg_prefix=fail_msg,
+ html=True,
+ )
def test_named_group_field_choices_filter(self):
"""
Ensures the filter UI shows correctly when at least one named group has
been used in the choices option of a model field.
"""
- response = self.client.get(reverse('admin:admin_views_fabric_changelist'))
+ response = self.client.get(reverse("admin:admin_views_fabric_changelist"))
fail_msg = (
"Changelist filter isn't showing options contained inside a model "
"field 'choices' option named group."
)
self.assertContains(response, '<div id="changelist-filter">')
self.assertContains(
- response, '<a href="?surface__exact=x">Horizontal</a>',
- msg_prefix=fail_msg, html=True
+ response,
+ '<a href="?surface__exact=x">Horizontal</a>',
+ msg_prefix=fail_msg,
+ html=True,
)
self.assertContains(
- response, '<a href="?surface__exact=y">Vertical</a>',
- msg_prefix=fail_msg, html=True
+ response,
+ '<a href="?surface__exact=y">Vertical</a>',
+ msg_prefix=fail_msg,
+ html=True,
)
def test_change_list_null_boolean_display(self):
Post.objects.create(public=None)
- response = self.client.get(reverse('admin:admin_views_post_changelist'))
- self.assertContains(response, 'icon-unknown.svg')
+ response = self.client.get(reverse("admin:admin_views_post_changelist"))
+ self.assertContains(response, "icon-unknown.svg")
def test_display_decorator_with_boolean_and_empty_value(self):
msg = (
- 'The boolean and empty_value arguments to the @display decorator '
- 'are mutually exclusive.'
+ "The boolean and empty_value arguments to the @display decorator "
+ "are mutually exclusive."
)
with self.assertRaisesMessage(ValueError, msg):
+
class BookAdmin(admin.ModelAdmin):
- @admin.display(boolean=True, empty_value='(Missing)')
+ @admin.display(boolean=True, empty_value="(Missing)")
def is_published(self, obj):
return obj.publish_date is not None
@@ -783,21 +989,21 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
if the default language is non-English but the selected language
is English. See #13388 and #3594 for more details.
"""
- with self.settings(LANGUAGE_CODE='fr'), translation.override('en-us'):
- response = self.client.get(reverse('admin:jsi18n'))
- self.assertNotContains(response, 'Choisir une heure')
+ with self.settings(LANGUAGE_CODE="fr"), translation.override("en-us"):
+ response = self.client.get(reverse("admin:jsi18n"))
+ self.assertNotContains(response, "Choisir une heure")
def test_i18n_language_non_english_fallback(self):
"""
Makes sure that the fallback language is still working properly
in cases where the selected language cannot be found.
"""
- with self.settings(LANGUAGE_CODE='fr'), translation.override('none'):
- response = self.client.get(reverse('admin:jsi18n'))
- self.assertContains(response, 'Choisir une heure')
+ with self.settings(LANGUAGE_CODE="fr"), translation.override("none"):
+ response = self.client.get(reverse("admin:jsi18n"))
+ self.assertContains(response, "Choisir une heure")
def test_jsi18n_with_context(self):
- response = self.client.get(reverse('admin-extra-context:jsi18n'))
+ response = self.client.get(reverse("admin-extra-context:jsi18n"))
self.assertEqual(response.status_code, 200)
def test_jsi18n_format_fallback(self):
@@ -805,96 +1011,125 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
The JavaScript i18n view doesn't return localized date/time formats
when the selected language cannot be found.
"""
- with self.settings(LANGUAGE_CODE='ru'), translation.override('none'):
- response = self.client.get(reverse('admin:jsi18n'))
- self.assertNotContains(response, '%d.%m.%Y %H:%M:%S')
- self.assertContains(response, '%Y-%m-%d %H:%M:%S')
+ with self.settings(LANGUAGE_CODE="ru"), translation.override("none"):
+ response = self.client.get(reverse("admin:jsi18n"))
+ self.assertNotContains(response, "%d.%m.%Y %H:%M:%S")
+ self.assertContains(response, "%Y-%m-%d %H:%M:%S")
def test_disallowed_filtering(self):
- with self.assertLogs('django.security.DisallowedModelAdminLookup', 'ERROR'):
+ with self.assertLogs("django.security.DisallowedModelAdminLookup", "ERROR"):
response = self.client.get(
- "%s?owner__email__startswith=fuzzy" % reverse('admin:admin_views_album_changelist')
+ "%s?owner__email__startswith=fuzzy"
+ % reverse("admin:admin_views_album_changelist")
)
self.assertEqual(response.status_code, 400)
# Filters are allowed if explicitly included in list_filter
- response = self.client.get("%s?color__value__startswith=red" % reverse('admin:admin_views_thing_changelist'))
+ response = self.client.get(
+ "%s?color__value__startswith=red"
+ % reverse("admin:admin_views_thing_changelist")
+ )
self.assertEqual(response.status_code, 200)
- response = self.client.get("%s?color__value=red" % reverse('admin:admin_views_thing_changelist'))
+ response = self.client.get(
+ "%s?color__value=red" % reverse("admin:admin_views_thing_changelist")
+ )
self.assertEqual(response.status_code, 200)
# Filters should be allowed if they involve a local field without the
# need to allow them in list_filter or date_hierarchy.
- response = self.client.get("%s?age__gt=30" % reverse('admin:admin_views_person_changelist'))
+ response = self.client.get(
+ "%s?age__gt=30" % reverse("admin:admin_views_person_changelist")
+ )
self.assertEqual(response.status_code, 200)
- e1 = Employee.objects.create(name='Anonymous', gender=1, age=22, alive=True, code='123')
- e2 = Employee.objects.create(name='Visitor', gender=2, age=19, alive=True, code='124')
+ e1 = Employee.objects.create(
+ name="Anonymous", gender=1, age=22, alive=True, code="123"
+ )
+ e2 = Employee.objects.create(
+ name="Visitor", gender=2, age=19, alive=True, code="124"
+ )
WorkHour.objects.create(datum=datetime.datetime.now(), employee=e1)
WorkHour.objects.create(datum=datetime.datetime.now(), employee=e2)
- response = self.client.get(reverse('admin:admin_views_workhour_changelist'))
- self.assertContains(response, 'employee__person_ptr__exact')
- response = self.client.get("%s?employee__person_ptr__exact=%d" % (
- reverse('admin:admin_views_workhour_changelist'), e1.pk)
+ response = self.client.get(reverse("admin:admin_views_workhour_changelist"))
+ self.assertContains(response, "employee__person_ptr__exact")
+ response = self.client.get(
+ "%s?employee__person_ptr__exact=%d"
+ % (reverse("admin:admin_views_workhour_changelist"), e1.pk)
)
self.assertEqual(response.status_code, 200)
def test_disallowed_to_field(self):
- url = reverse('admin:admin_views_section_changelist')
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.get(url, {TO_FIELD_VAR: 'missing_field'})
+ url = reverse("admin:admin_views_section_changelist")
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.get(url, {TO_FIELD_VAR: "missing_field"})
self.assertEqual(response.status_code, 400)
# Specifying a field that is not referred by any other model registered
# to this admin site should raise an exception.
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.get(reverse('admin:admin_views_section_changelist'), {TO_FIELD_VAR: 'name'})
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.get(
+ reverse("admin:admin_views_section_changelist"), {TO_FIELD_VAR: "name"}
+ )
self.assertEqual(response.status_code, 400)
# #23839 - Primary key should always be allowed, even if the referenced model isn't registered.
- response = self.client.get(reverse('admin:admin_views_notreferenced_changelist'), {TO_FIELD_VAR: 'id'})
+ response = self.client.get(
+ reverse("admin:admin_views_notreferenced_changelist"), {TO_FIELD_VAR: "id"}
+ )
self.assertEqual(response.status_code, 200)
# #23915 - Specifying a field referenced by another model though a m2m should be allowed.
- response = self.client.get(reverse('admin:admin_views_recipe_changelist'), {TO_FIELD_VAR: 'rname'})
+ response = self.client.get(
+ reverse("admin:admin_views_recipe_changelist"), {TO_FIELD_VAR: "rname"}
+ )
self.assertEqual(response.status_code, 200)
# #23604, #23915 - Specifying a field referenced through a reverse m2m relationship should be allowed.
- response = self.client.get(reverse('admin:admin_views_ingredient_changelist'), {TO_FIELD_VAR: 'iname'})
+ response = self.client.get(
+ reverse("admin:admin_views_ingredient_changelist"), {TO_FIELD_VAR: "iname"}
+ )
self.assertEqual(response.status_code, 200)
# #23329 - Specifying a field that is not referred by any other model directly registered
# to this admin site but registered through inheritance should be allowed.
- response = self.client.get(reverse('admin:admin_views_referencedbyparent_changelist'), {TO_FIELD_VAR: 'name'})
+ response = self.client.get(
+ reverse("admin:admin_views_referencedbyparent_changelist"),
+ {TO_FIELD_VAR: "name"},
+ )
self.assertEqual(response.status_code, 200)
# #23431 - Specifying a field that is only referred to by a inline of a registered
# model should be allowed.
- response = self.client.get(reverse('admin:admin_views_referencedbyinline_changelist'), {TO_FIELD_VAR: 'name'})
+ response = self.client.get(
+ reverse("admin:admin_views_referencedbyinline_changelist"),
+ {TO_FIELD_VAR: "name"},
+ )
self.assertEqual(response.status_code, 200)
# #25622 - Specifying a field of a model only referred by a generic
# relation should raise DisallowedModelAdminToField.
- url = reverse('admin:admin_views_referencedbygenrel_changelist')
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.get(url, {TO_FIELD_VAR: 'object_id'})
+ url = reverse("admin:admin_views_referencedbygenrel_changelist")
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.get(url, {TO_FIELD_VAR: "object_id"})
self.assertEqual(response.status_code, 400)
# We also want to prevent the add, change, and delete views from
# leaking a disallowed field value.
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.post(reverse('admin:admin_views_section_add'), {TO_FIELD_VAR: 'name'})
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.post(
+ reverse("admin:admin_views_section_add"), {TO_FIELD_VAR: "name"}
+ )
self.assertEqual(response.status_code, 400)
section = Section.objects.create()
- url = reverse('admin:admin_views_section_change', args=(section.pk,))
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.post(url, {TO_FIELD_VAR: 'name'})
+ url = reverse("admin:admin_views_section_change", args=(section.pk,))
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.post(url, {TO_FIELD_VAR: "name"})
self.assertEqual(response.status_code, 400)
- url = reverse('admin:admin_views_section_delete', args=(section.pk,))
- with self.assertLogs('django.security.DisallowedModelAdminToField', 'ERROR'):
- response = self.client.post(url, {TO_FIELD_VAR: 'name'})
+ url = reverse("admin:admin_views_section_delete", args=(section.pk,))
+ with self.assertLogs("django.security.DisallowedModelAdminToField", "ERROR"):
+ response = self.client.post(url, {TO_FIELD_VAR: "name"})
self.assertEqual(response.status_code, 400)
def test_allowed_filtering_15103(self):
@@ -904,7 +1139,9 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
can break.
"""
# Filters should be allowed if they are defined on a ForeignKey pointing to this model
- url = "%s?leader__name=Palin&leader__age=27" % reverse('admin:admin_views_inquisition_changelist')
+ url = "%s?leader__name=Palin&leader__age=27" % reverse(
+ "admin:admin_views_inquisition_changelist"
+ )
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
@@ -913,7 +1150,9 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
Regression test for ticket 20664 - ensure the pk is properly quoted.
"""
actor = Actor.objects.create(name="Palin", age=27)
- response = self.client.get("%s?%s" % (reverse('admin:admin_views_actor_changelist'), IS_POPUP_VAR))
+ response = self.client.get(
+ "%s?%s" % (reverse("admin:admin_views_actor_changelist"), IS_POPUP_VAR)
+ )
self.assertContains(response, 'data-popup-opener="%s"' % actor.pk)
def test_hide_change_password(self):
@@ -922,14 +1161,15 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
does not have a usable password set.
(against 9bea85795705d015cdadc82c68b99196a8554f5c)
"""
- user = User.objects.get(username='super')
+ user = User.objects.get(username="super")
user.set_unusable_password()
user.save()
self.client.force_login(user)
- response = self.client.get(reverse('admin:index'))
+ response = self.client.get(reverse("admin:index"))
self.assertNotContains(
- response, reverse('admin:password_change'),
- msg_prefix='The "change password" link should not be displayed if a user does not have a usable password.'
+ response,
+ reverse("admin:password_change"),
+ msg_prefix='The "change password" link should not be displayed if a user does not have a usable password.',
)
def test_change_view_with_show_delete_extra_context(self):
@@ -937,20 +1177,31 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
The 'show_delete' context variable in the admin's change view controls
the display of the delete button.
"""
- instance = UndeletableObject.objects.create(name='foo')
- response = self.client.get(reverse('admin:admin_views_undeletableobject_change', args=(instance.pk,)))
- self.assertNotContains(response, 'deletelink')
+ instance = UndeletableObject.objects.create(name="foo")
+ response = self.client.get(
+ reverse("admin:admin_views_undeletableobject_change", args=(instance.pk,))
+ )
+ self.assertNotContains(response, "deletelink")
def test_change_view_logs_m2m_field_changes(self):
"""Changes to ManyToManyFields are included in the object's history."""
- pizza = ReadablePizza.objects.create(name='Cheese')
- cheese = Topping.objects.create(name='cheese')
- post_data = {'name': pizza.name, 'toppings': [cheese.pk]}
- response = self.client.post(reverse('admin:admin_views_readablepizza_change', args=(pizza.pk,)), post_data)
- self.assertRedirects(response, reverse('admin:admin_views_readablepizza_changelist'))
- pizza_ctype = ContentType.objects.get_for_model(ReadablePizza, for_concrete_model=False)
- log = LogEntry.objects.filter(content_type=pizza_ctype, object_id=pizza.pk).first()
- self.assertEqual(log.get_change_message(), 'Changed Toppings.')
+ pizza = ReadablePizza.objects.create(name="Cheese")
+ cheese = Topping.objects.create(name="cheese")
+ post_data = {"name": pizza.name, "toppings": [cheese.pk]}
+ response = self.client.post(
+ reverse("admin:admin_views_readablepizza_change", args=(pizza.pk,)),
+ post_data,
+ )
+ self.assertRedirects(
+ response, reverse("admin:admin_views_readablepizza_changelist")
+ )
+ pizza_ctype = ContentType.objects.get_for_model(
+ ReadablePizza, for_concrete_model=False
+ )
+ log = LogEntry.objects.filter(
+ content_type=pizza_ctype, object_id=pizza.pk
+ ).first()
+ self.assertEqual(log.get_change_message(), "Changed Toppings.")
def test_allows_attributeerror_to_bubble_up(self):
"""
@@ -960,7 +1211,7 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"""
Simple.objects.create()
with self.assertRaises(AttributeError):
- self.client.get(reverse('admin:admin_views_simple_changelist'))
+ self.client.get(reverse("admin:admin_views_simple_changelist"))
def test_changelist_with_no_change_url(self):
"""
@@ -968,282 +1219,337 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
for change_view is removed from get_urls (#20934).
"""
o = UnchangeableObject.objects.create()
- response = self.client.get(reverse('admin:admin_views_unchangeableobject_changelist'))
+ response = self.client.get(
+ reverse("admin:admin_views_unchangeableobject_changelist")
+ )
# Check the format of the shown object -- shouldn't contain a change link
- self.assertContains(response, '<th class="field-__str__">%s</th>' % o, html=True)
+ self.assertContains(
+ response, '<th class="field-__str__">%s</th>' % o, html=True
+ )
def test_invalid_appindex_url(self):
"""
#21056 -- URL reversing shouldn't work for nonexistent apps.
"""
- good_url = '/test_admin/admin/admin_views/'
- confirm_good_url = reverse('admin:app_list',
- kwargs={'app_label': 'admin_views'})
+ good_url = "/test_admin/admin/admin_views/"
+ confirm_good_url = reverse(
+ "admin:app_list", kwargs={"app_label": "admin_views"}
+ )
self.assertEqual(good_url, confirm_good_url)
with self.assertRaises(NoReverseMatch):
- reverse('admin:app_list', kwargs={'app_label': 'this_should_fail'})
+ reverse("admin:app_list", kwargs={"app_label": "this_should_fail"})
with self.assertRaises(NoReverseMatch):
- reverse('admin:app_list', args=('admin_views2',))
+ reverse("admin:app_list", args=("admin_views2",))
def test_resolve_admin_views(self):
- index_match = resolve('/test_admin/admin4/')
- list_match = resolve('/test_admin/admin4/auth/user/')
+ index_match = resolve("/test_admin/admin4/")
+ list_match = resolve("/test_admin/admin4/auth/user/")
self.assertIs(index_match.func.admin_site, customadmin.simple_site)
- self.assertIsInstance(list_match.func.model_admin, customadmin.CustomPwdTemplateUserAdmin)
+ self.assertIsInstance(
+ list_match.func.model_admin, customadmin.CustomPwdTemplateUserAdmin
+ )
def test_adminsite_display_site_url(self):
"""
#13749 - Admin should display link to front-end site 'View site'
"""
- url = reverse('admin:index')
+ url = reverse("admin:index")
response = self.client.get(url)
- self.assertEqual(response.context['site_url'], '/my-site-url/')
+ self.assertEqual(response.context["site_url"], "/my-site-url/")
self.assertContains(response, '<a href="/my-site-url/">View site</a>')
def test_date_hierarchy_empty_queryset(self):
self.assertIs(Question.objects.exists(), False)
- response = self.client.get(reverse('admin:admin_views_answer2_changelist'))
+ response = self.client.get(reverse("admin:admin_views_answer2_changelist"))
self.assertEqual(response.status_code, 200)
- @override_settings(TIME_ZONE='America/Sao_Paulo', USE_TZ=True)
+ @override_settings(TIME_ZONE="America/Sao_Paulo", USE_TZ=True)
def test_date_hierarchy_timezone_dst(self):
# This datetime doesn't exist in this timezone due to DST.
- for date in make_aware_datetimes(datetime.datetime(2016, 10, 16, 15), 'America/Sao_Paulo'):
+ for date in make_aware_datetimes(
+ datetime.datetime(2016, 10, 16, 15), "America/Sao_Paulo"
+ ):
with self.subTest(repr(date.tzinfo)):
- q = Question.objects.create(question='Why?', expires=date)
- Answer2.objects.create(question=q, answer='Because.')
- response = self.client.get(reverse('admin:admin_views_answer2_changelist'))
- self.assertContains(response, 'question__expires__day=16')
- self.assertContains(response, 'question__expires__month=10')
- self.assertContains(response, 'question__expires__year=2016')
-
- @override_settings(TIME_ZONE='America/Los_Angeles', USE_TZ=True)
+ q = Question.objects.create(question="Why?", expires=date)
+ Answer2.objects.create(question=q, answer="Because.")
+ response = self.client.get(
+ reverse("admin:admin_views_answer2_changelist")
+ )
+ self.assertContains(response, "question__expires__day=16")
+ self.assertContains(response, "question__expires__month=10")
+ self.assertContains(response, "question__expires__year=2016")
+
+ @override_settings(TIME_ZONE="America/Los_Angeles", USE_TZ=True)
def test_date_hierarchy_local_date_differ_from_utc(self):
# This datetime is 2017-01-01 in UTC.
- for date in make_aware_datetimes(datetime.datetime(2016, 12, 31, 16), 'America/Los_Angeles'):
+ for date in make_aware_datetimes(
+ datetime.datetime(2016, 12, 31, 16), "America/Los_Angeles"
+ ):
with self.subTest(repr(date.tzinfo)):
- q = Question.objects.create(question='Why?', expires=date)
- Answer2.objects.create(question=q, answer='Because.')
- response = self.client.get(reverse('admin:admin_views_answer2_changelist'))
- self.assertContains(response, 'question__expires__day=31')
- self.assertContains(response, 'question__expires__month=12')
- self.assertContains(response, 'question__expires__year=2016')
+ q = Question.objects.create(question="Why?", expires=date)
+ Answer2.objects.create(question=q, answer="Because.")
+ response = self.client.get(
+ reverse("admin:admin_views_answer2_changelist")
+ )
+ self.assertContains(response, "question__expires__day=31")
+ self.assertContains(response, "question__expires__month=12")
+ self.assertContains(response, "question__expires__year=2016")
def test_sortable_by_columns_subset(self):
- expected_sortable_fields = ('date', 'callable_year')
+ expected_sortable_fields = ("date", "callable_year")
expected_not_sortable_fields = (
- 'content', 'model_year', 'modeladmin_year', 'model_year_reversed',
- 'section',
+ "content",
+ "model_year",
+ "modeladmin_year",
+ "model_year_reversed",
+ "section",
)
- response = self.client.get(reverse('admin6:admin_views_article_changelist'))
+ response = self.client.get(reverse("admin6:admin_views_article_changelist"))
for field_name in expected_sortable_fields:
- self.assertContains(response, '<th scope="col" class="sortable column-%s">' % field_name)
+ self.assertContains(
+ response, '<th scope="col" class="sortable column-%s">' % field_name
+ )
for field_name in expected_not_sortable_fields:
- self.assertContains(response, '<th scope="col" class="column-%s">' % field_name)
+ self.assertContains(
+ response, '<th scope="col" class="column-%s">' % field_name
+ )
def test_get_sortable_by_columns_subset(self):
- response = self.client.get(reverse('admin6:admin_views_actor_changelist'))
+ response = self.client.get(reverse("admin6:admin_views_actor_changelist"))
self.assertContains(response, '<th scope="col" class="sortable column-age">')
self.assertContains(response, '<th scope="col" class="column-name">')
def test_sortable_by_no_column(self):
- expected_not_sortable_fields = ('title', 'book')
- response = self.client.get(reverse('admin6:admin_views_chapter_changelist'))
+ expected_not_sortable_fields = ("title", "book")
+ response = self.client.get(reverse("admin6:admin_views_chapter_changelist"))
for field_name in expected_not_sortable_fields:
- self.assertContains(response, '<th scope="col" class="column-%s">' % field_name)
+ self.assertContains(
+ response, '<th scope="col" class="column-%s">' % field_name
+ )
self.assertNotContains(response, '<th scope="col" class="sortable column')
def test_get_sortable_by_no_column(self):
- response = self.client.get(reverse('admin6:admin_views_color_changelist'))
+ response = self.client.get(reverse("admin6:admin_views_color_changelist"))
self.assertContains(response, '<th scope="col" class="column-value">')
self.assertNotContains(response, '<th scope="col" class="sortable column')
def test_app_index_context(self):
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertContains(
response,
- '<title>Admin_Views administration | Django site admin</title>',
+ "<title>Admin_Views administration | Django site admin</title>",
)
- self.assertEqual(response.context['title'], 'Admin_Views administration')
- self.assertEqual(response.context['app_label'], 'admin_views')
+ self.assertEqual(response.context["title"], "Admin_Views administration")
+ self.assertEqual(response.context["app_label"], "admin_views")
def test_change_view_subtitle_per_object(self):
response = self.client.get(
- reverse('admin:admin_views_article_change', args=(self.a1.pk,)),
+ reverse("admin:admin_views_article_change", args=(self.a1.pk,)),
)
self.assertContains(
response,
- '<title>Article 1 | Change article | Django site admin</title>',
+ "<title>Article 1 | Change article | Django site admin</title>",
)
- self.assertContains(response, '<h1>Change article</h1>')
- self.assertContains(response, '<h2>Article 1</h2>')
+ self.assertContains(response, "<h1>Change article</h1>")
+ self.assertContains(response, "<h2>Article 1</h2>")
response = self.client.get(
- reverse('admin:admin_views_article_change', args=(self.a2.pk,)),
+ reverse("admin:admin_views_article_change", args=(self.a2.pk,)),
)
self.assertContains(
response,
- '<title>Article 2 | Change article | Django site admin</title>',
+ "<title>Article 2 | Change article | Django site admin</title>",
)
- self.assertContains(response, '<h1>Change article</h1>')
- self.assertContains(response, '<h2>Article 2</h2>')
+ self.assertContains(response, "<h1>Change article</h1>")
+ self.assertContains(response, "<h2>Article 2</h2>")
def test_view_subtitle_per_object(self):
viewuser = User.objects.create_user(
- username='viewuser', password='secret', is_staff=True,
+ username="viewuser",
+ password="secret",
+ is_staff=True,
)
viewuser.user_permissions.add(
- get_perm(Article, get_permission_codename('view', Article._meta)),
+ get_perm(Article, get_permission_codename("view", Article._meta)),
)
self.client.force_login(viewuser)
response = self.client.get(
- reverse('admin:admin_views_article_change', args=(self.a1.pk,)),
+ reverse("admin:admin_views_article_change", args=(self.a1.pk,)),
)
self.assertContains(
response,
- '<title>Article 1 | View article | Django site admin</title>',
+ "<title>Article 1 | View article | Django site admin</title>",
)
- self.assertContains(response, '<h1>View article</h1>')
- self.assertContains(response, '<h2>Article 1</h2>')
+ self.assertContains(response, "<h1>View article</h1>")
+ self.assertContains(response, "<h2>Article 1</h2>")
response = self.client.get(
- reverse('admin:admin_views_article_change', args=(self.a2.pk,)),
+ reverse("admin:admin_views_article_change", args=(self.a2.pk,)),
)
self.assertContains(
response,
- '<title>Article 2 | View article | Django site admin</title>',
+ "<title>Article 2 | View article | Django site admin</title>",
)
- self.assertContains(response, '<h1>View article</h1>')
- self.assertContains(response, '<h2>Article 2</h2>')
+ self.assertContains(response, "<h1>View article</h1>")
+ self.assertContains(response, "<h2>Article 2</h2>")
def test_formset_kwargs_can_be_overridden(self):
- response = self.client.get(reverse('admin:admin_views_city_add'))
- self.assertContains(response, 'overridden_name')
+ response = self.client.get(reverse("admin:admin_views_city_add"))
+ self.assertContains(response, "overridden_name")
def test_render_views_no_subtitle(self):
tests = [
- reverse('admin:index'),
- reverse('admin:password_change'),
- reverse('admin:app_list', args=('admin_views',)),
- reverse('admin:admin_views_article_delete', args=(self.a1.pk,)),
- reverse('admin:admin_views_article_history', args=(self.a1.pk,)),
+ reverse("admin:index"),
+ reverse("admin:password_change"),
+ reverse("admin:app_list", args=("admin_views",)),
+ reverse("admin:admin_views_article_delete", args=(self.a1.pk,)),
+ reverse("admin:admin_views_article_history", args=(self.a1.pk,)),
# Login must be after logout.
- reverse('admin:logout'),
- reverse('admin:login'),
+ reverse("admin:logout"),
+ reverse("admin:login"),
]
for url in tests:
with self.subTest(url=url):
- with self.assertNoLogs('django.template', 'DEBUG'):
+ with self.assertNoLogs("django.template", "DEBUG"):
self.client.get(url)
def test_render_delete_selected_confirmation_no_subtitle(self):
post_data = {
- 'action': 'delete_selected',
- 'selected_across': '0',
- 'index': '0',
- '_selected_action': self.a1.pk,
+ "action": "delete_selected",
+ "selected_across": "0",
+ "index": "0",
+ "_selected_action": self.a1.pk,
}
- with self.assertNoLogs('django.template', 'DEBUG'):
- self.client.post(reverse('admin:admin_views_article_changelist'), post_data)
+ with self.assertNoLogs("django.template", "DEBUG"):
+ self.client.post(reverse("admin:admin_views_article_changelist"), post_data)
-@override_settings(TEMPLATES=[{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- # Put this app's and the shared tests templates dirs in DIRS to take precedence
- # over the admin's templates dir.
- 'DIRS': [
- os.path.join(os.path.dirname(__file__), 'templates'),
- os.path.join(os.path.dirname(os.path.dirname(__file__)), 'templates'),
- ],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
-}])
+@override_settings(
+ TEMPLATES=[
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ # Put this app's and the shared tests templates dirs in DIRS to take precedence
+ # over the admin's templates dir.
+ "DIRS": [
+ os.path.join(os.path.dirname(__file__), "templates"),
+ os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates"),
+ ],
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ }
+ ]
+)
class AdminCustomTemplateTests(AdminViewBasicTestCase):
def test_custom_model_admin_templates(self):
# Test custom change list template with custom extra context
- response = self.client.get(reverse('admin:admin_views_customarticle_changelist'))
+ response = self.client.get(
+ reverse("admin:admin_views_customarticle_changelist")
+ )
self.assertContains(response, "var hello = 'Hello!';")
- self.assertTemplateUsed(response, 'custom_admin/change_list.html')
+ self.assertTemplateUsed(response, "custom_admin/change_list.html")
# Test custom add form template
- response = self.client.get(reverse('admin:admin_views_customarticle_add'))
- self.assertTemplateUsed(response, 'custom_admin/add_form.html')
+ response = self.client.get(reverse("admin:admin_views_customarticle_add"))
+ self.assertTemplateUsed(response, "custom_admin/add_form.html")
# Add an article so we can test delete, change, and history views
- post = self.client.post(reverse('admin:admin_views_customarticle_add'), {
- 'content': '<p>great article</p>',
- 'date_0': '2008-03-18',
- 'date_1': '10:54:39'
- })
- self.assertRedirects(post, reverse('admin:admin_views_customarticle_changelist'))
+ post = self.client.post(
+ reverse("admin:admin_views_customarticle_add"),
+ {
+ "content": "<p>great article</p>",
+ "date_0": "2008-03-18",
+ "date_1": "10:54:39",
+ },
+ )
+ self.assertRedirects(
+ post, reverse("admin:admin_views_customarticle_changelist")
+ )
self.assertEqual(CustomArticle.objects.all().count(), 1)
article_pk = CustomArticle.objects.all()[0].pk
# Test custom delete, change, and object history templates
# Test custom change form template
- response = self.client.get(reverse('admin:admin_views_customarticle_change', args=(article_pk,)))
- self.assertTemplateUsed(response, 'custom_admin/change_form.html')
- response = self.client.get(reverse('admin:admin_views_customarticle_delete', args=(article_pk,)))
- self.assertTemplateUsed(response, 'custom_admin/delete_confirmation.html')
- response = self.client.post(reverse('admin:admin_views_customarticle_changelist'), data={
- 'index': 0,
- 'action': ['delete_selected'],
- '_selected_action': ['1'],
- })
- self.assertTemplateUsed(response, 'custom_admin/delete_selected_confirmation.html')
- response = self.client.get(reverse('admin:admin_views_customarticle_history', args=(article_pk,)))
- self.assertTemplateUsed(response, 'custom_admin/object_history.html')
+ response = self.client.get(
+ reverse("admin:admin_views_customarticle_change", args=(article_pk,))
+ )
+ self.assertTemplateUsed(response, "custom_admin/change_form.html")
+ response = self.client.get(
+ reverse("admin:admin_views_customarticle_delete", args=(article_pk,))
+ )
+ self.assertTemplateUsed(response, "custom_admin/delete_confirmation.html")
+ response = self.client.post(
+ reverse("admin:admin_views_customarticle_changelist"),
+ data={
+ "index": 0,
+ "action": ["delete_selected"],
+ "_selected_action": ["1"],
+ },
+ )
+ self.assertTemplateUsed(
+ response, "custom_admin/delete_selected_confirmation.html"
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_customarticle_history", args=(article_pk,))
+ )
+ self.assertTemplateUsed(response, "custom_admin/object_history.html")
# A custom popup response template may be specified by
# ModelAdmin.popup_response_template.
- response = self.client.post(reverse('admin:admin_views_customarticle_add') + '?%s=1' % IS_POPUP_VAR, {
- 'content': '<p>great article</p>',
- 'date_0': '2008-03-18',
- 'date_1': '10:54:39',
- IS_POPUP_VAR: '1'
- })
- self.assertEqual(response.template_name, 'custom_admin/popup_response.html')
+ response = self.client.post(
+ reverse("admin:admin_views_customarticle_add") + "?%s=1" % IS_POPUP_VAR,
+ {
+ "content": "<p>great article</p>",
+ "date_0": "2008-03-18",
+ "date_1": "10:54:39",
+ IS_POPUP_VAR: "1",
+ },
+ )
+ self.assertEqual(response.template_name, "custom_admin/popup_response.html")
def test_extended_bodyclass_template_change_form(self):
"""
The admin/change_form.html template uses block.super in the
bodyclass block.
"""
- response = self.client.get(reverse('admin:admin_views_section_add'))
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.get(reverse("admin:admin_views_section_add"))
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_change_password_template(self):
- user = User.objects.get(username='super')
- response = self.client.get(reverse('admin:auth_user_password_change', args=(user.id,)))
+ user = User.objects.get(username="super")
+ response = self.client.get(
+ reverse("admin:auth_user_password_change", args=(user.id,))
+ )
# The auth/user/change_password.html template uses super in the
# bodyclass block.
- self.assertContains(response, 'bodyclass_consistency_check ')
+ self.assertContains(response, "bodyclass_consistency_check ")
# When a site has multiple passwords in the browser's password manager,
# a browser pop up asks which user the new password is for. To prevent
# this, the username is added to the change password form.
- self.assertContains(response, '<input type="text" name="username" value="super" class="hidden">')
+ self.assertContains(
+ response, '<input type="text" name="username" value="super" class="hidden">'
+ )
def test_extended_bodyclass_template_index(self):
"""
The admin/index.html template uses block.super in the bodyclass block.
"""
- response = self.client.get(reverse('admin:index'))
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.get(reverse("admin:index"))
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_extended_bodyclass_change_list(self):
"""
The admin/change_list.html' template uses block.super
in the bodyclass block.
"""
- response = self.client.get(reverse('admin:admin_views_article_changelist'))
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.get(reverse("admin:admin_views_article_changelist"))
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_extended_bodyclass_template_login(self):
"""
@@ -1251,8 +1557,8 @@ class AdminCustomTemplateTests(AdminViewBasicTestCase):
bodyclass block.
"""
self.client.logout()
- response = self.client.get(reverse('admin:login'))
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.get(reverse("admin:login"))
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_extended_bodyclass_template_delete_confirmation(self):
"""
@@ -1260,8 +1566,8 @@ class AdminCustomTemplateTests(AdminViewBasicTestCase):
block.super in the bodyclass block.
"""
group = Group.objects.create(name="foogroup")
- response = self.client.get(reverse('admin:auth_group_delete', args=(group.id,)))
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.get(reverse("admin:auth_group_delete", args=(group.id,)))
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_extended_bodyclass_template_delete_selected_confirmation(self):
"""
@@ -1270,41 +1576,51 @@ class AdminCustomTemplateTests(AdminViewBasicTestCase):
"""
group = Group.objects.create(name="foogroup")
post_data = {
- 'action': 'delete_selected',
- 'selected_across': '0',
- 'index': '0',
- '_selected_action': group.id
+ "action": "delete_selected",
+ "selected_across": "0",
+ "index": "0",
+ "_selected_action": group.id,
}
- response = self.client.post(reverse('admin:auth_group_changelist'), post_data)
- self.assertEqual(response.context['site_header'], 'Django administration')
- self.assertContains(response, 'bodyclass_consistency_check ')
+ response = self.client.post(reverse("admin:auth_group_changelist"), post_data)
+ self.assertEqual(response.context["site_header"], "Django administration")
+ self.assertContains(response, "bodyclass_consistency_check ")
def test_filter_with_custom_template(self):
"""
A custom template can be used to render an admin filter.
"""
- response = self.client.get(reverse('admin:admin_views_color2_changelist'))
- self.assertTemplateUsed(response, 'custom_filter_template.html')
+ response = self.client.get(reverse("admin:admin_views_color2_changelist"))
+ self.assertTemplateUsed(response, "custom_filter_template.html")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewFormUrlTest(TestCase):
current_app = "admin3"
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
def setUp(self):
self.client.force_login(self.superuser)
@@ -1314,10 +1630,16 @@ class AdminViewFormUrlTest(TestCase):
change_view has form_url in response.context
"""
response = self.client.get(
- reverse('admin:admin_views_section_change', args=(self.s1.pk,), current_app=self.current_app)
+ reverse(
+ "admin:admin_views_section_change",
+ args=(self.s1.pk,),
+ current_app=self.current_app,
+ )
)
- self.assertIn('form_url', response.context, msg='form_url not present in response.context')
- self.assertEqual(response.context['form_url'], 'pony')
+ self.assertIn(
+ "form_url", response.context, msg="form_url not present in response.context"
+ )
+ self.assertEqual(response.context["form_url"], "pony")
def test_initial_data_can_be_overridden(self):
"""
@@ -1325,8 +1647,8 @@ class AdminViewFormUrlTest(TestCase):
ModelAdmin class. Usually, the initial value is set via the GET params.
"""
response = self.client.get(
- reverse('admin:admin_views_restaurant_add', current_app=self.current_app),
- {'name': 'test_value'}
+ reverse("admin:admin_views_restaurant_add", current_app=self.current_app),
+ {"name": "test_value"},
)
# this would be the usual behaviour
self.assertNotContains(response, 'value="test_value"')
@@ -1334,12 +1656,13 @@ class AdminViewFormUrlTest(TestCase):
self.assertContains(response, 'value="overridden_value"')
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminJavaScriptTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -1349,54 +1672,66 @@ class AdminJavaScriptTest(TestCase):
The minified versions of the JS files are only used when DEBUG is False.
"""
with override_settings(DEBUG=False):
- response = self.client.get(reverse('admin:admin_views_section_add'))
- self.assertNotContains(response, 'vendor/jquery/jquery.js')
- self.assertContains(response, 'vendor/jquery/jquery.min.js')
- self.assertContains(response, 'prepopulate.js')
- self.assertContains(response, 'actions.js')
- self.assertContains(response, 'collapse.js')
- self.assertContains(response, 'inlines.js')
+ response = self.client.get(reverse("admin:admin_views_section_add"))
+ self.assertNotContains(response, "vendor/jquery/jquery.js")
+ self.assertContains(response, "vendor/jquery/jquery.min.js")
+ self.assertContains(response, "prepopulate.js")
+ self.assertContains(response, "actions.js")
+ self.assertContains(response, "collapse.js")
+ self.assertContains(response, "inlines.js")
with override_settings(DEBUG=True):
- response = self.client.get(reverse('admin:admin_views_section_add'))
- self.assertContains(response, 'vendor/jquery/jquery.js')
- self.assertNotContains(response, 'vendor/jquery/jquery.min.js')
- self.assertContains(response, 'prepopulate.js')
- self.assertContains(response, 'actions.js')
- self.assertContains(response, 'collapse.js')
- self.assertContains(response, 'inlines.js')
+ response = self.client.get(reverse("admin:admin_views_section_add"))
+ self.assertContains(response, "vendor/jquery/jquery.js")
+ self.assertNotContains(response, "vendor/jquery/jquery.min.js")
+ self.assertContains(response, "prepopulate.js")
+ self.assertContains(response, "actions.js")
+ self.assertContains(response, "collapse.js")
+ self.assertContains(response, "inlines.js")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class SaveAsTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.per1 = Person.objects.create(name='John Mauchly', gender=1, alive=True)
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.per1 = Person.objects.create(name="John Mauchly", gender=1, alive=True)
def setUp(self):
self.client.force_login(self.superuser)
def test_save_as_duplication(self):
"""'save as' creates a new person"""
- post_data = {'_saveasnew': '', 'name': 'John M', 'gender': 1, 'age': 42}
- response = self.client.post(reverse('admin:admin_views_person_change', args=(self.per1.pk,)), post_data)
- self.assertEqual(len(Person.objects.filter(name='John M')), 1)
+ post_data = {"_saveasnew": "", "name": "John M", "gender": 1, "age": 42}
+ response = self.client.post(
+ reverse("admin:admin_views_person_change", args=(self.per1.pk,)), post_data
+ )
+ self.assertEqual(len(Person.objects.filter(name="John M")), 1)
self.assertEqual(len(Person.objects.filter(id=self.per1.pk)), 1)
- new_person = Person.objects.latest('id')
- self.assertRedirects(response, reverse('admin:admin_views_person_change', args=(new_person.pk,)))
+ new_person = Person.objects.latest("id")
+ self.assertRedirects(
+ response, reverse("admin:admin_views_person_change", args=(new_person.pk,))
+ )
def test_save_as_continue_false(self):
"""
Saving a new object using "Save as new" redirects to the changelist
instead of the change view when ModelAdmin.save_as_continue=False.
"""
- post_data = {'_saveasnew': '', 'name': 'John M', 'gender': 1, 'age': 42}
- url = reverse('admin:admin_views_person_change', args=(self.per1.pk,), current_app=site2.name)
+ post_data = {"_saveasnew": "", "name": "John M", "gender": 1, "age": 42}
+ url = reverse(
+ "admin:admin_views_person_change",
+ args=(self.per1.pk,),
+ current_app=site2.name,
+ )
response = self.client.post(url, post_data)
- self.assertEqual(len(Person.objects.filter(name='John M')), 1)
+ self.assertEqual(len(Person.objects.filter(name="John M")), 1)
self.assertEqual(len(Person.objects.filter(id=self.per1.pk)), 1)
- self.assertRedirects(response, reverse('admin:admin_views_person_changelist', current_app=site2.name))
+ self.assertRedirects(
+ response,
+ reverse("admin:admin_views_person_changelist", current_app=site2.name),
+ )
def test_save_as_new_with_validation_errors(self):
"""
@@ -1404,124 +1739,142 @@ class SaveAsTests(TestCase):
you only see the "Save as new" button and not the other save buttons,
and that only the "Save as" button is visible.
"""
- response = self.client.post(reverse('admin:admin_views_person_change', args=(self.per1.pk,)), {
- '_saveasnew': '',
- 'gender': 'invalid',
- '_addanother': 'fail',
- })
- self.assertContains(response, 'Please correct the errors below.')
- self.assertFalse(response.context['show_save_and_add_another'])
- self.assertFalse(response.context['show_save_and_continue'])
- self.assertTrue(response.context['show_save_as_new'])
+ response = self.client.post(
+ reverse("admin:admin_views_person_change", args=(self.per1.pk,)),
+ {
+ "_saveasnew": "",
+ "gender": "invalid",
+ "_addanother": "fail",
+ },
+ )
+ self.assertContains(response, "Please correct the errors below.")
+ self.assertFalse(response.context["show_save_and_add_another"])
+ self.assertFalse(response.context["show_save_and_continue"])
+ self.assertTrue(response.context["show_save_as_new"])
def test_save_as_new_with_validation_errors_with_inlines(self):
- parent = Parent.objects.create(name='Father')
- child = Child.objects.create(parent=parent, name='Child')
- response = self.client.post(reverse('admin:admin_views_parent_change', args=(parent.pk,)), {
- '_saveasnew': 'Save as new',
- 'child_set-0-parent': parent.pk,
- 'child_set-0-id': child.pk,
- 'child_set-0-name': 'Child',
- 'child_set-INITIAL_FORMS': 1,
- 'child_set-MAX_NUM_FORMS': 1000,
- 'child_set-MIN_NUM_FORMS': 0,
- 'child_set-TOTAL_FORMS': 4,
- 'name': '_invalid',
- })
- self.assertContains(response, 'Please correct the error below.')
- self.assertFalse(response.context['show_save_and_add_another'])
- self.assertFalse(response.context['show_save_and_continue'])
- self.assertTrue(response.context['show_save_as_new'])
+ parent = Parent.objects.create(name="Father")
+ child = Child.objects.create(parent=parent, name="Child")
+ response = self.client.post(
+ reverse("admin:admin_views_parent_change", args=(parent.pk,)),
+ {
+ "_saveasnew": "Save as new",
+ "child_set-0-parent": parent.pk,
+ "child_set-0-id": child.pk,
+ "child_set-0-name": "Child",
+ "child_set-INITIAL_FORMS": 1,
+ "child_set-MAX_NUM_FORMS": 1000,
+ "child_set-MIN_NUM_FORMS": 0,
+ "child_set-TOTAL_FORMS": 4,
+ "name": "_invalid",
+ },
+ )
+ self.assertContains(response, "Please correct the error below.")
+ self.assertFalse(response.context["show_save_and_add_another"])
+ self.assertFalse(response.context["show_save_and_continue"])
+ self.assertTrue(response.context["show_save_as_new"])
def test_save_as_new_with_inlines_with_validation_errors(self):
- parent = Parent.objects.create(name='Father')
- child = Child.objects.create(parent=parent, name='Child')
- response = self.client.post(reverse('admin:admin_views_parent_change', args=(parent.pk,)), {
- '_saveasnew': 'Save as new',
- 'child_set-0-parent': parent.pk,
- 'child_set-0-id': child.pk,
- 'child_set-0-name': '_invalid',
- 'child_set-INITIAL_FORMS': 1,
- 'child_set-MAX_NUM_FORMS': 1000,
- 'child_set-MIN_NUM_FORMS': 0,
- 'child_set-TOTAL_FORMS': 4,
- 'name': 'Father',
- })
- self.assertContains(response, 'Please correct the error below.')
- self.assertFalse(response.context['show_save_and_add_another'])
- self.assertFalse(response.context['show_save_and_continue'])
- self.assertTrue(response.context['show_save_as_new'])
-
-
-@override_settings(ROOT_URLCONF='admin_views.urls')
-class CustomModelAdminTest(AdminViewBasicTestCase):
+ parent = Parent.objects.create(name="Father")
+ child = Child.objects.create(parent=parent, name="Child")
+ response = self.client.post(
+ reverse("admin:admin_views_parent_change", args=(parent.pk,)),
+ {
+ "_saveasnew": "Save as new",
+ "child_set-0-parent": parent.pk,
+ "child_set-0-id": child.pk,
+ "child_set-0-name": "_invalid",
+ "child_set-INITIAL_FORMS": 1,
+ "child_set-MAX_NUM_FORMS": 1000,
+ "child_set-MIN_NUM_FORMS": 0,
+ "child_set-TOTAL_FORMS": 4,
+ "name": "Father",
+ },
+ )
+ self.assertContains(response, "Please correct the error below.")
+ self.assertFalse(response.context["show_save_and_add_another"])
+ self.assertFalse(response.context["show_save_and_continue"])
+ self.assertTrue(response.context["show_save_as_new"])
+
+@override_settings(ROOT_URLCONF="admin_views.urls")
+class CustomModelAdminTest(AdminViewBasicTestCase):
def test_custom_admin_site_login_form(self):
self.client.logout()
- response = self.client.get(reverse('admin2:index'), follow=True)
+ response = self.client.get(reverse("admin2:index"), follow=True)
self.assertIsInstance(response, TemplateResponse)
self.assertEqual(response.status_code, 200)
- login = self.client.post(reverse('admin2:login'), {
- REDIRECT_FIELD_NAME: reverse('admin2:index'),
- 'username': 'customform',
- 'password': 'secret',
- }, follow=True)
+ login = self.client.post(
+ reverse("admin2:login"),
+ {
+ REDIRECT_FIELD_NAME: reverse("admin2:index"),
+ "username": "customform",
+ "password": "secret",
+ },
+ follow=True,
+ )
self.assertIsInstance(login, TemplateResponse)
- self.assertContains(login, 'custom form error')
- self.assertContains(login, 'path/to/media.css')
+ self.assertContains(login, "custom form error")
+ self.assertContains(login, "path/to/media.css")
def test_custom_admin_site_login_template(self):
self.client.logout()
- response = self.client.get(reverse('admin2:index'), follow=True)
+ response = self.client.get(reverse("admin2:index"), follow=True)
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/login.html')
- self.assertContains(response, 'Hello from a custom login template')
+ self.assertTemplateUsed(response, "custom_admin/login.html")
+ self.assertContains(response, "Hello from a custom login template")
def test_custom_admin_site_logout_template(self):
- response = self.client.get(reverse('admin2:logout'))
+ response = self.client.get(reverse("admin2:logout"))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/logout.html')
- self.assertContains(response, 'Hello from a custom logout template')
+ self.assertTemplateUsed(response, "custom_admin/logout.html")
+ self.assertContains(response, "Hello from a custom logout template")
def test_custom_admin_site_index_view_and_template(self):
- response = self.client.get(reverse('admin2:index'))
+ response = self.client.get(reverse("admin2:index"))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/index.html')
- self.assertContains(response, 'Hello from a custom index template *bar*')
+ self.assertTemplateUsed(response, "custom_admin/index.html")
+ self.assertContains(response, "Hello from a custom index template *bar*")
def test_custom_admin_site_app_index_view_and_template(self):
- response = self.client.get(reverse('admin2:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin2:app_list", args=("admin_views",)))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/app_index.html')
- self.assertContains(response, 'Hello from a custom app_index template')
+ self.assertTemplateUsed(response, "custom_admin/app_index.html")
+ self.assertContains(response, "Hello from a custom app_index template")
def test_custom_admin_site_password_change_template(self):
- response = self.client.get(reverse('admin2:password_change'))
+ response = self.client.get(reverse("admin2:password_change"))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/password_change_form.html')
- self.assertContains(response, 'Hello from a custom password change form template')
+ self.assertTemplateUsed(response, "custom_admin/password_change_form.html")
+ self.assertContains(
+ response, "Hello from a custom password change form template"
+ )
def test_custom_admin_site_password_change_with_extra_context(self):
- response = self.client.get(reverse('admin2:password_change'))
+ response = self.client.get(reverse("admin2:password_change"))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/password_change_form.html')
- self.assertContains(response, 'eggs')
+ self.assertTemplateUsed(response, "custom_admin/password_change_form.html")
+ self.assertContains(response, "eggs")
def test_custom_admin_site_password_change_done_template(self):
- response = self.client.get(reverse('admin2:password_change_done'))
+ response = self.client.get(reverse("admin2:password_change_done"))
self.assertIsInstance(response, TemplateResponse)
- self.assertTemplateUsed(response, 'custom_admin/password_change_done.html')
- self.assertContains(response, 'Hello from a custom password change done template')
+ self.assertTemplateUsed(response, "custom_admin/password_change_done.html")
+ self.assertContains(
+ response, "Hello from a custom password change done template"
+ )
def test_custom_admin_site_view(self):
self.client.force_login(self.superuser)
- response = self.client.get(reverse('admin2:my_view'))
+ response = self.client.get(reverse("admin2:my_view"))
self.assertEqual(response.content, b"Django is a magical pony!")
def test_pwd_change_custom_template(self):
self.client.force_login(self.superuser)
- su = User.objects.get(username='super')
- response = self.client.get(reverse('admin4:auth_user_password_change', args=(su.pk,)))
+ su = User.objects.get(username="super")
+ response = self.client.get(
+ reverse("admin4:auth_user_password_change", args=(su.pk,))
+ )
self.assertEqual(response.status_code, 200)
@@ -1532,110 +1885,146 @@ def get_perm(Model, codename):
@override_settings(
- ROOT_URLCONF='admin_views.urls',
+ ROOT_URLCONF="admin_views.urls",
# Test with the admin's documented list of required context processors.
- TEMPLATES=[{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- }],
+ TEMPLATES=[
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ }
+ ],
)
class AdminViewPermissionsTest(TestCase):
"""Tests for Admin Views Permissions."""
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.viewuser = User.objects.create_user(username='viewuser', password='secret', is_staff=True)
- cls.adduser = User.objects.create_user(username='adduser', password='secret', is_staff=True)
- cls.changeuser = User.objects.create_user(username='changeuser', password='secret', is_staff=True)
- cls.deleteuser = User.objects.create_user(username='deleteuser', password='secret', is_staff=True)
- cls.joepublicuser = User.objects.create_user(username='joepublic', password='secret')
- cls.nostaffuser = User.objects.create_user(username='nostaff', password='secret')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.viewuser = User.objects.create_user(
+ username="viewuser", password="secret", is_staff=True
+ )
+ cls.adduser = User.objects.create_user(
+ username="adduser", password="secret", is_staff=True
+ )
+ cls.changeuser = User.objects.create_user(
+ username="changeuser", password="secret", is_staff=True
+ )
+ cls.deleteuser = User.objects.create_user(
+ username="deleteuser", password="secret", is_staff=True
+ )
+ cls.joepublicuser = User.objects.create_user(
+ username="joepublic", password="secret"
+ )
+ cls.nostaffuser = User.objects.create_user(
+ username="nostaff", password="secret"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1,
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
another_section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
# Setup permissions, for our users who can add, change, and delete.
opts = Article._meta
# User who can view Articles
- cls.viewuser.user_permissions.add(get_perm(Article, get_permission_codename('view', opts)))
+ cls.viewuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("view", opts))
+ )
# User who can add Articles
- cls.adduser.user_permissions.add(get_perm(Article, get_permission_codename('add', opts)))
+ cls.adduser.user_permissions.add(
+ get_perm(Article, get_permission_codename("add", opts))
+ )
# User who can change Articles
- cls.changeuser.user_permissions.add(get_perm(Article, get_permission_codename('change', opts)))
- cls.nostaffuser.user_permissions.add(get_perm(Article, get_permission_codename('change', opts)))
+ cls.changeuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("change", opts))
+ )
+ cls.nostaffuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("change", opts))
+ )
# User who can delete Articles
- cls.deleteuser.user_permissions.add(get_perm(Article, get_permission_codename('delete', opts)))
- cls.deleteuser.user_permissions.add(get_perm(Section, get_permission_codename('delete', Section._meta)))
+ cls.deleteuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("delete", opts))
+ )
+ cls.deleteuser.user_permissions.add(
+ get_perm(Section, get_permission_codename("delete", Section._meta))
+ )
# login POST dicts
- cls.index_url = reverse('admin:index')
+ cls.index_url = reverse("admin:index")
cls.super_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'super',
- 'password': 'secret',
+ "username": "super",
+ "password": "secret",
}
cls.super_email_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'super@example.com',
- 'password': 'secret',
+ "username": "super@example.com",
+ "password": "secret",
}
cls.super_email_bad_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'super@example.com',
- 'password': 'notsecret',
+ "username": "super@example.com",
+ "password": "notsecret",
}
cls.adduser_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'adduser',
- 'password': 'secret',
+ "username": "adduser",
+ "password": "secret",
}
cls.changeuser_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'changeuser',
- 'password': 'secret',
+ "username": "changeuser",
+ "password": "secret",
}
cls.deleteuser_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'deleteuser',
- 'password': 'secret',
+ "username": "deleteuser",
+ "password": "secret",
}
cls.nostaff_login = {
- REDIRECT_FIELD_NAME: reverse('has_permission_admin:index'),
- 'username': 'nostaff',
- 'password': 'secret',
+ REDIRECT_FIELD_NAME: reverse("has_permission_admin:index"),
+ "username": "nostaff",
+ "password": "secret",
}
cls.joepublic_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'joepublic',
- 'password': 'secret',
+ "username": "joepublic",
+ "password": "secret",
}
cls.viewuser_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'username': 'viewuser',
- 'password': 'secret',
+ "username": "viewuser",
+ "password": "secret",
}
cls.no_username_login = {
REDIRECT_FIELD_NAME: cls.index_url,
- 'password': 'secret',
+ "password": "secret",
}
def test_login(self):
@@ -1646,14 +2035,14 @@ class AdminViewPermissionsTest(TestCase):
Unsuccessful attempts will continue to render the login page with
a 200 status code.
"""
- login_url = '%s?next=%s' % (reverse('admin:login'), reverse('admin:index'))
+ login_url = "%s?next=%s" % (reverse("admin:login"), reverse("admin:index"))
# Super User
response = self.client.get(self.index_url)
self.assertRedirects(response, login_url)
login = self.client.post(login_url, self.super_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Test if user enters email address
response = self.client.get(self.index_url)
@@ -1663,7 +2052,7 @@ class AdminViewPermissionsTest(TestCase):
# only correct passwords get a username hint
login = self.client.post(login_url, self.super_email_bad_login)
self.assertContains(login, ERROR_MESSAGE)
- new_user = User(username='jondoe', password='secret', email='super@example.com')
+ new_user = User(username="jondoe", password="secret", email="super@example.com")
new_user.save()
# check to ensure if there are multiple email addresses a user doesn't get a 500
login = self.client.post(login_url, self.super_email_login)
@@ -1675,7 +2064,7 @@ class AdminViewPermissionsTest(TestCase):
login = self.client.post(login_url, self.viewuser_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Add User
response = self.client.get(self.index_url)
@@ -1683,7 +2072,7 @@ class AdminViewPermissionsTest(TestCase):
login = self.client.post(login_url, self.adduser_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Change User
response = self.client.get(self.index_url)
@@ -1691,7 +2080,7 @@ class AdminViewPermissionsTest(TestCase):
login = self.client.post(login_url, self.changeuser_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Delete User
response = self.client.get(self.index_url)
@@ -1699,7 +2088,7 @@ class AdminViewPermissionsTest(TestCase):
login = self.client.post(login_url, self.deleteuser_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Regular User should not be able to login.
response = self.client.get(self.index_url)
@@ -1712,60 +2101,67 @@ class AdminViewPermissionsTest(TestCase):
self.assertEqual(response.status_code, 302)
login = self.client.post(login_url, self.no_username_login)
self.assertEqual(login.status_code, 200)
- self.assertFormError(login, 'form', 'username', ['This field is required.'])
+ self.assertFormError(login, "form", "username", ["This field is required."])
def test_login_redirect_for_direct_get(self):
"""
Login redirect should be to the admin index page when going directly to
/admin/login/.
"""
- response = self.client.get(reverse('admin:login'))
+ response = self.client.get(reverse("admin:login"))
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context[REDIRECT_FIELD_NAME], reverse('admin:index'))
+ self.assertEqual(response.context[REDIRECT_FIELD_NAME], reverse("admin:index"))
def test_login_has_permission(self):
# Regular User should not be able to login.
- response = self.client.get(reverse('has_permission_admin:index'))
+ response = self.client.get(reverse("has_permission_admin:index"))
self.assertEqual(response.status_code, 302)
- login = self.client.post(reverse('has_permission_admin:login'), self.joepublic_login)
- self.assertContains(login, 'permission denied')
+ login = self.client.post(
+ reverse("has_permission_admin:login"), self.joepublic_login
+ )
+ self.assertContains(login, "permission denied")
# User with permissions should be able to login.
- response = self.client.get(reverse('has_permission_admin:index'))
+ response = self.client.get(reverse("has_permission_admin:index"))
self.assertEqual(response.status_code, 302)
- login = self.client.post(reverse('has_permission_admin:login'), self.nostaff_login)
- self.assertRedirects(login, reverse('has_permission_admin:index'))
+ login = self.client.post(
+ reverse("has_permission_admin:login"), self.nostaff_login
+ )
+ self.assertRedirects(login, reverse("has_permission_admin:index"))
self.assertFalse(login.context)
- self.client.get(reverse('has_permission_admin:logout'))
+ self.client.get(reverse("has_permission_admin:logout"))
# Staff should be able to login.
- response = self.client.get(reverse('has_permission_admin:index'))
+ response = self.client.get(reverse("has_permission_admin:index"))
self.assertEqual(response.status_code, 302)
- login = self.client.post(reverse('has_permission_admin:login'), {
- REDIRECT_FIELD_NAME: reverse('has_permission_admin:index'),
- 'username': 'deleteuser',
- 'password': 'secret',
- })
- self.assertRedirects(login, reverse('has_permission_admin:index'))
+ login = self.client.post(
+ reverse("has_permission_admin:login"),
+ {
+ REDIRECT_FIELD_NAME: reverse("has_permission_admin:index"),
+ "username": "deleteuser",
+ "password": "secret",
+ },
+ )
+ self.assertRedirects(login, reverse("has_permission_admin:index"))
self.assertFalse(login.context)
- self.client.get(reverse('has_permission_admin:logout'))
+ self.client.get(reverse("has_permission_admin:logout"))
def test_login_successfully_redirects_to_original_URL(self):
response = self.client.get(self.index_url)
self.assertEqual(response.status_code, 302)
- query_string = 'the-answer=42'
- redirect_url = '%s?%s' % (self.index_url, query_string)
+ query_string = "the-answer=42"
+ redirect_url = "%s?%s" % (self.index_url, query_string)
new_next = {REDIRECT_FIELD_NAME: redirect_url}
post_data = self.super_login.copy()
post_data.pop(REDIRECT_FIELD_NAME)
login = self.client.post(
- '%s?%s' % (reverse('admin:login'), urlencode(new_next)),
- post_data)
+ "%s?%s" % (reverse("admin:login"), urlencode(new_next)), post_data
+ )
self.assertRedirects(login, redirect_url)
def test_double_login_is_not_allowed(self):
"""Regression test for #19327"""
- login_url = '%s?next=%s' % (reverse('admin:login'), reverse('admin:index'))
+ login_url = "%s?next=%s" % (reverse("admin:login"), reverse("admin:index"))
response = self.client.get(self.index_url)
self.assertEqual(response.status_code, 302)
@@ -1788,7 +2184,7 @@ class AdminViewPermissionsTest(TestCase):
login = self.client.post(login_url, self.super_login)
self.assertRedirects(login, self.index_url)
self.assertFalse(login.context)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
def test_login_page_notice_for_non_staff_users(self):
"""
@@ -1796,76 +2192,93 @@ class AdminViewPermissionsTest(TestCase):
presented with the login page and a hint indicating that the current
user doesn't have access to it.
"""
- hint_template = 'You are authenticated as {}'
+ hint_template = "You are authenticated as {}"
# Anonymous user should not be shown the hint
response = self.client.get(self.index_url, follow=True)
- self.assertContains(response, 'login-form')
- self.assertNotContains(response, hint_template.format(''), status_code=200)
+ self.assertContains(response, "login-form")
+ self.assertNotContains(response, hint_template.format(""), status_code=200)
# Non-staff user should be shown the hint
self.client.force_login(self.nostaffuser)
response = self.client.get(self.index_url, follow=True)
- self.assertContains(response, 'login-form')
- self.assertContains(response, hint_template.format(self.nostaffuser.username), status_code=200)
+ self.assertContains(response, "login-form")
+ self.assertContains(
+ response, hint_template.format(self.nostaffuser.username), status_code=200
+ )
def test_add_view(self):
"""Test add view restricts access and actually adds items."""
add_dict = {
- 'title': 'Døm ikke',
- 'content': '<p>great article</p>',
- 'date_0': '2008-03-18', 'date_1': '10:54:39',
- 'section': self.s1.pk,
+ "title": "Døm ikke",
+ "content": "<p>great article</p>",
+ "date_0": "2008-03-18",
+ "date_1": "10:54:39",
+ "section": self.s1.pk,
}
# Change User should not have access to add articles
self.client.force_login(self.changeuser)
# make sure the view removes test cookie
self.assertIs(self.client.session.test_cookie_worked(), False)
- response = self.client.get(reverse('admin:admin_views_article_add'))
+ response = self.client.get(reverse("admin:admin_views_article_add"))
self.assertEqual(response.status_code, 403)
# Try POST just to make sure
- post = self.client.post(reverse('admin:admin_views_article_add'), add_dict)
+ post = self.client.post(reverse("admin:admin_views_article_add"), add_dict)
self.assertEqual(post.status_code, 403)
self.assertEqual(Article.objects.count(), 3)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# View User should not have access to add articles
self.client.force_login(self.viewuser)
- response = self.client.get(reverse('admin:admin_views_article_add'))
+ response = self.client.get(reverse("admin:admin_views_article_add"))
self.assertEqual(response.status_code, 403)
# Try POST just to make sure
- post = self.client.post(reverse('admin:admin_views_article_add'), add_dict)
+ post = self.client.post(reverse("admin:admin_views_article_add"), add_dict)
self.assertEqual(post.status_code, 403)
self.assertEqual(Article.objects.count(), 3)
# Now give the user permission to add but not change.
- self.viewuser.user_permissions.add(get_perm(Article, get_permission_codename('add', Article._meta)))
- response = self.client.get(reverse('admin:admin_views_article_add'))
- self.assertEqual(response.context['title'], 'Add article')
- self.assertContains(response, '<title>Add article | Django site admin</title>')
- self.assertContains(response, '<input type="submit" value="Save and view" name="_continue">')
- post = self.client.post(reverse('admin:admin_views_article_add'), add_dict, follow=False)
+ self.viewuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("add", Article._meta))
+ )
+ response = self.client.get(reverse("admin:admin_views_article_add"))
+ self.assertEqual(response.context["title"], "Add article")
+ self.assertContains(response, "<title>Add article | Django site admin</title>")
+ self.assertContains(
+ response, '<input type="submit" value="Save and view" name="_continue">'
+ )
+ post = self.client.post(
+ reverse("admin:admin_views_article_add"), add_dict, follow=False
+ )
self.assertEqual(post.status_code, 302)
self.assertEqual(Article.objects.count(), 4)
- article = Article.objects.latest('pk')
- response = self.client.get(reverse('admin:admin_views_article_change', args=(article.pk,)))
- self.assertContains(response, '<li class="success">The article “Døm ikke” was added successfully.</li>')
+ article = Article.objects.latest("pk")
+ response = self.client.get(
+ reverse("admin:admin_views_article_change", args=(article.pk,))
+ )
+ self.assertContains(
+ response,
+ '<li class="success">The article “Døm ikke” was added successfully.</li>',
+ )
article.delete()
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Add user may login and POST to add view, then redirect to admin root
self.client.force_login(self.adduser)
- addpage = self.client.get(reverse('admin:admin_views_article_add'))
- change_list_link = '&rsaquo; <a href="%s">Articles</a>' % reverse('admin:admin_views_article_changelist')
+ addpage = self.client.get(reverse("admin:admin_views_article_add"))
+ change_list_link = '&rsaquo; <a href="%s">Articles</a>' % reverse(
+ "admin:admin_views_article_changelist"
+ )
self.assertNotContains(
- addpage, change_list_link,
- msg_prefix='User restricted to add permission is given link to change list view in breadcrumbs.'
+ addpage,
+ change_list_link,
+ msg_prefix="User restricted to add permission is given link to change list view in breadcrumbs.",
)
- post = self.client.post(reverse('admin:admin_views_article_add'), add_dict)
+ post = self.client.post(reverse("admin:admin_views_article_add"), add_dict)
self.assertRedirects(post, self.index_url)
self.assertEqual(Article.objects.count(), 4)
self.assertEqual(len(mail.outbox), 2)
- self.assertEqual(mail.outbox[0].subject, 'Greetings from a created object')
- self.client.get(reverse('admin:logout'))
+ self.assertEqual(mail.outbox[0].subject, "Greetings from a created object")
+ self.client.get(reverse("admin:logout"))
# The addition was logged correctly
addition_log = LogEntry.objects.all()[0]
@@ -1880,15 +2293,16 @@ class AdminViewPermissionsTest(TestCase):
# Super can add too, but is redirected to the change list view
self.client.force_login(self.superuser)
- addpage = self.client.get(reverse('admin:admin_views_article_add'))
+ addpage = self.client.get(reverse("admin:admin_views_article_add"))
self.assertContains(
- addpage, change_list_link,
- msg_prefix='Unrestricted user is not given link to change list view in breadcrumbs.'
+ addpage,
+ change_list_link,
+ msg_prefix="Unrestricted user is not given link to change list view in breadcrumbs.",
)
- post = self.client.post(reverse('admin:admin_views_article_add'), add_dict)
- self.assertRedirects(post, reverse('admin:admin_views_article_changelist'))
+ post = self.client.post(reverse("admin:admin_views_article_add"), add_dict)
+ self.assertRedirects(post, reverse("admin:admin_views_article_changelist"))
self.assertEqual(Article.objects.count(), 5)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# 8509 - if a normal user is already logged in, it is possible
# to change user into the superuser without error
@@ -1898,34 +2312,42 @@ class AdminViewPermissionsTest(TestCase):
# make sure the view removes test cookie
self.assertIs(self.client.session.test_cookie_worked(), False)
- @mock.patch('django.contrib.admin.options.InlineModelAdmin.has_change_permission')
+ @mock.patch("django.contrib.admin.options.InlineModelAdmin.has_change_permission")
def test_add_view_with_view_only_inlines(self, has_change_permission):
"""User with add permission to a section but view-only for inlines."""
- self.viewuser.user_permissions.add(get_perm(Section, get_permission_codename('add', Section._meta)))
+ self.viewuser.user_permissions.add(
+ get_perm(Section, get_permission_codename("add", Section._meta))
+ )
self.client.force_login(self.viewuser)
# Valid POST creates a new section.
data = {
- 'name': 'New obj',
- 'article_set-TOTAL_FORMS': 0,
- 'article_set-INITIAL_FORMS': 0,
+ "name": "New obj",
+ "article_set-TOTAL_FORMS": 0,
+ "article_set-INITIAL_FORMS": 0,
}
- response = self.client.post(reverse('admin:admin_views_section_add'), data)
- self.assertRedirects(response, reverse('admin:index'))
- self.assertEqual(Section.objects.latest('id').name, data['name'])
+ response = self.client.post(reverse("admin:admin_views_section_add"), data)
+ self.assertRedirects(response, reverse("admin:index"))
+ self.assertEqual(Section.objects.latest("id").name, data["name"])
# InlineModelAdmin.has_change_permission()'s obj argument is always
# None during object add.
- self.assertEqual([obj for (request, obj), _ in has_change_permission.call_args_list], [None, None])
+ self.assertEqual(
+ [obj for (request, obj), _ in has_change_permission.call_args_list],
+ [None, None],
+ )
def test_change_view(self):
"""Change view should restrict access and allow users to edit items."""
change_dict = {
- 'title': 'Ikke fordømt',
- 'content': '<p>edited article</p>',
- 'date_0': '2008-03-18', 'date_1': '10:54:39',
- 'section': self.s1.pk,
+ "title": "Ikke fordømt",
+ "content": "<p>edited article</p>",
+ "date_0": "2008-03-18",
+ "date_1": "10:54:39",
+ "section": self.s1.pk,
}
- article_change_url = reverse('admin:admin_views_article_change', args=(self.a1.pk,))
- article_changelist_url = reverse('admin:admin_views_article_changelist')
+ article_change_url = reverse(
+ "admin:admin_views_article_change", args=(self.a1.pk,)
+ )
+ article_changelist_url = reverse("admin:admin_views_article_changelist")
# add user should not be able to view the list of article or change any of them
self.client.force_login(self.adduser)
@@ -1935,127 +2357,170 @@ class AdminViewPermissionsTest(TestCase):
self.assertEqual(response.status_code, 403)
post = self.client.post(article_change_url, change_dict)
self.assertEqual(post.status_code, 403)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# view user can view articles but not make changes.
self.client.force_login(self.viewuser)
response = self.client.get(article_changelist_url)
self.assertContains(
response,
- '<title>Select article to view | Django site admin</title>',
+ "<title>Select article to view | Django site admin</title>",
)
- self.assertContains(response, '<h1>Select article to view</h1>')
- self.assertEqual(response.context['title'], 'Select article to view')
+ self.assertContains(response, "<h1>Select article to view</h1>")
+ self.assertEqual(response.context["title"], "Select article to view")
response = self.client.get(article_change_url)
- self.assertContains(response, '<title>View article | Django site admin</title>')
- self.assertContains(response, '<h1>View article</h1>')
- self.assertContains(response, '<label>Extra form field:</label>')
- self.assertContains(response, '<a href="/test_admin/admin/admin_views/article/" class="closelink">Close</a>')
- self.assertEqual(response.context['title'], 'View article')
+ self.assertContains(response, "<title>View article | Django site admin</title>")
+ self.assertContains(response, "<h1>View article</h1>")
+ self.assertContains(response, "<label>Extra form field:</label>")
+ self.assertContains(
+ response,
+ '<a href="/test_admin/admin/admin_views/article/" class="closelink">Close</a>',
+ )
+ self.assertEqual(response.context["title"], "View article")
post = self.client.post(article_change_url, change_dict)
self.assertEqual(post.status_code, 403)
- self.assertEqual(Article.objects.get(pk=self.a1.pk).content, '<p>Middle content</p>')
- self.client.get(reverse('admin:logout'))
+ self.assertEqual(
+ Article.objects.get(pk=self.a1.pk).content, "<p>Middle content</p>"
+ )
+ self.client.get(reverse("admin:logout"))
# change user can view all items and edit them
self.client.force_login(self.changeuser)
response = self.client.get(article_changelist_url)
- self.assertEqual(response.context['title'], 'Select article to change')
+ self.assertEqual(response.context["title"], "Select article to change")
self.assertContains(
response,
- '<title>Select article to change | Django site admin</title>',
+ "<title>Select article to change | Django site admin</title>",
)
- self.assertContains(response, '<h1>Select article to change</h1>')
+ self.assertContains(response, "<h1>Select article to change</h1>")
response = self.client.get(article_change_url)
- self.assertEqual(response.context['title'], 'Change article')
+ self.assertEqual(response.context["title"], "Change article")
self.assertContains(
response,
- '<title>Change article | Django site admin</title>',
+ "<title>Change article | Django site admin</title>",
)
- self.assertContains(response, '<h1>Change article</h1>')
+ self.assertContains(response, "<h1>Change article</h1>")
post = self.client.post(article_change_url, change_dict)
self.assertRedirects(post, article_changelist_url)
- self.assertEqual(Article.objects.get(pk=self.a1.pk).content, '<p>edited article</p>')
+ self.assertEqual(
+ Article.objects.get(pk=self.a1.pk).content, "<p>edited article</p>"
+ )
# one error in form should produce singular error message, multiple errors plural
- change_dict['title'] = ''
+ change_dict["title"] = ""
post = self.client.post(article_change_url, change_dict)
self.assertContains(
- post, 'Please correct the error below.',
- msg_prefix='Singular error message not found in response to post with one error'
+ post,
+ "Please correct the error below.",
+ msg_prefix="Singular error message not found in response to post with one error",
)
- change_dict['content'] = ''
+ change_dict["content"] = ""
post = self.client.post(article_change_url, change_dict)
self.assertContains(
- post, 'Please correct the errors below.',
- msg_prefix='Plural error message not found in response to post with multiple errors'
+ post,
+ "Please correct the errors below.",
+ msg_prefix="Plural error message not found in response to post with multiple errors",
)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# Test redirection when using row-level change permissions. Refs #11513.
r1 = RowLevelChangePermissionModel.objects.create(id=1, name="odd id")
r2 = RowLevelChangePermissionModel.objects.create(id=2, name="even id")
- r3 = RowLevelChangePermissionModel.objects.create(id=3, name='odd id mult 3')
- r6 = RowLevelChangePermissionModel.objects.create(id=6, name='even id mult 3')
- change_url_1 = reverse('admin:admin_views_rowlevelchangepermissionmodel_change', args=(r1.pk,))
- change_url_2 = reverse('admin:admin_views_rowlevelchangepermissionmodel_change', args=(r2.pk,))
- change_url_3 = reverse('admin:admin_views_rowlevelchangepermissionmodel_change', args=(r3.pk,))
- change_url_6 = reverse('admin:admin_views_rowlevelchangepermissionmodel_change', args=(r6.pk,))
- logins = [self.superuser, self.viewuser, self.adduser, self.changeuser, self.deleteuser]
+ r3 = RowLevelChangePermissionModel.objects.create(id=3, name="odd id mult 3")
+ r6 = RowLevelChangePermissionModel.objects.create(id=6, name="even id mult 3")
+ change_url_1 = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_change", args=(r1.pk,)
+ )
+ change_url_2 = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_change", args=(r2.pk,)
+ )
+ change_url_3 = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_change", args=(r3.pk,)
+ )
+ change_url_6 = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_change", args=(r6.pk,)
+ )
+ logins = [
+ self.superuser,
+ self.viewuser,
+ self.adduser,
+ self.changeuser,
+ self.deleteuser,
+ ]
for login_user in logins:
with self.subTest(login_user.username):
self.client.force_login(login_user)
response = self.client.get(change_url_1)
self.assertEqual(response.status_code, 403)
- response = self.client.post(change_url_1, {'name': 'changed'})
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=1).name, 'odd id')
+ response = self.client.post(change_url_1, {"name": "changed"})
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=1).name, "odd id"
+ )
self.assertEqual(response.status_code, 403)
response = self.client.get(change_url_2)
self.assertEqual(response.status_code, 200)
- response = self.client.post(change_url_2, {'name': 'changed'})
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
+ response = self.client.post(change_url_2, {"name": "changed"})
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=2).name, "changed"
+ )
self.assertRedirects(response, self.index_url)
response = self.client.get(change_url_3)
self.assertEqual(response.status_code, 200)
- response = self.client.post(change_url_3, {'name': 'changed'})
+ response = self.client.post(change_url_3, {"name": "changed"})
self.assertEqual(response.status_code, 403)
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=3).name, 'odd id mult 3')
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=3).name,
+ "odd id mult 3",
+ )
response = self.client.get(change_url_6)
self.assertEqual(response.status_code, 200)
- response = self.client.post(change_url_6, {'name': 'changed'})
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=6).name, 'changed')
+ response = self.client.post(change_url_6, {"name": "changed"})
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=6).name, "changed"
+ )
self.assertRedirects(response, self.index_url)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
for login_user in [self.joepublicuser, self.nostaffuser]:
with self.subTest(login_user.username):
self.client.force_login(login_user)
response = self.client.get(change_url_1, follow=True)
- self.assertContains(response, 'login-form')
- response = self.client.post(change_url_1, {'name': 'changed'}, follow=True)
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=1).name, 'odd id')
- self.assertContains(response, 'login-form')
+ self.assertContains(response, "login-form")
+ response = self.client.post(
+ change_url_1, {"name": "changed"}, follow=True
+ )
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=1).name, "odd id"
+ )
+ self.assertContains(response, "login-form")
response = self.client.get(change_url_2, follow=True)
- self.assertContains(response, 'login-form')
- response = self.client.post(change_url_2, {'name': 'changed again'}, follow=True)
- self.assertEqual(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
- self.assertContains(response, 'login-form')
- self.client.get(reverse('admin:logout'))
+ self.assertContains(response, "login-form")
+ response = self.client.post(
+ change_url_2, {"name": "changed again"}, follow=True
+ )
+ self.assertEqual(
+ RowLevelChangePermissionModel.objects.get(id=2).name, "changed"
+ )
+ self.assertContains(response, "login-form")
+ self.client.get(reverse("admin:logout"))
def test_change_view_without_object_change_permission(self):
"""
The object should be read-only if the user has permission to view it
and change objects of that type but not to change the current object.
"""
- change_url = reverse('admin9:admin_views_article_change', args=(self.a1.pk,))
+ change_url = reverse("admin9:admin_views_article_change", args=(self.a1.pk,))
self.client.force_login(self.viewuser)
response = self.client.get(change_url)
- self.assertEqual(response.context['title'], 'View article')
- self.assertContains(response, '<title>View article | Django site admin</title>')
- self.assertContains(response, '<h1>View article</h1>')
- self.assertContains(response, '<a href="/test_admin/admin9/admin_views/article/" class="closelink">Close</a>')
+ self.assertEqual(response.context["title"], "View article")
+ self.assertContains(response, "<title>View article | Django site admin</title>")
+ self.assertContains(response, "<h1>View article</h1>")
+ self.assertContains(
+ response,
+ '<a href="/test_admin/admin9/admin_views/article/" class="closelink">Close</a>',
+ )
def test_change_view_save_as_new(self):
"""
@@ -2063,13 +2528,16 @@ class AdminViewPermissionsTest(TestCase):
permission.
"""
change_dict_save_as_new = {
- '_saveasnew': 'Save as new',
- 'title': 'Ikke fordømt',
- 'content': '<p>edited article</p>',
- 'date_0': '2008-03-18', 'date_1': '10:54:39',
- 'section': self.s1.pk,
+ "_saveasnew": "Save as new",
+ "title": "Ikke fordømt",
+ "content": "<p>edited article</p>",
+ "date_0": "2008-03-18",
+ "date_1": "10:54:39",
+ "section": self.s1.pk,
}
- article_change_url = reverse('admin:admin_views_article_change', args=(self.a1.pk,))
+ article_change_url = reverse(
+ "admin:admin_views_article_change", args=(self.a1.pk,)
+ )
# Add user can perform "Save as new".
article_count = Article.objects.count()
@@ -2092,103 +2560,131 @@ class AdminViewPermissionsTest(TestCase):
self.client.force_login(self.superuser)
post = self.client.post(article_change_url, change_dict_save_as_new)
self.assertEqual(Article.objects.count(), article_count + 1)
- new_article = Article.objects.latest('id')
- self.assertRedirects(post, reverse('admin:admin_views_article_change', args=(new_article.pk,)))
+ new_article = Article.objects.latest("id")
+ self.assertRedirects(
+ post, reverse("admin:admin_views_article_change", args=(new_article.pk,))
+ )
def test_change_view_with_view_only_inlines(self):
"""
User with change permission to a section but view-only for inlines.
"""
- self.viewuser.user_permissions.add(get_perm(Section, get_permission_codename('change', Section._meta)))
+ self.viewuser.user_permissions.add(
+ get_perm(Section, get_permission_codename("change", Section._meta))
+ )
self.client.force_login(self.viewuser)
# GET shows inlines.
- response = self.client.get(reverse('admin:admin_views_section_change', args=(self.s1.pk,)))
- self.assertEqual(len(response.context['inline_admin_formsets']), 1)
- formset = response.context['inline_admin_formsets'][0]
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,))
+ )
+ self.assertEqual(len(response.context["inline_admin_formsets"]), 1)
+ formset = response.context["inline_admin_formsets"][0]
self.assertEqual(len(formset.forms), 3)
# Valid POST changes the name.
data = {
- 'name': 'Can edit name with view-only inlines',
- 'article_set-TOTAL_FORMS': 3,
- 'article_set-INITIAL_FORMS': 3
+ "name": "Can edit name with view-only inlines",
+ "article_set-TOTAL_FORMS": 3,
+ "article_set-INITIAL_FORMS": 3,
}
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
- self.assertRedirects(response, reverse('admin:admin_views_section_changelist'))
- self.assertEqual(Section.objects.get(pk=self.s1.pk).name, data['name'])
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
+ self.assertRedirects(response, reverse("admin:admin_views_section_changelist"))
+ self.assertEqual(Section.objects.get(pk=self.s1.pk).name, data["name"])
# Invalid POST reshows inlines.
- del data['name']
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
+ del data["name"]
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
self.assertEqual(response.status_code, 200)
- self.assertEqual(len(response.context['inline_admin_formsets']), 1)
- formset = response.context['inline_admin_formsets'][0]
+ self.assertEqual(len(response.context["inline_admin_formsets"]), 1)
+ formset = response.context["inline_admin_formsets"][0]
self.assertEqual(len(formset.forms), 3)
def test_change_view_with_view_and_add_inlines(self):
"""User has view and add permissions on the inline model."""
- self.viewuser.user_permissions.add(get_perm(Section, get_permission_codename('change', Section._meta)))
- self.viewuser.user_permissions.add(get_perm(Article, get_permission_codename('add', Article._meta)))
+ self.viewuser.user_permissions.add(
+ get_perm(Section, get_permission_codename("change", Section._meta))
+ )
+ self.viewuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("add", Article._meta))
+ )
self.client.force_login(self.viewuser)
# GET shows inlines.
- response = self.client.get(reverse('admin:admin_views_section_change', args=(self.s1.pk,)))
- self.assertEqual(len(response.context['inline_admin_formsets']), 1)
- formset = response.context['inline_admin_formsets'][0]
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,))
+ )
+ self.assertEqual(len(response.context["inline_admin_formsets"]), 1)
+ formset = response.context["inline_admin_formsets"][0]
self.assertEqual(len(formset.forms), 6)
# Valid POST creates a new article.
data = {
- 'name': 'Can edit name with view-only inlines',
- 'article_set-TOTAL_FORMS': 6,
- 'article_set-INITIAL_FORMS': 3,
- 'article_set-3-id': [''],
- 'article_set-3-title': ['A title'],
- 'article_set-3-content': ['Added content'],
- 'article_set-3-date_0': ['2008-3-18'],
- 'article_set-3-date_1': ['11:54:58'],
- 'article_set-3-section': [str(self.s1.pk)],
+ "name": "Can edit name with view-only inlines",
+ "article_set-TOTAL_FORMS": 6,
+ "article_set-INITIAL_FORMS": 3,
+ "article_set-3-id": [""],
+ "article_set-3-title": ["A title"],
+ "article_set-3-content": ["Added content"],
+ "article_set-3-date_0": ["2008-3-18"],
+ "article_set-3-date_1": ["11:54:58"],
+ "article_set-3-section": [str(self.s1.pk)],
}
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
- self.assertRedirects(response, reverse('admin:admin_views_section_changelist'))
- self.assertEqual(Section.objects.get(pk=self.s1.pk).name, data['name'])
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
+ self.assertRedirects(response, reverse("admin:admin_views_section_changelist"))
+ self.assertEqual(Section.objects.get(pk=self.s1.pk).name, data["name"])
self.assertEqual(Article.objects.count(), 4)
# Invalid POST reshows inlines.
- del data['name']
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
+ del data["name"]
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
self.assertEqual(response.status_code, 200)
- self.assertEqual(len(response.context['inline_admin_formsets']), 1)
- formset = response.context['inline_admin_formsets'][0]
+ self.assertEqual(len(response.context["inline_admin_formsets"]), 1)
+ formset = response.context["inline_admin_formsets"][0]
self.assertEqual(len(formset.forms), 6)
def test_change_view_with_view_and_delete_inlines(self):
"""User has view and delete permissions on the inline model."""
- self.viewuser.user_permissions.add(get_perm(Section, get_permission_codename('change', Section._meta)))
+ self.viewuser.user_permissions.add(
+ get_perm(Section, get_permission_codename("change", Section._meta))
+ )
self.client.force_login(self.viewuser)
data = {
- 'name': 'Name is required.',
- 'article_set-TOTAL_FORMS': 6,
- 'article_set-INITIAL_FORMS': 3,
- 'article_set-0-id': [str(self.a1.pk)],
- 'article_set-0-DELETE': ['on'],
+ "name": "Name is required.",
+ "article_set-TOTAL_FORMS": 6,
+ "article_set-INITIAL_FORMS": 3,
+ "article_set-0-id": [str(self.a1.pk)],
+ "article_set-0-DELETE": ["on"],
}
# Inline POST details are ignored without delete permission.
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
- self.assertRedirects(response, reverse('admin:admin_views_section_changelist'))
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
+ self.assertRedirects(response, reverse("admin:admin_views_section_changelist"))
self.assertEqual(Article.objects.count(), 3)
# Deletion successful when delete permission is added.
- self.viewuser.user_permissions.add(get_perm(Article, get_permission_codename('delete', Article._meta)))
+ self.viewuser.user_permissions.add(
+ get_perm(Article, get_permission_codename("delete", Article._meta))
+ )
data = {
- 'name': 'Name is required.',
- 'article_set-TOTAL_FORMS': 6,
- 'article_set-INITIAL_FORMS': 3,
- 'article_set-0-id': [str(self.a1.pk)],
- 'article_set-0-DELETE': ['on'],
+ "name": "Name is required.",
+ "article_set-TOTAL_FORMS": 6,
+ "article_set-INITIAL_FORMS": 3,
+ "article_set-0-id": [str(self.a1.pk)],
+ "article_set-0-DELETE": ["on"],
}
- response = self.client.post(reverse('admin:admin_views_section_change', args=(self.s1.pk,)), data)
- self.assertRedirects(response, reverse('admin:admin_views_section_changelist'))
+ response = self.client.post(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,)), data
+ )
+ self.assertRedirects(response, reverse("admin:admin_views_section_changelist"))
self.assertEqual(Article.objects.count(), 2)
def test_delete_view(self):
"""Delete view should restrict access and actually delete items."""
- delete_dict = {'post': 'yes'}
- delete_url = reverse('admin:admin_views_article_delete', args=(self.a1.pk,))
+ delete_dict = {"post": "yes"}
+ delete_url = reverse("admin:admin_views_article_delete", args=(self.a1.pk,))
# add user should not be able to delete articles
self.client.force_login(self.adduser)
@@ -2210,7 +2706,9 @@ class AdminViewPermissionsTest(TestCase):
# Delete user can delete
self.client.force_login(self.deleteuser)
- response = self.client.get(reverse('admin:admin_views_section_delete', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_delete", args=(self.s1.pk,))
+ )
self.assertContains(response, "<h2>Summary</h2>")
self.assertContains(response, "<li>Articles: 3</li>")
# test response contains link to related Article
@@ -2224,7 +2722,7 @@ class AdminViewPermissionsTest(TestCase):
self.assertRedirects(post, self.index_url)
self.assertEqual(Article.objects.count(), 2)
self.assertEqual(len(mail.outbox), 1)
- self.assertEqual(mail.outbox[0].subject, 'Greetings from a deleted object')
+ self.assertEqual(mail.outbox[0].subject, "Greetings from a deleted object")
article_ct = ContentType.objects.get_for_model(Article)
logged = LogEntry.objects.get(content_type=article_ct, action_flag=DELETION)
self.assertEqual(logged.object_id, str(self.a1.pk))
@@ -2234,82 +2732,110 @@ class AdminViewPermissionsTest(TestCase):
The delete view allows users to delete collected objects without a
'delete' permission (ReadOnlyPizza.Meta.default_permissions is empty).
"""
- pizza = ReadOnlyPizza.objects.create(name='Double Cheese')
- delete_url = reverse('admin:admin_views_readonlypizza_delete', args=(pizza.pk,))
+ pizza = ReadOnlyPizza.objects.create(name="Double Cheese")
+ delete_url = reverse("admin:admin_views_readonlypizza_delete", args=(pizza.pk,))
self.client.force_login(self.adduser)
response = self.client.get(delete_url)
- self.assertContains(response, 'admin_views/readonlypizza/%s/' % pizza.pk)
- self.assertContains(response, '<h2>Summary</h2>')
- self.assertContains(response, '<li>Read only pizzas: 1</li>')
- post = self.client.post(delete_url, {'post': 'yes'})
- self.assertRedirects(post, reverse('admin:admin_views_readonlypizza_changelist'))
+ self.assertContains(response, "admin_views/readonlypizza/%s/" % pizza.pk)
+ self.assertContains(response, "<h2>Summary</h2>")
+ self.assertContains(response, "<li>Read only pizzas: 1</li>")
+ post = self.client.post(delete_url, {"post": "yes"})
+ self.assertRedirects(
+ post, reverse("admin:admin_views_readonlypizza_changelist")
+ )
self.assertEqual(ReadOnlyPizza.objects.count(), 0)
def test_delete_view_nonexistent_obj(self):
self.client.force_login(self.deleteuser)
- url = reverse('admin:admin_views_article_delete', args=('nonexistent',))
+ url = reverse("admin:admin_views_article_delete", args=("nonexistent",))
response = self.client.get(url, follow=True)
- self.assertRedirects(response, reverse('admin:index'))
+ self.assertRedirects(response, reverse("admin:index"))
self.assertEqual(
- [m.message for m in response.context['messages']],
- ['article with ID “nonexistent” doesn’t exist. Perhaps it was deleted?']
+ [m.message for m in response.context["messages"]],
+ ["article with ID “nonexistent” doesn’t exist. Perhaps it was deleted?"],
)
def test_history_view(self):
"""History view should restrict access."""
# add user should not be able to view the list of article or change any of them
self.client.force_login(self.adduser)
- response = self.client.get(reverse('admin:admin_views_article_history', args=(self.a1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_article_history", args=(self.a1.pk,))
+ )
self.assertEqual(response.status_code, 403)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# view user can view all items
self.client.force_login(self.viewuser)
- response = self.client.get(reverse('admin:admin_views_article_history', args=(self.a1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_article_history", args=(self.a1.pk,))
+ )
self.assertEqual(response.status_code, 200)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
# change user can view all items and edit them
self.client.force_login(self.changeuser)
- response = self.client.get(reverse('admin:admin_views_article_history', args=(self.a1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_article_history", args=(self.a1.pk,))
+ )
self.assertEqual(response.status_code, 200)
# Test redirection when using row-level change permissions. Refs #11513.
rl1 = RowLevelChangePermissionModel.objects.create(id=1, name="odd id")
rl2 = RowLevelChangePermissionModel.objects.create(id=2, name="even id")
- logins = [self.superuser, self.viewuser, self.adduser, self.changeuser, self.deleteuser]
+ logins = [
+ self.superuser,
+ self.viewuser,
+ self.adduser,
+ self.changeuser,
+ self.deleteuser,
+ ]
for login_user in logins:
with self.subTest(login_user.username):
self.client.force_login(login_user)
- url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,))
+ url = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_history",
+ args=(rl1.pk,),
+ )
response = self.client.get(url)
self.assertEqual(response.status_code, 403)
- url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,))
+ url = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_history",
+ args=(rl2.pk,),
+ )
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
for login_user in [self.joepublicuser, self.nostaffuser]:
with self.subTest(login_user.username):
self.client.force_login(login_user)
- url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl1.pk,))
+ url = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_history",
+ args=(rl1.pk,),
+ )
response = self.client.get(url, follow=True)
- self.assertContains(response, 'login-form')
- url = reverse('admin:admin_views_rowlevelchangepermissionmodel_history', args=(rl2.pk,))
+ self.assertContains(response, "login-form")
+ url = reverse(
+ "admin:admin_views_rowlevelchangepermissionmodel_history",
+ args=(rl2.pk,),
+ )
response = self.client.get(url, follow=True)
- self.assertContains(response, 'login-form')
+ self.assertContains(response, "login-form")
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
def test_history_view_bad_url(self):
self.client.force_login(self.changeuser)
- response = self.client.get(reverse('admin:admin_views_article_history', args=('foo',)), follow=True)
- self.assertRedirects(response, reverse('admin:index'))
+ response = self.client.get(
+ reverse("admin:admin_views_article_history", args=("foo",)), follow=True
+ )
+ self.assertRedirects(response, reverse("admin:index"))
self.assertEqual(
- [m.message for m in response.context['messages']],
- ['article with ID “foo” doesn’t exist. Perhaps it was deleted?']
+ [m.message for m in response.context["messages"]],
+ ["article with ID “foo” doesn’t exist. Perhaps it was deleted?"],
)
def test_conditionally_show_add_section_link(self):
@@ -2319,13 +2845,13 @@ class AdminViewPermissionsTest(TestCase):
"""
self.client.force_login(self.adduser)
# The user can't add sections yet, so they shouldn't see the "add section" link.
- url = reverse('admin:admin_views_article_add')
- add_link_text = 'add_id_section'
+ url = reverse("admin:admin_views_article_add")
+ add_link_text = "add_id_section"
response = self.client.get(url)
self.assertNotContains(response, add_link_text)
# Allow the user to add sections too. Now they can see the "add section" link.
- user = User.objects.get(username='adduser')
- perm = get_perm(Section, get_permission_codename('add', Section._meta))
+ user = User.objects.get(username="adduser")
+ perm = get_perm(Section, get_permission_codename("add", Section._meta))
user.user_permissions.add(perm)
response = self.client.get(url)
self.assertContains(response, add_link_text)
@@ -2335,19 +2861,24 @@ class AdminViewPermissionsTest(TestCase):
The foreign key widget should only show the "change related" button if
the user has permission to change that related item.
"""
+
def get_change_related(response):
- return response.context['adminform'].form.fields['section'].widget.can_change_related
+ return (
+ response.context["adminform"]
+ .form.fields["section"]
+ .widget.can_change_related
+ )
self.client.force_login(self.adduser)
# The user can't change sections yet, so they shouldn't see the "change section" link.
- url = reverse('admin:admin_views_article_add')
- change_link_text = 'change_id_section'
+ url = reverse("admin:admin_views_article_add")
+ change_link_text = "change_id_section"
response = self.client.get(url)
self.assertFalse(get_change_related(response))
self.assertNotContains(response, change_link_text)
# Allow the user to change sections too. Now they can see the "change section" link.
- user = User.objects.get(username='adduser')
- perm = get_perm(Section, get_permission_codename('change', Section._meta))
+ user = User.objects.get(username="adduser")
+ perm = get_perm(Section, get_permission_codename("change", Section._meta))
user.user_permissions.add(perm)
response = self.client.get(url)
self.assertTrue(get_change_related(response))
@@ -2358,19 +2889,24 @@ class AdminViewPermissionsTest(TestCase):
The foreign key widget should only show the "delete related" button if
the user has permission to delete that related item.
"""
+
def get_delete_related(response):
- return response.context['adminform'].form.fields['sub_section'].widget.can_delete_related
+ return (
+ response.context["adminform"]
+ .form.fields["sub_section"]
+ .widget.can_delete_related
+ )
self.client.force_login(self.adduser)
# The user can't delete sections yet, so they shouldn't see the "delete section" link.
- url = reverse('admin:admin_views_article_add')
- delete_link_text = 'delete_id_sub_section'
+ url = reverse("admin:admin_views_article_add")
+ delete_link_text = "delete_id_sub_section"
response = self.client.get(url)
self.assertFalse(get_delete_related(response))
self.assertNotContains(response, delete_link_text)
# Allow the user to delete sections too. Now they can see the "delete section" link.
- user = User.objects.get(username='adduser')
- perm = get_perm(Section, get_permission_codename('delete', Section._meta))
+ user = User.objects.get(username="adduser")
+ perm = get_perm(Section, get_permission_codename("delete", Section._meta))
user.user_permissions.add(perm)
response = self.client.get(url)
self.assertTrue(get_delete_related(response))
@@ -2378,28 +2914,28 @@ class AdminViewPermissionsTest(TestCase):
def test_disabled_permissions_when_logged_in(self):
self.client.force_login(self.superuser)
- superuser = User.objects.get(username='super')
+ superuser = User.objects.get(username="super")
superuser.is_active = False
superuser.save()
response = self.client.get(self.index_url, follow=True)
self.assertContains(response, 'id="login-form"')
- self.assertNotContains(response, 'Log out')
+ self.assertNotContains(response, "Log out")
- response = self.client.get(reverse('secure_view'), follow=True)
+ response = self.client.get(reverse("secure_view"), follow=True)
self.assertContains(response, 'id="login-form"')
def test_disabled_staff_permissions_when_logged_in(self):
self.client.force_login(self.superuser)
- superuser = User.objects.get(username='super')
+ superuser = User.objects.get(username="super")
superuser.is_staff = False
superuser.save()
response = self.client.get(self.index_url, follow=True)
self.assertContains(response, 'id="login-form"')
- self.assertNotContains(response, 'Log out')
+ self.assertNotContains(response, "Log out")
- response = self.client.get(reverse('secure_view'), follow=True)
+ response = self.client.get(reverse("secure_view"), follow=True)
self.assertContains(response, 'id="login-form"')
def test_app_list_permissions(self):
@@ -2407,19 +2943,19 @@ class AdminViewPermissionsTest(TestCase):
If a user has no module perms, the app list returns a 404.
"""
opts = Article._meta
- change_user = User.objects.get(username='changeuser')
- permission = get_perm(Article, get_permission_codename('change', opts))
+ change_user = User.objects.get(username="changeuser")
+ permission = get_perm(Article, get_permission_codename("change", opts))
self.client.force_login(self.changeuser)
# the user has no module permissions
change_user.user_permissions.remove(permission)
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertEqual(response.status_code, 404)
# the user now has module permissions
change_user.user_permissions.add(permission)
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertEqual(response.status_code, 200)
def test_shortcut_view_only_available_to_staff(self):
@@ -2427,12 +2963,12 @@ class AdminViewPermissionsTest(TestCase):
Only admin users should be able to use the admin shortcut view.
"""
model_ctype = ContentType.objects.get_for_model(ModelWithStringPrimaryKey)
- obj = ModelWithStringPrimaryKey.objects.create(string_pk='foo')
- shortcut_url = reverse('admin:view_on_site', args=(model_ctype.pk, obj.pk))
+ obj = ModelWithStringPrimaryKey.objects.create(string_pk="foo")
+ shortcut_url = reverse("admin:view_on_site", args=(model_ctype.pk, obj.pk))
# Not logged in: we should see the login page.
response = self.client.get(shortcut_url, follow=True)
- self.assertTemplateUsed(response, 'admin/login.html')
+ self.assertTemplateUsed(response, "admin/login.html")
# Logged in? Redirect.
self.client.force_login(self.superuser)
@@ -2440,7 +2976,7 @@ class AdminViewPermissionsTest(TestCase):
# Can't use self.assertRedirects() because User.get_absolute_url() is silly.
self.assertEqual(response.status_code, 302)
# Domain may depend on contrib.sites tests also run
- self.assertRegex(response.url, 'http://(testserver|example.com)/dummy/foo/')
+ self.assertRegex(response.url, "http://(testserver|example.com)/dummy/foo/")
def test_has_module_permission(self):
"""
@@ -2450,32 +2986,32 @@ class AdminViewPermissionsTest(TestCase):
"""
self.client.force_login(self.superuser)
response = self.client.get(self.index_url)
- self.assertContains(response, 'admin_views')
- self.assertContains(response, 'Articles')
+ self.assertContains(response, "admin_views")
+ self.assertContains(response, "Articles")
self.client.logout()
self.client.force_login(self.viewuser)
response = self.client.get(self.index_url)
- self.assertContains(response, 'admin_views')
- self.assertContains(response, 'Articles')
+ self.assertContains(response, "admin_views")
+ self.assertContains(response, "Articles")
self.client.logout()
self.client.force_login(self.adduser)
response = self.client.get(self.index_url)
- self.assertContains(response, 'admin_views')
- self.assertContains(response, 'Articles')
+ self.assertContains(response, "admin_views")
+ self.assertContains(response, "Articles")
self.client.logout()
self.client.force_login(self.changeuser)
response = self.client.get(self.index_url)
- self.assertContains(response, 'admin_views')
- self.assertContains(response, 'Articles')
+ self.assertContains(response, "admin_views")
+ self.assertContains(response, "Articles")
self.client.logout()
self.client.force_login(self.deleteuser)
response = self.client.get(self.index_url)
- self.assertContains(response, 'admin_views')
- self.assertContains(response, 'Articles')
+ self.assertContains(response, "admin_views")
+ self.assertContains(response, "Articles")
def test_overriding_has_module_permission(self):
"""
@@ -2484,7 +3020,7 @@ class AdminViewPermissionsTest(TestCase):
"""
articles = Article._meta.verbose_name_plural.title()
sections = Section._meta.verbose_name_plural.title()
- index_url = reverse('admin7:index')
+ index_url = reverse("admin7:index")
self.client.force_login(self.superuser)
response = self.client.get(index_url)
@@ -2494,19 +3030,19 @@ class AdminViewPermissionsTest(TestCase):
self.client.force_login(self.viewuser)
response = self.client.get(index_url)
- self.assertNotContains(response, 'admin_views')
+ self.assertNotContains(response, "admin_views")
self.assertNotContains(response, articles)
self.client.logout()
self.client.force_login(self.adduser)
response = self.client.get(index_url)
- self.assertNotContains(response, 'admin_views')
+ self.assertNotContains(response, "admin_views")
self.assertNotContains(response, articles)
self.client.logout()
self.client.force_login(self.changeuser)
response = self.client.get(index_url)
- self.assertNotContains(response, 'admin_views')
+ self.assertNotContains(response, "admin_views")
self.assertNotContains(response, articles)
self.client.logout()
@@ -2517,7 +3053,7 @@ class AdminViewPermissionsTest(TestCase):
# The app list displays Sections but not Articles as the latter has
# ModelAdmin.has_module_permission() = False.
self.client.force_login(self.superuser)
- response = self.client.get(reverse('admin7:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin7:app_list", args=("admin_views",)))
self.assertContains(response, sections)
self.assertNotContains(response, articles)
@@ -2535,140 +3071,195 @@ class AdminViewPermissionsTest(TestCase):
"date_1": "16:35:00",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_article_add'), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_article_add"), post_data, follow=True
+ )
self.assertContains(
response,
'<li class="success">The article “Fun &amp; games” was added successfully.</li>',
- html=True
+ html=True,
)
@override_settings(
- ROOT_URLCONF='admin_views.urls',
- TEMPLATES=[{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- }],
+ ROOT_URLCONF="admin_views.urls",
+ TEMPLATES=[
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ }
+ ],
)
class AdminViewProxyModelPermissionsTests(TestCase):
"""Tests for proxy models permissions in the admin."""
@classmethod
def setUpTestData(cls):
- cls.viewuser = User.objects.create_user(username='viewuser', password='secret', is_staff=True)
- cls.adduser = User.objects.create_user(username='adduser', password='secret', is_staff=True)
- cls.changeuser = User.objects.create_user(username='changeuser', password='secret', is_staff=True)
- cls.deleteuser = User.objects.create_user(username='deleteuser', password='secret', is_staff=True)
+ cls.viewuser = User.objects.create_user(
+ username="viewuser", password="secret", is_staff=True
+ )
+ cls.adduser = User.objects.create_user(
+ username="adduser", password="secret", is_staff=True
+ )
+ cls.changeuser = User.objects.create_user(
+ username="changeuser", password="secret", is_staff=True
+ )
+ cls.deleteuser = User.objects.create_user(
+ username="deleteuser", password="secret", is_staff=True
+ )
# Setup permissions.
opts = UserProxy._meta
- cls.viewuser.user_permissions.add(get_perm(UserProxy, get_permission_codename('view', opts)))
- cls.adduser.user_permissions.add(get_perm(UserProxy, get_permission_codename('add', opts)))
- cls.changeuser.user_permissions.add(get_perm(UserProxy, get_permission_codename('change', opts)))
- cls.deleteuser.user_permissions.add(get_perm(UserProxy, get_permission_codename('delete', opts)))
+ cls.viewuser.user_permissions.add(
+ get_perm(UserProxy, get_permission_codename("view", opts))
+ )
+ cls.adduser.user_permissions.add(
+ get_perm(UserProxy, get_permission_codename("add", opts))
+ )
+ cls.changeuser.user_permissions.add(
+ get_perm(UserProxy, get_permission_codename("change", opts))
+ )
+ cls.deleteuser.user_permissions.add(
+ get_perm(UserProxy, get_permission_codename("delete", opts))
+ )
# UserProxy instances.
- cls.user_proxy = UserProxy.objects.create(username='user_proxy', password='secret')
+ cls.user_proxy = UserProxy.objects.create(
+ username="user_proxy", password="secret"
+ )
def test_add(self):
self.client.force_login(self.adduser)
- url = reverse('admin:admin_views_userproxy_add')
+ url = reverse("admin:admin_views_userproxy_add")
data = {
- 'username': 'can_add',
- 'password': 'secret',
- 'date_joined_0': '2019-01-15',
- 'date_joined_1': '16:59:10',
+ "username": "can_add",
+ "password": "secret",
+ "date_joined_0": "2019-01-15",
+ "date_joined_1": "16:59:10",
}
response = self.client.post(url, data, follow=True)
self.assertEqual(response.status_code, 200)
- self.assertTrue(UserProxy.objects.filter(username='can_add').exists())
+ self.assertTrue(UserProxy.objects.filter(username="can_add").exists())
def test_view(self):
self.client.force_login(self.viewuser)
- response = self.client.get(reverse('admin:admin_views_userproxy_changelist'))
- self.assertContains(response, '<h1>Select user proxy to view</h1>')
- response = self.client.get(reverse('admin:admin_views_userproxy_change', args=(self.user_proxy.pk,)))
- self.assertContains(response, '<h1>View user proxy</h1>')
+ response = self.client.get(reverse("admin:admin_views_userproxy_changelist"))
+ self.assertContains(response, "<h1>Select user proxy to view</h1>")
+ response = self.client.get(
+ reverse("admin:admin_views_userproxy_change", args=(self.user_proxy.pk,))
+ )
+ self.assertContains(response, "<h1>View user proxy</h1>")
self.assertContains(response, '<div class="readonly">user_proxy</div>')
def test_change(self):
self.client.force_login(self.changeuser)
data = {
- 'password': self.user_proxy.password,
- 'username': self.user_proxy.username,
- 'date_joined_0': self.user_proxy.date_joined.strftime('%Y-%m-%d'),
- 'date_joined_1': self.user_proxy.date_joined.strftime('%H:%M:%S'),
- 'first_name': 'first_name',
+ "password": self.user_proxy.password,
+ "username": self.user_proxy.username,
+ "date_joined_0": self.user_proxy.date_joined.strftime("%Y-%m-%d"),
+ "date_joined_1": self.user_proxy.date_joined.strftime("%H:%M:%S"),
+ "first_name": "first_name",
}
- url = reverse('admin:admin_views_userproxy_change', args=(self.user_proxy.pk,))
+ url = reverse("admin:admin_views_userproxy_change", args=(self.user_proxy.pk,))
response = self.client.post(url, data)
- self.assertRedirects(response, reverse('admin:admin_views_userproxy_changelist'))
- self.assertEqual(UserProxy.objects.get(pk=self.user_proxy.pk).first_name, 'first_name')
+ self.assertRedirects(
+ response, reverse("admin:admin_views_userproxy_changelist")
+ )
+ self.assertEqual(
+ UserProxy.objects.get(pk=self.user_proxy.pk).first_name, "first_name"
+ )
def test_delete(self):
self.client.force_login(self.deleteuser)
- url = reverse('admin:admin_views_userproxy_delete', args=(self.user_proxy.pk,))
- response = self.client.post(url, {'post': 'yes'}, follow=True)
+ url = reverse("admin:admin_views_userproxy_delete", args=(self.user_proxy.pk,))
+ response = self.client.post(url, {"post": "yes"}, follow=True)
self.assertEqual(response.status_code, 200)
self.assertFalse(UserProxy.objects.filter(pk=self.user_proxy.pk).exists())
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewsNoUrlTest(TestCase):
"""Regression test for #17333"""
@classmethod
def setUpTestData(cls):
# User who can change Reports
- cls.changeuser = User.objects.create_user(username='changeuser', password='secret', is_staff=True)
- cls.changeuser.user_permissions.add(get_perm(Report, get_permission_codename('change', Report._meta)))
+ cls.changeuser = User.objects.create_user(
+ username="changeuser", password="secret", is_staff=True
+ )
+ cls.changeuser.user_permissions.add(
+ get_perm(Report, get_permission_codename("change", Report._meta))
+ )
def test_no_standard_modeladmin_urls(self):
"""Admin index views don't break when user's ModelAdmin removes standard urls"""
self.client.force_login(self.changeuser)
- r = self.client.get(reverse('admin:index'))
+ r = self.client.get(reverse("admin:index"))
# we shouldn't get a 500 error caused by a NoReverseMatch
self.assertEqual(r.status_code, 200)
- self.client.get(reverse('admin:logout'))
+ self.client.get(reverse("admin:logout"))
-@skipUnlessDBFeature('can_defer_constraint_checks')
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@skipUnlessDBFeature("can_defer_constraint_checks")
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewDeletedObjectsTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.deleteuser = User.objects.create_user(username='deleteuser', password='secret', is_staff=True)
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.deleteuser = User.objects.create_user(
+ username="deleteuser", password="secret", is_staff=True
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
- )
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
-
- cls.v1 = Villain.objects.create(name='Adam')
- cls.v2 = Villain.objects.create(name='Sue')
- cls.sv1 = SuperVillain.objects.create(name='Bob')
- cls.pl1 = Plot.objects.create(name='World Domination', team_leader=cls.v1, contact=cls.v2)
- cls.pl2 = Plot.objects.create(name='World Peace', team_leader=cls.v2, contact=cls.v2)
- cls.pl3 = Plot.objects.create(name='Corn Conspiracy', team_leader=cls.v1, contact=cls.v1)
- cls.pd1 = PlotDetails.objects.create(details='almost finished', plot=cls.pl1)
- cls.sh1 = SecretHideout.objects.create(location='underground bunker', villain=cls.v1)
- cls.sh2 = SecretHideout.objects.create(location='floating castle', villain=cls.sv1)
- cls.ssh1 = SuperSecretHideout.objects.create(location='super floating castle!', supervillain=cls.sv1)
- cls.cy1 = CyclicOne.objects.create(name='I am recursive', two_id=1)
- cls.cy2 = CyclicTwo.objects.create(name='I am recursive too', one_id=1)
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
+ )
+
+ cls.v1 = Villain.objects.create(name="Adam")
+ cls.v2 = Villain.objects.create(name="Sue")
+ cls.sv1 = SuperVillain.objects.create(name="Bob")
+ cls.pl1 = Plot.objects.create(
+ name="World Domination", team_leader=cls.v1, contact=cls.v2
+ )
+ cls.pl2 = Plot.objects.create(
+ name="World Peace", team_leader=cls.v2, contact=cls.v2
+ )
+ cls.pl3 = Plot.objects.create(
+ name="Corn Conspiracy", team_leader=cls.v1, contact=cls.v1
+ )
+ cls.pd1 = PlotDetails.objects.create(details="almost finished", plot=cls.pl1)
+ cls.sh1 = SecretHideout.objects.create(
+ location="underground bunker", villain=cls.v1
+ )
+ cls.sh2 = SecretHideout.objects.create(
+ location="floating castle", villain=cls.sv1
+ )
+ cls.ssh1 = SuperSecretHideout.objects.create(
+ location="super floating castle!", supervillain=cls.sv1
+ )
+ cls.cy1 = CyclicOne.objects.create(name="I am recursive", two_id=1)
+ cls.cy2 = CyclicTwo.objects.create(name="I am recursive too", one_id=1)
def setUp(self):
self.client.force_login(self.superuser)
@@ -2680,12 +3271,15 @@ class AdminViewDeletedObjectsTest(TestCase):
"""
pattern = re.compile(
r'<li>Plot: <a href="%s">World Domination</a>\s*<ul>\s*'
- r'<li>Plot details: <a href="%s">almost finished</a>' % (
- reverse('admin:admin_views_plot_change', args=(self.pl1.pk,)),
- reverse('admin:admin_views_plotdetails_change', args=(self.pd1.pk,)),
+ r'<li>Plot details: <a href="%s">almost finished</a>'
+ % (
+ reverse("admin:admin_views_plot_change", args=(self.pl1.pk,)),
+ reverse("admin:admin_views_plotdetails_change", args=(self.pd1.pk,)),
)
)
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.v1.pk,))
+ )
self.assertRegex(response.content.decode(), pattern)
def test_cyclic(self):
@@ -2694,24 +3288,33 @@ class AdminViewDeletedObjectsTest(TestCase):
listed once.
"""
one = '<li>Cyclic one: <a href="%s">I am recursive</a>' % (
- reverse('admin:admin_views_cyclicone_change', args=(self.cy1.pk,)),
+ reverse("admin:admin_views_cyclicone_change", args=(self.cy1.pk,)),
)
two = '<li>Cyclic two: <a href="%s">I am recursive too</a>' % (
- reverse('admin:admin_views_cyclictwo_change', args=(self.cy2.pk,)),
+ reverse("admin:admin_views_cyclictwo_change", args=(self.cy2.pk,)),
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_cyclicone_delete", args=(self.cy1.pk,))
)
- response = self.client.get(reverse('admin:admin_views_cyclicone_delete', args=(self.cy1.pk,)))
self.assertContains(response, one, 1)
self.assertContains(response, two, 1)
def test_perms_needed(self):
self.client.logout()
- delete_user = User.objects.get(username='deleteuser')
- delete_user.user_permissions.add(get_perm(Plot, get_permission_codename('delete', Plot._meta)))
+ delete_user = User.objects.get(username="deleteuser")
+ delete_user.user_permissions.add(
+ get_perm(Plot, get_permission_codename("delete", Plot._meta))
+ )
self.client.force_login(self.deleteuser)
- response = self.client.get(reverse('admin:admin_views_plot_delete', args=(self.pl1.pk,)))
- self.assertContains(response, "your account doesn't have permission to delete the following types of objects")
+ response = self.client.get(
+ reverse("admin:admin_views_plot_delete", args=(self.pl1.pk,))
+ )
+ self.assertContains(
+ response,
+ "your account doesn't have permission to delete the following types of objects",
+ )
self.assertContains(response, "<li>plot details</li>")
def test_protected(self):
@@ -2719,15 +3322,21 @@ class AdminViewDeletedObjectsTest(TestCase):
a1 = Answer.objects.create(question=q, answer="Because.")
a2 = Answer.objects.create(question=q, answer="Yes.")
- response = self.client.get(reverse('admin:admin_views_question_delete', args=(q.pk,)))
- self.assertContains(response, "would require deleting the following protected related objects")
+ response = self.client.get(
+ reverse("admin:admin_views_question_delete", args=(q.pk,))
+ )
+ self.assertContains(
+ response, "would require deleting the following protected related objects"
+ )
self.assertContains(
response,
- '<li>Answer: <a href="%s">Because.</a></li>' % reverse('admin:admin_views_answer_change', args=(a1.pk,))
+ '<li>Answer: <a href="%s">Because.</a></li>'
+ % reverse("admin:admin_views_answer_change", args=(a1.pk,)),
)
self.assertContains(
response,
- '<li>Answer: <a href="%s">Yes.</a></li>' % reverse('admin:admin_views_answer_change', args=(a2.pk,))
+ '<li>Answer: <a href="%s">Yes.</a></li>'
+ % reverse("admin:admin_views_answer_change", args=(a2.pk,)),
)
def test_post_delete_protected(self):
@@ -2735,43 +3344,51 @@ class AdminViewDeletedObjectsTest(TestCase):
A POST request to delete protected objects should display the page
which says the deletion is prohibited.
"""
- q = Question.objects.create(question='Why?')
- Answer.objects.create(question=q, answer='Because.')
+ q = Question.objects.create(question="Why?")
+ Answer.objects.create(question=q, answer="Because.")
- response = self.client.post(reverse('admin:admin_views_question_delete', args=(q.pk,)), {'post': 'yes'})
+ response = self.client.post(
+ reverse("admin:admin_views_question_delete", args=(q.pk,)), {"post": "yes"}
+ )
self.assertEqual(Question.objects.count(), 1)
- self.assertContains(response, "would require deleting the following protected related objects")
+ self.assertContains(
+ response, "would require deleting the following protected related objects"
+ )
def test_restricted(self):
- album = Album.objects.create(title='Amaryllis')
- song = Song.objects.create(album=album, name='Unity')
- response = self.client.get(reverse('admin:admin_views_album_delete', args=(album.pk,)))
+ album = Album.objects.create(title="Amaryllis")
+ song = Song.objects.create(album=album, name="Unity")
+ response = self.client.get(
+ reverse("admin:admin_views_album_delete", args=(album.pk,))
+ )
self.assertContains(
response,
- 'would require deleting the following protected related objects',
+ "would require deleting the following protected related objects",
)
self.assertContains(
response,
'<li>Song: <a href="%s">Unity</a></li>'
- % reverse('admin:admin_views_song_change', args=(song.pk,))
+ % reverse("admin:admin_views_song_change", args=(song.pk,)),
)
def test_post_delete_restricted(self):
- album = Album.objects.create(title='Amaryllis')
- Song.objects.create(album=album, name='Unity')
+ album = Album.objects.create(title="Amaryllis")
+ Song.objects.create(album=album, name="Unity")
response = self.client.post(
- reverse('admin:admin_views_album_delete', args=(album.pk,)),
- {'post': 'yes'},
+ reverse("admin:admin_views_album_delete", args=(album.pk,)),
+ {"post": "yes"},
)
self.assertEqual(Album.objects.count(), 1)
self.assertContains(
response,
- 'would require deleting the following protected related objects',
+ "would require deleting the following protected related objects",
)
def test_not_registered(self):
should_contain = """<li>Secret hideout: underground bunker"""
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.v1.pk,))
+ )
self.assertContains(response, should_contain, 1)
def test_multiple_fkeys_to_same_model(self):
@@ -2781,11 +3398,15 @@ class AdminViewDeletedObjectsTest(TestCase):
objects to delete.
"""
should_contain = '<li>Plot: <a href="%s">World Domination</a>' % reverse(
- 'admin:admin_views_plot_change', args=(self.pl1.pk,)
+ "admin:admin_views_plot_change", args=(self.pl1.pk,)
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.v1.pk,))
)
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v1.pk,)))
self.assertContains(response, should_contain)
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v2.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.v2.pk,))
+ )
self.assertContains(response, should_contain)
def test_multiple_fkeys_to_same_instance(self):
@@ -2795,9 +3416,11 @@ class AdminViewDeletedObjectsTest(TestCase):
once.
"""
should_contain = '<li>Plot: <a href="%s">World Peace</a></li>' % reverse(
- 'admin:admin_views_plot_change', args=(self.pl2.pk,)
+ "admin:admin_views_plot_change", args=(self.pl2.pk,)
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.v2.pk,))
)
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.v2.pk,)))
self.assertContains(response, should_contain, 1)
def test_inheritance(self):
@@ -2807,17 +3430,21 @@ class AdminViewDeletedObjectsTest(TestCase):
for deletion, as well as any relationships they have.
"""
should_contain = [
- '<li>Villain: <a href="%s">Bob</a>' % reverse('admin:admin_views_villain_change', args=(self.sv1.pk,)),
- '<li>Super villain: <a href="%s">Bob</a>' % reverse(
- 'admin:admin_views_supervillain_change', args=(self.sv1.pk,)
- ),
- '<li>Secret hideout: floating castle',
- '<li>Super secret hideout: super floating castle!',
+ '<li>Villain: <a href="%s">Bob</a>'
+ % reverse("admin:admin_views_villain_change", args=(self.sv1.pk,)),
+ '<li>Super villain: <a href="%s">Bob</a>'
+ % reverse("admin:admin_views_supervillain_change", args=(self.sv1.pk,)),
+ "<li>Secret hideout: floating castle",
+ "<li>Super secret hideout: super floating castle!",
]
- response = self.client.get(reverse('admin:admin_views_villain_delete', args=(self.sv1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_villain_delete", args=(self.sv1.pk,))
+ )
for should in should_contain:
self.assertContains(response, should, 1)
- response = self.client.get(reverse('admin:admin_views_supervillain_delete', args=(self.sv1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_supervillain_delete", args=(self.sv1.pk,))
+ )
for should in should_contain:
self.assertContains(response, should, 1)
@@ -2827,10 +3454,13 @@ class AdminViewDeletedObjectsTest(TestCase):
those objects should be listed for deletion.
"""
plot = self.pl3
- tag = FunkyTag.objects.create(content_object=plot, name='hott')
+ tag = FunkyTag.objects.create(content_object=plot, name="hott")
should_contain = '<li>Funky tag: <a href="%s">hott' % reverse(
- 'admin:admin_views_funkytag_change', args=(tag.id,))
- response = self.client.get(reverse('admin:admin_views_plot_delete', args=(plot.pk,)))
+ "admin:admin_views_funkytag_change", args=(tag.id,)
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_plot_delete", args=(plot.pk,))
+ )
self.assertContains(response, should_contain)
def test_generic_relations_with_related_query_name(self):
@@ -2839,64 +3469,89 @@ class AdminViewDeletedObjectsTest(TestCase):
GenericRelation(related_query_name='...') pointing to it, those objects
should be listed for deletion.
"""
- bookmark = Bookmark.objects.create(name='djangoproject')
- tag = FunkyTag.objects.create(content_object=bookmark, name='django')
- tag_url = reverse('admin:admin_views_funkytag_change', args=(tag.id,))
+ bookmark = Bookmark.objects.create(name="djangoproject")
+ tag = FunkyTag.objects.create(content_object=bookmark, name="django")
+ tag_url = reverse("admin:admin_views_funkytag_change", args=(tag.id,))
should_contain = '<li>Funky tag: <a href="%s">django' % tag_url
- response = self.client.get(reverse('admin:admin_views_bookmark_delete', args=(bookmark.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_bookmark_delete", args=(bookmark.pk,))
+ )
self.assertContains(response, should_contain)
def test_delete_view_uses_get_deleted_objects(self):
"""The delete view uses ModelAdmin.get_deleted_objects()."""
- book = Book.objects.create(name='Test Book')
- response = self.client.get(reverse('admin2:admin_views_book_delete', args=(book.pk,)))
+ book = Book.objects.create(name="Test Book")
+ response = self.client.get(
+ reverse("admin2:admin_views_book_delete", args=(book.pk,))
+ )
# BookAdmin.get_deleted_objects() returns custom text.
- self.assertContains(response, 'a deletable object')
+ self.assertContains(response, "a deletable object")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class TestGenericRelations(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.v1 = Villain.objects.create(name='Adam')
- cls.pl3 = Plot.objects.create(name='Corn Conspiracy', team_leader=cls.v1, contact=cls.v1)
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.v1 = Villain.objects.create(name="Adam")
+ cls.pl3 = Plot.objects.create(
+ name="Corn Conspiracy", team_leader=cls.v1, contact=cls.v1
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_generic_content_object_in_list_display(self):
- FunkyTag.objects.create(content_object=self.pl3, name='hott')
- response = self.client.get(reverse('admin:admin_views_funkytag_changelist'))
+ FunkyTag.objects.create(content_object=self.pl3, name="hott")
+ response = self.client.get(reverse("admin:admin_views_funkytag_changelist"))
self.assertContains(response, "%s</td>" % self.pl3)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewStringPrimaryKeyTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
cls.pk = (
"abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 "
r"""-_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`"""
)
cls.m1 = ModelWithStringPrimaryKey.objects.create(string_pk=cls.pk)
- content_type_pk = ContentType.objects.get_for_model(ModelWithStringPrimaryKey).pk
+ content_type_pk = ContentType.objects.get_for_model(
+ ModelWithStringPrimaryKey
+ ).pk
user_pk = cls.superuser.pk
- LogEntry.objects.log_action(user_pk, content_type_pk, cls.pk, cls.pk, 2, change_message='Changed something')
+ LogEntry.objects.log_action(
+ user_pk,
+ content_type_pk,
+ cls.pk,
+ cls.pk,
+ 2,
+ change_message="Changed something",
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -2907,57 +3562,82 @@ class AdminViewStringPrimaryKeyTest(TestCase):
key should work.
Refs #12349, #18550.
"""
- response = self.client.get(reverse('admin:admin_views_modelwithstringprimarykey_history', args=(self.pk,)))
+ response = self.client.get(
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_history", args=(self.pk,)
+ )
+ )
self.assertContains(response, escape(self.pk))
- self.assertContains(response, 'Changed something')
+ self.assertContains(response, "Changed something")
def test_get_change_view(self):
"Retrieving the object using urlencoded form of primary key should work"
- response = self.client.get(reverse('admin:admin_views_modelwithstringprimarykey_change', args=(self.pk,)))
+ response = self.client.get(
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_change", args=(self.pk,)
+ )
+ )
self.assertContains(response, escape(self.pk))
def test_changelist_to_changeform_link(self):
"Link to the changeform of the object in changelist should use reverse() and be quoted -- #18072"
- response = self.client.get(reverse('admin:admin_views_modelwithstringprimarykey_changelist'))
+ response = self.client.get(
+ reverse("admin:admin_views_modelwithstringprimarykey_changelist")
+ )
# this URL now comes through reverse(), thus url quoting and iri_to_uri encoding
pk_final_url = escape(iri_to_uri(quote(self.pk)))
change_url = reverse(
- 'admin:admin_views_modelwithstringprimarykey_change', args=('__fk__',)
- ).replace('__fk__', pk_final_url)
- should_contain = '<th class="field-__str__"><a href="%s">%s</a></th>' % (change_url, escape(self.pk))
+ "admin:admin_views_modelwithstringprimarykey_change", args=("__fk__",)
+ ).replace("__fk__", pk_final_url)
+ should_contain = '<th class="field-__str__"><a href="%s">%s</a></th>' % (
+ change_url,
+ escape(self.pk),
+ )
self.assertContains(response, should_contain)
def test_recentactions_link(self):
"The link from the recent actions list referring to the changeform of the object should be quoted"
- response = self.client.get(reverse('admin:index'))
- link = reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(self.pk),))
+ response = self.client.get(reverse("admin:index"))
+ link = reverse(
+ "admin:admin_views_modelwithstringprimarykey_change", args=(quote(self.pk),)
+ )
should_contain = """<a href="%s">%s</a>""" % (escape(link), escape(self.pk))
self.assertContains(response, should_contain)
def test_deleteconfirmation_link(self):
"The link from the delete confirmation page referring back to the changeform of the object should be quoted"
- url = reverse('admin:admin_views_modelwithstringprimarykey_delete', args=(quote(self.pk),))
+ url = reverse(
+ "admin:admin_views_modelwithstringprimarykey_delete", args=(quote(self.pk),)
+ )
response = self.client.get(url)
# this URL now comes through reverse(), thus url quoting and iri_to_uri encoding
change_url = reverse(
- 'admin:admin_views_modelwithstringprimarykey_change', args=('__fk__',)
- ).replace('__fk__', escape(iri_to_uri(quote(self.pk))))
+ "admin:admin_views_modelwithstringprimarykey_change", args=("__fk__",)
+ ).replace("__fk__", escape(iri_to_uri(quote(self.pk))))
should_contain = '<a href="%s">%s</a>' % (change_url, escape(self.pk))
self.assertContains(response, should_contain)
def test_url_conflicts_with_add(self):
"A model with a primary key that ends with add or is `add` should be visible"
- add_model = ModelWithStringPrimaryKey.objects.create(pk="i have something to add")
+ add_model = ModelWithStringPrimaryKey.objects.create(
+ pk="i have something to add"
+ )
add_model.save()
response = self.client.get(
- reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(add_model.pk),))
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_change",
+ args=(quote(add_model.pk),),
+ )
)
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
add_model2 = ModelWithStringPrimaryKey.objects.create(pk="add")
- add_url = reverse('admin:admin_views_modelwithstringprimarykey_add')
- change_url = reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(add_model2.pk),))
+ add_url = reverse("admin:admin_views_modelwithstringprimarykey_add")
+ change_url = reverse(
+ "admin:admin_views_modelwithstringprimarykey_change",
+ args=(quote(add_model2.pk),),
+ )
self.assertNotEqual(add_url, change_url)
def test_url_conflicts_with_delete(self):
@@ -2965,7 +3645,10 @@ class AdminViewStringPrimaryKeyTest(TestCase):
delete_model = ModelWithStringPrimaryKey(pk="delete")
delete_model.save()
response = self.client.get(
- reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(delete_model.pk),))
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_change",
+ args=(quote(delete_model.pk),),
+ )
)
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
@@ -2975,17 +3658,23 @@ class AdminViewStringPrimaryKeyTest(TestCase):
history_model = ModelWithStringPrimaryKey(pk="history")
history_model.save()
response = self.client.get(
- reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(history_model.pk),))
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_change",
+ args=(quote(history_model.pk),),
+ )
)
should_contain = """<h1>Change model with string primary key</h1>"""
self.assertContains(response, should_contain)
def test_shortcut_view_with_escaping(self):
"'View on site should' work properly with char fields"
- model = ModelWithStringPrimaryKey(pk='abc_123')
+ model = ModelWithStringPrimaryKey(pk="abc_123")
model.save()
response = self.client.get(
- reverse('admin:admin_views_modelwithstringprimarykey_change', args=(quote(model.pk),))
+ reverse(
+ "admin:admin_views_modelwithstringprimarykey_change",
+ args=(quote(model.pk),),
+ )
)
should_contain = '/%s/" class="viewsitelink">' % model.pk
self.assertContains(response, should_contain)
@@ -2993,16 +3682,20 @@ class AdminViewStringPrimaryKeyTest(TestCase):
def test_change_view_history_link(self):
"""Object history button link should work and contain the pk value quoted."""
url = reverse(
- 'admin:%s_modelwithstringprimarykey_change' % ModelWithStringPrimaryKey._meta.app_label,
- args=(quote(self.pk),)
+ "admin:%s_modelwithstringprimarykey_change"
+ % ModelWithStringPrimaryKey._meta.app_label,
+ args=(quote(self.pk),),
)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
expected_link = reverse(
- 'admin:%s_modelwithstringprimarykey_history' % ModelWithStringPrimaryKey._meta.app_label,
- args=(quote(self.pk),)
+ "admin:%s_modelwithstringprimarykey_history"
+ % ModelWithStringPrimaryKey._meta.app_label,
+ args=(quote(self.pk),),
+ )
+ self.assertContains(
+ response, '<a href="%s" class="historylink"' % escape(expected_link)
)
- self.assertContains(response, '<a href="%s" class="historylink"' % escape(expected_link))
def test_redirect_on_add_view_continue_button(self):
"""As soon as an object is added using "Save and continue editing"
@@ -3012,29 +3705,31 @@ class AdminViewStringPrimaryKeyTest(TestCase):
like slash or underscore, these characters must be escaped (see #22266)
"""
response = self.client.post(
- reverse('admin:admin_views_modelwithstringprimarykey_add'),
+ reverse("admin:admin_views_modelwithstringprimarykey_add"),
{
- 'string_pk': '123/history',
+ "string_pk": "123/history",
"_continue": "1", # Save and continue editing
- }
+ },
)
self.assertEqual(response.status_code, 302) # temporary redirect
- self.assertIn('/123_2Fhistory/', response.headers['location']) # PK is quoted
+ self.assertIn("/123_2Fhistory/", response.headers["location"]) # PK is quoted
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class SecureViewTests(TestCase):
"""
Test behavior of a view protected by the staff_member_required decorator.
"""
def test_secure_view_shows_login_if_not_logged_in(self):
- secure_url = reverse('secure_view')
+ secure_url = reverse("secure_view")
response = self.client.get(secure_url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), secure_url))
+ self.assertRedirects(
+ response, "%s?next=%s" % (reverse("admin:login"), secure_url)
+ )
response = self.client.get(secure_url, follow=True)
- self.assertTemplateUsed(response, 'admin/login.html')
+ self.assertTemplateUsed(response, "admin/login.html")
self.assertEqual(response.context[REDIRECT_FIELD_NAME], secure_url)
def test_staff_member_required_decorator_works_with_argument(self):
@@ -3042,32 +3737,53 @@ class SecureViewTests(TestCase):
Staff_member_required decorator works with an argument
(redirect_field_name).
"""
- secure_url = '/test_admin/admin/secure-view2/'
+ secure_url = "/test_admin/admin/secure-view2/"
response = self.client.get(secure_url)
- self.assertRedirects(response, '%s?myfield=%s' % (reverse('admin:login'), secure_url))
+ self.assertRedirects(
+ response, "%s?myfield=%s" % (reverse("admin:login"), secure_url)
+ )
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewUnicodeTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.b1 = Book.objects.create(name='Lærdommer')
- cls.p1 = Promo.objects.create(name='<Promo for Lærdommer>', book=cls.b1)
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.b1 = Book.objects.create(name="Lærdommer")
+ cls.p1 = Promo.objects.create(name="<Promo for Lærdommer>", book=cls.b1)
cls.chap1 = Chapter.objects.create(
- title='Norske bostaver æøå skaper problemer', content='<p>Svært frustrerende med UnicodeDecodeErro</p>',
- book=cls.b1
+ title="Norske bostaver æøå skaper problemer",
+ content="<p>Svært frustrerende med UnicodeDecodeErro</p>",
+ book=cls.b1,
)
cls.chap2 = Chapter.objects.create(
- title='Kjærlighet', content='<p>La kjærligheten til de lidende seire.</p>', book=cls.b1)
- cls.chap3 = Chapter.objects.create(title='Kjærlighet', content='<p>Noe innhold</p>', book=cls.b1)
- cls.chap4 = ChapterXtra1.objects.create(chap=cls.chap1, xtra='<Xtra(1) Norske bostaver æøå skaper problemer>')
- cls.chap5 = ChapterXtra1.objects.create(chap=cls.chap2, xtra='<Xtra(1) Kjærlighet>')
- cls.chap6 = ChapterXtra1.objects.create(chap=cls.chap3, xtra='<Xtra(1) Kjærlighet>')
- cls.chap7 = ChapterXtra2.objects.create(chap=cls.chap1, xtra='<Xtra(2) Norske bostaver æøå skaper problemer>')
- cls.chap8 = ChapterXtra2.objects.create(chap=cls.chap2, xtra='<Xtra(2) Kjærlighet>')
- cls.chap9 = ChapterXtra2.objects.create(chap=cls.chap3, xtra='<Xtra(2) Kjærlighet>')
+ title="Kjærlighet",
+ content="<p>La kjærligheten til de lidende seire.</p>",
+ book=cls.b1,
+ )
+ cls.chap3 = Chapter.objects.create(
+ title="Kjærlighet", content="<p>Noe innhold</p>", book=cls.b1
+ )
+ cls.chap4 = ChapterXtra1.objects.create(
+ chap=cls.chap1, xtra="<Xtra(1) Norske bostaver æøå skaper problemer>"
+ )
+ cls.chap5 = ChapterXtra1.objects.create(
+ chap=cls.chap2, xtra="<Xtra(1) Kjærlighet>"
+ )
+ cls.chap6 = ChapterXtra1.objects.create(
+ chap=cls.chap3, xtra="<Xtra(1) Kjærlighet>"
+ )
+ cls.chap7 = ChapterXtra2.objects.create(
+ chap=cls.chap1, xtra="<Xtra(2) Norske bostaver æøå skaper problemer>"
+ )
+ cls.chap8 = ChapterXtra2.objects.create(
+ chap=cls.chap2, xtra="<Xtra(2) Kjærlighet>"
+ )
+ cls.chap9 = ChapterXtra2.objects.create(
+ chap=cls.chap3, xtra="<Xtra(2) Kjærlighet>"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -3102,62 +3818,75 @@ class AdminViewUnicodeTest(TestCase):
"chapter_set-5-content": "",
}
- response = self.client.post(reverse('admin:admin_views_book_change', args=(self.b1.pk,)), post_data)
+ response = self.client.post(
+ reverse("admin:admin_views_book_change", args=(self.b1.pk,)), post_data
+ )
self.assertEqual(response.status_code, 302) # redirect somewhere
def test_unicode_delete(self):
"""
The delete_view handles non-ASCII characters
"""
- delete_dict = {'post': 'yes'}
- delete_url = reverse('admin:admin_views_book_delete', args=(self.b1.pk,))
+ delete_dict = {"post": "yes"}
+ delete_url = reverse("admin:admin_views_book_delete", args=(self.b1.pk,))
response = self.client.get(delete_url)
self.assertEqual(response.status_code, 200)
response = self.client.post(delete_url, delete_dict)
- self.assertRedirects(response, reverse('admin:admin_views_book_changelist'))
+ self.assertRedirects(response, reverse("admin:admin_views_book_changelist"))
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewListEditable(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
- cls.per1 = Person.objects.create(name='John Mauchly', gender=1, alive=True)
- cls.per2 = Person.objects.create(name='Grace Hopper', gender=1, alive=False)
- cls.per3 = Person.objects.create(name='Guido van Rossum', gender=1, alive=True)
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
+ )
+ cls.per1 = Person.objects.create(name="John Mauchly", gender=1, alive=True)
+ cls.per2 = Person.objects.create(name="Grace Hopper", gender=1, alive=False)
+ cls.per3 = Person.objects.create(name="Guido van Rossum", gender=1, alive=True)
def setUp(self):
self.client.force_login(self.superuser)
def test_inheritance(self):
- Podcast.objects.create(name="This Week in Django", release_date=datetime.date.today())
- response = self.client.get(reverse('admin:admin_views_podcast_changelist'))
+ Podcast.objects.create(
+ name="This Week in Django", release_date=datetime.date.today()
+ )
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"))
self.assertEqual(response.status_code, 200)
def test_inheritance_2(self):
Vodcast.objects.create(name="This Week in Django", released=True)
- response = self.client.get(reverse('admin:admin_views_vodcast_changelist'))
+ response = self.client.get(reverse("admin:admin_views_vodcast_changelist"))
self.assertEqual(response.status_code, 200)
def test_custom_pk(self):
- Language.objects.create(iso='en', name='English', english_name='English')
- response = self.client.get(reverse('admin:admin_views_language_changelist'))
+ Language.objects.create(iso="en", name="English", english_name="English")
+ response = self.client.get(reverse("admin:admin_views_language_changelist"))
self.assertEqual(response.status_code, 200)
def test_changelist_input_html(self):
- response = self.client.get(reverse('admin:admin_views_person_changelist'))
+ response = self.client.get(reverse("admin:admin_views_person_changelist"))
# 2 inputs per object(the field and the hidden id field) = 6
# 4 management hidden fields = 4
# 4 action inputs (3 regular checkboxes, 1 checkbox to select all)
@@ -3177,42 +3906,35 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-gender": "1",
"form-0-id": str(self.per1.pk),
-
"form-1-gender": "2",
"form-1-id": str(self.per2.pk),
-
"form-2-alive": "checked",
"form-2-gender": "1",
"form-2-id": str(self.per3.pk),
-
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_person_changelist'),
- data, follow=True)
- self.assertEqual(len(response.context['messages']), 1)
+ response = self.client.post(
+ reverse("admin:admin_views_person_changelist"), data, follow=True
+ )
+ self.assertEqual(len(response.context["messages"]), 1)
def test_post_submission(self):
data = {
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-gender": "1",
"form-0-id": str(self.per1.pk),
-
"form-1-gender": "2",
"form-1-id": str(self.per2.pk),
-
"form-2-alive": "checked",
"form-2-gender": "1",
"form-2-id": str(self.per3.pk),
-
"_save": "Save",
}
- self.client.post(reverse('admin:admin_views_person_changelist'), data)
+ self.client.post(reverse("admin:admin_views_person_changelist"), data)
self.assertIs(Person.objects.get(name="John Mauchly").alive, False)
self.assertEqual(Person.objects.get(name="Grace Hopper").gender, 2)
@@ -3222,18 +3944,17 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "2",
"form-INITIAL_FORMS": "2",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(self.per1.pk),
"form-0-gender": "1",
"form-0-alive": "checked",
-
"form-1-id": str(self.per3.pk),
"form-1-gender": "1",
"form-1-alive": "checked",
-
"_save": "Save",
}
- self.client.post(reverse('admin:admin_views_person_changelist') + '?gender__exact=1', data)
+ self.client.post(
+ reverse("admin:admin_views_person_changelist") + "?gender__exact=1", data
+ )
self.assertIs(Person.objects.get(name="John Mauchly").alive, True)
@@ -3242,13 +3963,13 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "1",
"form-INITIAL_FORMS": "1",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(self.per1.pk),
"form-0-gender": "1",
-
"_save": "Save",
}
- self.client.post(reverse('admin:admin_views_person_changelist') + '?q=john', data)
+ self.client.post(
+ reverse("admin:admin_views_person_changelist") + "?q=john", data
+ )
self.assertIs(Person.objects.get(name="John Mauchly").alive, False)
@@ -3257,73 +3978,75 @@ class AdminViewListEditable(TestCase):
Non-field errors are displayed for each of the forms in the
changelist's formset.
"""
- fd1 = FoodDelivery.objects.create(reference='123', driver='bill', restaurant='thai')
- fd2 = FoodDelivery.objects.create(reference='456', driver='bill', restaurant='india')
- fd3 = FoodDelivery.objects.create(reference='789', driver='bill', restaurant='pizza')
+ fd1 = FoodDelivery.objects.create(
+ reference="123", driver="bill", restaurant="thai"
+ )
+ fd2 = FoodDelivery.objects.create(
+ reference="456", driver="bill", restaurant="india"
+ )
+ fd3 = FoodDelivery.objects.create(
+ reference="789", driver="bill", restaurant="pizza"
+ )
data = {
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(fd1.id),
"form-0-reference": "123",
"form-0-driver": "bill",
"form-0-restaurant": "thai",
-
# Same data as above: Forbidden because of unique_together!
"form-1-id": str(fd2.id),
"form-1-reference": "456",
"form-1-driver": "bill",
"form-1-restaurant": "thai",
-
"form-2-id": str(fd3.id),
"form-2-reference": "789",
"form-2-driver": "bill",
"form-2-restaurant": "pizza",
-
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_fooddelivery_changelist'), data)
+ response = self.client.post(
+ reverse("admin:admin_views_fooddelivery_changelist"), data
+ )
self.assertContains(
response,
'<tr><td colspan="4"><ul class="errorlist nonfield"><li>Food delivery '
- 'with this Driver and Restaurant already exists.</li></ul></td></tr>',
+ "with this Driver and Restaurant already exists.</li></ul></td></tr>",
1,
- html=True
+ html=True,
)
data = {
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(fd1.id),
"form-0-reference": "123",
"form-0-driver": "bill",
"form-0-restaurant": "thai",
-
# Same data as above: Forbidden because of unique_together!
"form-1-id": str(fd2.id),
"form-1-reference": "456",
"form-1-driver": "bill",
"form-1-restaurant": "thai",
-
# Same data also.
"form-2-id": str(fd3.id),
"form-2-reference": "789",
"form-2-driver": "bill",
"form-2-restaurant": "thai",
-
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_fooddelivery_changelist'), data)
+ response = self.client.post(
+ reverse("admin:admin_views_fooddelivery_changelist"), data
+ )
self.assertContains(
response,
'<tr><td colspan="4"><ul class="errorlist nonfield"><li>Food delivery '
- 'with this Driver and Restaurant already exists.</li></ul></td></tr>',
+ "with this Driver and Restaurant already exists.</li></ul></td></tr>",
2,
- html=True
+ html=True,
)
def test_non_form_errors(self):
@@ -3332,16 +4055,16 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "1",
"form-INITIAL_FORMS": "1",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(self.per2.pk),
"form-0-alive": "1",
"form-0-gender": "2",
-
# The form processing understands this as a list_editable "Save"
# and not an action "Go".
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_person_changelist'), data)
+ response = self.client.post(
+ reverse("admin:admin_views_person_changelist"), data
+ )
self.assertContains(response, "Grace is not a Zombie")
def test_non_form_errors_is_errorlist(self):
@@ -3350,19 +4073,19 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "1",
"form-INITIAL_FORMS": "1",
"form-MAX_NUM_FORMS": "0",
-
"form-0-id": str(self.per2.pk),
"form-0-alive": "1",
"form-0-gender": "2",
-
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_person_changelist'), data)
- non_form_errors = response.context['cl'].formset.non_form_errors()
+ response = self.client.post(
+ reverse("admin:admin_views_person_changelist"), data
+ )
+ non_form_errors = response.context["cl"].formset.non_form_errors()
self.assertIsInstance(non_form_errors, ErrorList)
self.assertEqual(
str(non_form_errors),
- str(ErrorList(['Grace is not a Zombie'], error_class='nonform')),
+ str(ErrorList(["Grace is not a Zombie"], error_class="nonform")),
)
def test_list_editable_ordering(self):
@@ -3378,28 +4101,25 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "4",
"form-INITIAL_FORMS": "4",
"form-MAX_NUM_FORMS": "0",
-
"form-0-order": "14",
"form-0-id": "1",
"form-0-collector": "1",
-
"form-1-order": "13",
"form-1-id": "2",
"form-1-collector": "1",
-
"form-2-order": "1",
"form-2-id": "3",
"form-2-collector": "1",
-
"form-3-order": "0",
"form-3-id": "4",
"form-3-collector": "1",
-
# The form processing understands this as a list_editable "Save"
# and not an action "Go".
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_category_changelist'), data)
+ response = self.client.post(
+ reverse("admin:admin_views_category_changelist"), data
+ )
# Successful post will redirect
self.assertEqual(response.status_code, 302)
@@ -3413,17 +4133,21 @@ class AdminViewListEditable(TestCase):
"""
Pagination works for list_editable items.
"""
- UnorderedObject.objects.create(id=1, name='Unordered object #1')
- UnorderedObject.objects.create(id=2, name='Unordered object #2')
- UnorderedObject.objects.create(id=3, name='Unordered object #3')
- response = self.client.get(reverse('admin:admin_views_unorderedobject_changelist'))
- self.assertContains(response, 'Unordered object #3')
- self.assertContains(response, 'Unordered object #2')
- self.assertNotContains(response, 'Unordered object #1')
- response = self.client.get(reverse('admin:admin_views_unorderedobject_changelist') + '?p=2')
- self.assertNotContains(response, 'Unordered object #3')
- self.assertNotContains(response, 'Unordered object #2')
- self.assertContains(response, 'Unordered object #1')
+ UnorderedObject.objects.create(id=1, name="Unordered object #1")
+ UnorderedObject.objects.create(id=2, name="Unordered object #2")
+ UnorderedObject.objects.create(id=3, name="Unordered object #3")
+ response = self.client.get(
+ reverse("admin:admin_views_unorderedobject_changelist")
+ )
+ self.assertContains(response, "Unordered object #3")
+ self.assertContains(response, "Unordered object #2")
+ self.assertNotContains(response, "Unordered object #1")
+ response = self.client.get(
+ reverse("admin:admin_views_unorderedobject_changelist") + "?p=2"
+ )
+ self.assertNotContains(response, "Unordered object #3")
+ self.assertNotContains(response, "Unordered object #2")
+ self.assertContains(response, "Unordered object #1")
def test_list_editable_action_submit(self):
# List editable changes should not be executed if the action "Go" button is
@@ -3432,22 +4156,18 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-gender": "1",
"form-0-id": "1",
-
"form-1-gender": "2",
"form-1-id": "2",
-
"form-2-alive": "checked",
"form-2-gender": "1",
"form-2-id": "3",
-
"index": "0",
- "_selected_action": ['3'],
- "action": ['', 'delete_selected'],
+ "_selected_action": ["3"],
+ "action": ["", "delete_selected"],
}
- self.client.post(reverse('admin:admin_views_person_changelist'), data)
+ self.client.post(reverse("admin:admin_views_person_changelist"), data)
self.assertIs(Person.objects.get(name="John Mauchly").alive, True)
self.assertEqual(Person.objects.get(name="Grace Hopper").gender, 1)
@@ -3459,22 +4179,18 @@ class AdminViewListEditable(TestCase):
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
-
"form-0-gender": "1",
"form-0-id": str(self.per1.pk),
-
"form-1-gender": "2",
"form-1-id": str(self.per2.pk),
-
"form-2-alive": "checked",
"form-2-gender": "1",
"form-2-id": str(self.per3.pk),
-
"_save": "Save",
- "_selected_action": ['1'],
- "action": ['', 'delete_selected'],
+ "_selected_action": ["1"],
+ "action": ["", "delete_selected"],
}
- self.client.post(reverse('admin:admin_views_person_changelist'), data)
+ self.client.post(reverse("admin:admin_views_person_changelist"), data)
self.assertIs(Person.objects.get(name="John Mauchly").alive, False)
self.assertEqual(Person.objects.get(name="Grace Hopper").gender, 2)
@@ -3483,10 +4199,12 @@ class AdminViewListEditable(TestCase):
"""
Fields should not be list-editable in popups.
"""
- response = self.client.get(reverse('admin:admin_views_person_changelist'))
- self.assertNotEqual(response.context['cl'].list_editable, ())
- response = self.client.get(reverse('admin:admin_views_person_changelist') + '?%s' % IS_POPUP_VAR)
- self.assertEqual(response.context['cl'].list_editable, ())
+ response = self.client.get(reverse("admin:admin_views_person_changelist"))
+ self.assertNotEqual(response.context["cl"].list_editable, ())
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist") + "?%s" % IS_POPUP_VAR
+ )
+ self.assertEqual(response.context["cl"].list_editable, ())
def test_pk_hidden_fields(self):
"""
@@ -3494,12 +4212,14 @@ class AdminViewListEditable(TestCase):
corresponding human-readable value is displayed instead. The hidden pk
fields are displayed but separately (not in the table) and only once.
"""
- story1 = Story.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...')
+ story1 = Story.objects.create(
+ title="The adventures of Guido", content="Once upon a time in Djangoland..."
+ )
story2 = Story.objects.create(
- title='Crouching Tiger, Hidden Python',
- content='The Python was sneaking into...',
+ title="Crouching Tiger, Hidden Python",
+ content="The Python was sneaking into...",
)
- response = self.client.get(reverse('admin:admin_views_story_changelist'))
+ response = self.client.get(reverse("admin:admin_views_story_changelist"))
# Only one hidden field, in a separate place than the table.
self.assertContains(response, 'id="id_form-0-id"', 1)
self.assertContains(response, 'id="id_form-1-id"', 1)
@@ -3509,27 +4229,27 @@ class AdminViewListEditable(TestCase):
'<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id">'
'<input type="hidden" name="form-1-id" value="%d" id="id_form-1-id">\n</div>'
% (story2.id, story1.id),
- html=True
+ html=True,
)
self.assertContains(response, '<td class="field-id">%d</td>' % story1.id, 1)
self.assertContains(response, '<td class="field-id">%d</td>' % story2.id, 1)
def test_pk_hidden_fields_with_list_display_links(self):
- """ Similarly as test_pk_hidden_fields, but when the hidden pk fields are
- referenced in list_display_links.
- Refs #12475.
+ """Similarly as test_pk_hidden_fields, but when the hidden pk fields are
+ referenced in list_display_links.
+ Refs #12475.
"""
story1 = OtherStory.objects.create(
- title='The adventures of Guido',
- content='Once upon a time in Djangoland...',
+ title="The adventures of Guido",
+ content="Once upon a time in Djangoland...",
)
story2 = OtherStory.objects.create(
- title='Crouching Tiger, Hidden Python',
- content='The Python was sneaking into...',
+ title="Crouching Tiger, Hidden Python",
+ content="The Python was sneaking into...",
)
- link1 = reverse('admin:admin_views_otherstory_change', args=(story1.pk,))
- link2 = reverse('admin:admin_views_otherstory_change', args=(story2.pk,))
- response = self.client.get(reverse('admin:admin_views_otherstory_changelist'))
+ link1 = reverse("admin:admin_views_otherstory_change", args=(story1.pk,))
+ link2 = reverse("admin:admin_views_otherstory_change", args=(story2.pk,))
+ response = self.client.get(reverse("admin:admin_views_otherstory_changelist"))
# Only one hidden field, in a separate place than the table.
self.assertContains(response, 'id="id_form-0-id"', 1)
self.assertContains(response, 'id="id_form-1-id"', 1)
@@ -3539,35 +4259,54 @@ class AdminViewListEditable(TestCase):
'<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id">'
'<input type="hidden" name="form-1-id" value="%d" id="id_form-1-id">\n</div>'
% (story2.id, story1.id),
- html=True
+ html=True,
+ )
+ self.assertContains(
+ response,
+ '<th class="field-id"><a href="%s">%d</a></th>' % (link1, story1.id),
+ 1,
+ )
+ self.assertContains(
+ response,
+ '<th class="field-id"><a href="%s">%d</a></th>' % (link2, story2.id),
+ 1,
)
- self.assertContains(response, '<th class="field-id"><a href="%s">%d</a></th>' % (link1, story1.id), 1)
- self.assertContains(response, '<th class="field-id"><a href="%s">%d</a></th>' % (link2, story2.id), 1)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminSearchTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.joepublicuser = User.objects.create_user(username='joepublic', password='secret')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.joepublicuser = User.objects.create_user(
+ username="joepublic", password="secret"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
- cls.per1 = Person.objects.create(name='John Mauchly', gender=1, alive=True)
- cls.per2 = Person.objects.create(name='Grace Hopper', gender=1, alive=False)
- cls.per3 = Person.objects.create(name='Guido van Rossum', gender=1, alive=True)
- Person.objects.create(name='John Doe', gender=1)
+ cls.per1 = Person.objects.create(name="John Mauchly", gender=1, alive=True)
+ cls.per2 = Person.objects.create(name="Grace Hopper", gender=1, alive=False)
+ cls.per3 = Person.objects.create(name="Guido van Rossum", gender=1, alive=True)
+ Person.objects.create(name="John Doe", gender=1)
Person.objects.create(name='John O"Hara', gender=1)
Person.objects.create(name="John O'Hara", gender=1)
@@ -3576,17 +4315,19 @@ class AdminSearchTest(TestCase):
cls.t3 = Recommender.objects.create()
cls.t4 = Recommendation.objects.create(the_recommender=cls.t3)
- cls.tt1 = TitleTranslation.objects.create(title=cls.t1, text='Bar')
- cls.tt2 = TitleTranslation.objects.create(title=cls.t2, text='Foo')
- cls.tt3 = TitleTranslation.objects.create(title=cls.t3, text='Few')
- cls.tt4 = TitleTranslation.objects.create(title=cls.t4, text='Bas')
+ cls.tt1 = TitleTranslation.objects.create(title=cls.t1, text="Bar")
+ cls.tt2 = TitleTranslation.objects.create(title=cls.t2, text="Foo")
+ cls.tt3 = TitleTranslation.objects.create(title=cls.t3, text="Few")
+ cls.tt4 = TitleTranslation.objects.create(title=cls.t4, text="Bas")
def setUp(self):
self.client.force_login(self.superuser)
def test_search_on_sibling_models(self):
"A search that mentions sibling models"
- response = self.client.get(reverse('admin:admin_views_recommendation_changelist') + '?q=bar')
+ response = self.client.get(
+ reverse("admin:admin_views_recommendation_changelist") + "?q=bar"
+ )
# confirm the search returned 1 object
self.assertContains(response, "\n1 recommendation\n")
@@ -3595,26 +4336,40 @@ class AdminSearchTest(TestCase):
The to_field GET parameter is preserved when a search is performed.
Refs #10918.
"""
- response = self.client.get(reverse('admin:auth_user_changelist') + '?q=joe&%s=id' % TO_FIELD_VAR)
+ response = self.client.get(
+ reverse("admin:auth_user_changelist") + "?q=joe&%s=id" % TO_FIELD_VAR
+ )
self.assertContains(response, "\n1 user\n")
- self.assertContains(response, '<input type="hidden" name="%s" value="id">' % TO_FIELD_VAR, html=True)
+ self.assertContains(
+ response,
+ '<input type="hidden" name="%s" value="id">' % TO_FIELD_VAR,
+ html=True,
+ )
def test_exact_matches(self):
- response = self.client.get(reverse('admin:admin_views_recommendation_changelist') + '?q=bar')
+ response = self.client.get(
+ reverse("admin:admin_views_recommendation_changelist") + "?q=bar"
+ )
# confirm the search returned one object
self.assertContains(response, "\n1 recommendation\n")
- response = self.client.get(reverse('admin:admin_views_recommendation_changelist') + '?q=ba')
+ response = self.client.get(
+ reverse("admin:admin_views_recommendation_changelist") + "?q=ba"
+ )
# confirm the search returned zero objects
self.assertContains(response, "\n0 recommendations\n")
def test_beginning_matches(self):
- response = self.client.get(reverse('admin:admin_views_person_changelist') + '?q=Gui')
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist") + "?q=Gui"
+ )
# confirm the search returned one object
self.assertContains(response, "\n1 person\n")
self.assertContains(response, "Guido")
- response = self.client.get(reverse('admin:admin_views_person_changelist') + '?q=uido')
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist") + "?q=uido"
+ )
# confirm the search returned zero objects
self.assertContains(response, "\n0 persons\n")
self.assertNotContains(response, "Guido")
@@ -3623,12 +4378,16 @@ class AdminSearchTest(TestCase):
PluggableSearchPerson.objects.create(name="Bob", age=10)
PluggableSearchPerson.objects.create(name="Amy", age=20)
- response = self.client.get(reverse('admin:admin_views_pluggablesearchperson_changelist') + '?q=Bob')
+ response = self.client.get(
+ reverse("admin:admin_views_pluggablesearchperson_changelist") + "?q=Bob"
+ )
# confirm the search returned one object
self.assertContains(response, "\n1 pluggable search person\n")
self.assertContains(response, "Bob")
- response = self.client.get(reverse('admin:admin_views_pluggablesearchperson_changelist') + '?q=20')
+ response = self.client.get(
+ reverse("admin:admin_views_pluggablesearchperson_changelist") + "?q=20"
+ )
# confirm the search returned one object
self.assertContains(response, "\n1 pluggable search person\n")
self.assertContains(response, "Amy")
@@ -3641,11 +4400,13 @@ class AdminSearchTest(TestCase):
# + 1 for filtered result + 1 for filtered count
# + 1 for total count
with self.assertNumQueries(5):
- response = self.client.get(reverse('admin:admin_views_person_changelist') + '?q=Gui')
+ response = self.client.get(
+ reverse("admin:admin_views_person_changelist") + "?q=Gui"
+ )
self.assertContains(
response,
"""<span class="small quiet">1 result (<a href="?">6 total</a>)</span>""",
- html=True
+ html=True,
)
def test_no_total_count(self):
@@ -3656,42 +4417,45 @@ class AdminSearchTest(TestCase):
# 1 query for session + 1 for fetching user
# + 1 for filtered result + 1 for filtered count
with self.assertNumQueries(4):
- response = self.client.get(reverse('admin:admin_views_recommendation_changelist') + '?q=bar')
+ response = self.client.get(
+ reverse("admin:admin_views_recommendation_changelist") + "?q=bar"
+ )
self.assertContains(
response,
"""<span class="small quiet">1 result (<a href="?">Show all</a>)</span>""",
- html=True
+ html=True,
)
- self.assertTrue(response.context['cl'].show_admin_actions)
+ self.assertTrue(response.context["cl"].show_admin_actions)
def test_search_with_spaces(self):
- url = reverse('admin:admin_views_person_changelist') + '?q=%s'
+ url = reverse("admin:admin_views_person_changelist") + "?q=%s"
tests = [
('"John Doe"', 1),
("'John Doe'", 1),
- ('John Doe', 0),
+ ("John Doe", 0),
('"John Doe" John', 1),
("'John Doe' John", 1),
("John Doe John", 0),
('"John Do"', 1),
("'John Do'", 1),
- ("'John O\'Hara'", 0),
+ ("'John O'Hara'", 0),
("'John O\\'Hara'", 1),
- ('"John O\"Hara"', 0),
+ ('"John O"Hara"', 0),
('"John O\\"Hara"', 1),
]
for search, hits in tests:
with self.subTest(search=search):
response = self.client.get(url % search)
- self.assertContains(response, '\n%s person' % hits)
+ self.assertContains(response, "\n%s person" % hits)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminInheritedInlinesTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -3706,7 +4470,7 @@ class AdminInheritedInlinesTest(TestCase):
name_re = re.compile(b'name="(.*?)"')
# test the add case
- response = self.client.get(reverse('admin:admin_views_persona_add'))
+ response = self.client.get(reverse("admin:admin_views_persona_add"))
names = name_re.findall(response.content)
# make sure we have no duplicate HTML names
self.assertEqual(len(names), len(set(names)))
@@ -3725,7 +4489,7 @@ class AdminInheritedInlinesTest(TestCase):
"accounts-2-0-username": bar_user,
}
- response = self.client.post(reverse('admin:admin_views_persona_add'), post_data)
+ response = self.client.post(reverse("admin:admin_views_persona_add"), post_data)
self.assertEqual(response.status_code, 302) # redirect somewhere
self.assertEqual(Persona.objects.count(), 1)
self.assertEqual(FooAccount.objects.count(), 1)
@@ -3740,31 +4504,31 @@ class AdminInheritedInlinesTest(TestCase):
# test the edit case
- response = self.client.get(reverse('admin:admin_views_persona_change', args=(persona_id,)))
+ response = self.client.get(
+ reverse("admin:admin_views_persona_change", args=(persona_id,))
+ )
names = name_re.findall(response.content)
# make sure we have no duplicate HTML names
self.assertEqual(len(names), len(set(names)))
post_data = {
"name": "Test Name",
-
"accounts-TOTAL_FORMS": "2",
"accounts-INITIAL_FORMS": "1",
"accounts-MAX_NUM_FORMS": "0",
-
"accounts-0-username": "%s-1" % foo_user,
"accounts-0-account_ptr": str(foo_id),
"accounts-0-persona": str(persona_id),
-
"accounts-2-TOTAL_FORMS": "2",
"accounts-2-INITIAL_FORMS": "1",
"accounts-2-MAX_NUM_FORMS": "0",
-
"accounts-2-0-username": "%s-1" % bar_user,
"accounts-2-0-account_ptr": str(bar_id),
"accounts-2-0-persona": str(persona_id),
}
- response = self.client.post(reverse('admin:admin_views_persona_change', args=(persona_id,)), post_data)
+ response = self.client.post(
+ reverse("admin:admin_views_persona_change", args=(persona_id,)), post_data
+ )
self.assertEqual(response.status_code, 302)
self.assertEqual(Persona.objects.count(), 1)
self.assertEqual(FooAccount.objects.count(), 1)
@@ -3774,12 +4538,13 @@ class AdminInheritedInlinesTest(TestCase):
self.assertEqual(Persona.objects.all()[0].accounts.count(), 2)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class TestCustomChangeList(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -3790,21 +4555,22 @@ class TestCustomChangeList(TestCase):
"""
# Insert some data
post_data = {"name": "First Gadget"}
- response = self.client.post(reverse('admin:admin_views_gadget_add'), post_data)
+ response = self.client.post(reverse("admin:admin_views_gadget_add"), post_data)
self.assertEqual(response.status_code, 302) # redirect somewhere
# Hit the page once to get messages out of the queue message list
- response = self.client.get(reverse('admin:admin_views_gadget_changelist'))
+ response = self.client.get(reverse("admin:admin_views_gadget_changelist"))
# Data is still not visible on the page
- response = self.client.get(reverse('admin:admin_views_gadget_changelist'))
- self.assertNotContains(response, 'First Gadget')
+ response = self.client.get(reverse("admin:admin_views_gadget_changelist"))
+ self.assertNotContains(response, "First Gadget")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class TestInlineNotEditable(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -3813,73 +4579,74 @@ class TestInlineNotEditable(TestCase):
"""
InlineModelAdmin broken?
"""
- response = self.client.get(reverse('admin:admin_views_parent_add'))
+ response = self.client.get(reverse("admin:admin_views_parent_add"))
self.assertEqual(response.status_code, 200)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminCustomQuerysetTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
cls.pks = [EmptyModel.objects.create().id for i in range(3)]
def setUp(self):
self.client.force_login(self.superuser)
self.super_login = {
- REDIRECT_FIELD_NAME: reverse('admin:index'),
- 'username': 'super',
- 'password': 'secret',
+ REDIRECT_FIELD_NAME: reverse("admin:index"),
+ "username": "super",
+ "password": "secret",
}
def test_changelist_view(self):
- response = self.client.get(reverse('admin:admin_views_emptymodel_changelist'))
+ response = self.client.get(reverse("admin:admin_views_emptymodel_changelist"))
for i in self.pks:
if i > 1:
- self.assertContains(response, 'Primary key = %s' % i)
+ self.assertContains(response, "Primary key = %s" % i)
else:
- self.assertNotContains(response, 'Primary key = %s' % i)
+ self.assertNotContains(response, "Primary key = %s" % i)
def test_changelist_view_count_queries(self):
# create 2 Person objects
- Person.objects.create(name='person1', gender=1)
- Person.objects.create(name='person2', gender=2)
- changelist_url = reverse('admin:admin_views_person_changelist')
+ Person.objects.create(name="person1", gender=1)
+ Person.objects.create(name="person2", gender=2)
+ changelist_url = reverse("admin:admin_views_person_changelist")
# 5 queries are expected: 1 for the session, 1 for the user,
# 2 for the counts and 1 for the objects on the page
with self.assertNumQueries(5):
resp = self.client.get(changelist_url)
- self.assertEqual(resp.context['selection_note'], '0 of 2 selected')
- self.assertEqual(resp.context['selection_note_all'], 'All 2 selected')
+ self.assertEqual(resp.context["selection_note"], "0 of 2 selected")
+ self.assertEqual(resp.context["selection_note_all"], "All 2 selected")
with self.assertNumQueries(5):
- extra = {'q': 'not_in_name'}
+ extra = {"q": "not_in_name"}
resp = self.client.get(changelist_url, extra)
- self.assertEqual(resp.context['selection_note'], '0 of 0 selected')
- self.assertEqual(resp.context['selection_note_all'], 'All 0 selected')
+ self.assertEqual(resp.context["selection_note"], "0 of 0 selected")
+ self.assertEqual(resp.context["selection_note_all"], "All 0 selected")
with self.assertNumQueries(5):
- extra = {'q': 'person'}
+ extra = {"q": "person"}
resp = self.client.get(changelist_url, extra)
- self.assertEqual(resp.context['selection_note'], '0 of 2 selected')
- self.assertEqual(resp.context['selection_note_all'], 'All 2 selected')
+ self.assertEqual(resp.context["selection_note"], "0 of 2 selected")
+ self.assertEqual(resp.context["selection_note_all"], "All 2 selected")
with self.assertNumQueries(5):
- extra = {'gender__exact': '1'}
+ extra = {"gender__exact": "1"}
resp = self.client.get(changelist_url, extra)
- self.assertEqual(resp.context['selection_note'], '0 of 1 selected')
- self.assertEqual(resp.context['selection_note_all'], '1 selected')
+ self.assertEqual(resp.context["selection_note"], "0 of 1 selected")
+ self.assertEqual(resp.context["selection_note_all"], "1 selected")
def test_change_view(self):
for i in self.pks:
- url = reverse('admin:admin_views_emptymodel_change', args=(i,))
+ url = reverse("admin:admin_views_emptymodel_change", args=(i,))
response = self.client.get(url, follow=True)
if i > 1:
self.assertEqual(response.status_code, 200)
else:
- self.assertRedirects(response, reverse('admin:index'))
+ self.assertRedirects(response, reverse("admin:index"))
self.assertEqual(
- [m.message for m in response.context['messages']],
- ['empty model with ID “1” doesn’t exist. Perhaps it was deleted?']
+ [m.message for m in response.context["messages"]],
+ ["empty model with ID “1” doesn’t exist. Perhaps it was deleted?"],
)
def test_add_model_modeladmin_defer_qs(self):
@@ -3892,7 +4659,9 @@ class AdminCustomQuerysetTest(TestCase):
"author": "Candidate, Best",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_coverletter_add'), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_coverletter_add"), post_data, follow=True
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(CoverLetter.objects.count(), 1)
# Message should contain non-ugly model verbose name
@@ -3900,8 +4669,9 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The cover letter “<a href="%s">'
- 'Candidate, Best</a>” was added successfully.</li>' %
- reverse('admin:admin_views_coverletter_change', args=(pk,)), html=True
+ "Candidate, Best</a>” was added successfully.</li>"
+ % reverse("admin:admin_views_coverletter_change", args=(pk,)),
+ html=True,
)
# model has no __str__ method
@@ -3911,7 +4681,9 @@ class AdminCustomQuerysetTest(TestCase):
"content": "What's this SMS thing?",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_shortmessage_add'), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_shortmessage_add"), post_data, follow=True
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(ShortMessage.objects.count(), 1)
# Message should contain non-ugly model verbose name
@@ -3919,8 +4691,9 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The short message “<a href="%s">'
- '%s</a>” was added successfully.</li>' %
- (reverse('admin:admin_views_shortmessage_change', args=(sm.pk,)), sm), html=True
+ "%s</a>” was added successfully.</li>"
+ % (reverse("admin:admin_views_shortmessage_change", args=(sm.pk,)), sm),
+ html=True,
)
def test_add_model_modeladmin_only_qs(self):
@@ -3933,7 +4706,9 @@ class AdminCustomQuerysetTest(TestCase):
"title": "Urgent telegram",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_telegram_add'), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_telegram_add"), post_data, follow=True
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(Telegram.objects.count(), 1)
# Message should contain non-ugly model verbose name
@@ -3941,8 +4716,9 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The telegram “<a href="%s">'
- 'Urgent telegram</a>” was added successfully.</li>' %
- reverse('admin:admin_views_telegram_change', args=(pk,)), html=True
+ "Urgent telegram</a>” was added successfully.</li>"
+ % reverse("admin:admin_views_telegram_change", args=(pk,)),
+ html=True,
)
# model has no __str__ method
@@ -3952,7 +4728,9 @@ class AdminCustomQuerysetTest(TestCase):
"title": "My Modified Paper Title",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_paper_add'), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_paper_add"), post_data, follow=True
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(Paper.objects.count(), 1)
# Message should contain non-ugly model verbose name
@@ -3960,8 +4738,9 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The paper “<a href="%s">'
- '%s</a>” was added successfully.</li>' %
- (reverse('admin:admin_views_paper_change', args=(p.pk,)), p), html=True
+ "%s</a>” was added successfully.</li>"
+ % (reverse("admin:admin_views_paper_change", args=(p.pk,)), p),
+ html=True,
)
def test_edit_model_modeladmin_defer_qs(self):
@@ -3970,14 +4749,16 @@ class AdminCustomQuerysetTest(TestCase):
# model has __str__ method
cl = CoverLetter.objects.create(author="John Doe")
self.assertEqual(CoverLetter.objects.count(), 1)
- response = self.client.get(reverse('admin:admin_views_coverletter_change', args=(cl.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_coverletter_change", args=(cl.pk,))
+ )
self.assertEqual(response.status_code, 200)
# Emulate model instance edit via the admin
post_data = {
"author": "John Doe II",
"_save": "Save",
}
- url = reverse('admin:admin_views_coverletter_change', args=(cl.pk,))
+ url = reverse("admin:admin_views_coverletter_change", args=(cl.pk,))
response = self.client.post(url, post_data, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(CoverLetter.objects.count(), 1)
@@ -3986,21 +4767,24 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The cover letter “<a href="%s">'
- 'John Doe II</a>” was changed successfully.</li>' %
- reverse('admin:admin_views_coverletter_change', args=(cl.pk,)), html=True
+ "John Doe II</a>” was changed successfully.</li>"
+ % reverse("admin:admin_views_coverletter_change", args=(cl.pk,)),
+ html=True,
)
# model has no __str__ method
sm = ShortMessage.objects.create(content="This is expensive")
self.assertEqual(ShortMessage.objects.count(), 1)
- response = self.client.get(reverse('admin:admin_views_shortmessage_change', args=(sm.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_shortmessage_change", args=(sm.pk,))
+ )
self.assertEqual(response.status_code, 200)
# Emulate model instance edit via the admin
post_data = {
"content": "Too expensive",
"_save": "Save",
}
- url = reverse('admin:admin_views_shortmessage_change', args=(sm.pk,))
+ url = reverse("admin:admin_views_shortmessage_change", args=(sm.pk,))
response = self.client.post(url, post_data, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(ShortMessage.objects.count(), 1)
@@ -4009,8 +4793,9 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The short message “<a href="%s">'
- '%s</a>” was changed successfully.</li>' %
- (reverse('admin:admin_views_shortmessage_change', args=(sm.pk,)), sm), html=True
+ "%s</a>” was changed successfully.</li>"
+ % (reverse("admin:admin_views_shortmessage_change", args=(sm.pk,)), sm),
+ html=True,
)
def test_edit_model_modeladmin_only_qs(self):
@@ -4019,14 +4804,20 @@ class AdminCustomQuerysetTest(TestCase):
# model has __str__ method
t = Telegram.objects.create(title="First Telegram")
self.assertEqual(Telegram.objects.count(), 1)
- response = self.client.get(reverse('admin:admin_views_telegram_change', args=(t.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_telegram_change", args=(t.pk,))
+ )
self.assertEqual(response.status_code, 200)
# Emulate model instance edit via the admin
post_data = {
"title": "Telegram without typo",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_telegram_change', args=(t.pk,)), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_telegram_change", args=(t.pk,)),
+ post_data,
+ follow=True,
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(Telegram.objects.count(), 1)
# Message should contain non-ugly model verbose name. The instance
@@ -4034,21 +4825,28 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The telegram “<a href="%s">'
- 'Telegram without typo</a>” was changed successfully.</li>' %
- reverse('admin:admin_views_telegram_change', args=(t.pk,)), html=True
+ "Telegram without typo</a>” was changed successfully.</li>"
+ % reverse("admin:admin_views_telegram_change", args=(t.pk,)),
+ html=True,
)
# model has no __str__ method
p = Paper.objects.create(title="My Paper Title")
self.assertEqual(Paper.objects.count(), 1)
- response = self.client.get(reverse('admin:admin_views_paper_change', args=(p.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_paper_change", args=(p.pk,))
+ )
self.assertEqual(response.status_code, 200)
# Emulate model instance edit via the admin
post_data = {
"title": "My Modified Paper Title",
"_save": "Save",
}
- response = self.client.post(reverse('admin:admin_views_paper_change', args=(p.pk,)), post_data, follow=True)
+ response = self.client.post(
+ reverse("admin:admin_views_paper_change", args=(p.pk,)),
+ post_data,
+ follow=True,
+ )
self.assertEqual(response.status_code, 200)
self.assertEqual(Paper.objects.count(), 1)
# Message should contain non-ugly model verbose name. The ugly(!)
@@ -4056,41 +4854,51 @@ class AdminCustomQuerysetTest(TestCase):
self.assertContains(
response,
'<li class="success">The paper “<a href="%s">'
- '%s</a>” was changed successfully.</li>' %
- (reverse('admin:admin_views_paper_change', args=(p.pk,)), p), html=True
+ "%s</a>” was changed successfully.</li>"
+ % (reverse("admin:admin_views_paper_change", args=(p.pk,)), p),
+ html=True,
)
def test_history_view_custom_qs(self):
"""
Custom querysets are considered for the admin history view.
"""
- self.client.post(reverse('admin:login'), self.super_login)
+ self.client.post(reverse("admin:login"), self.super_login)
FilteredManager.objects.create(pk=1)
FilteredManager.objects.create(pk=2)
- response = self.client.get(reverse('admin:admin_views_filteredmanager_changelist'))
+ response = self.client.get(
+ reverse("admin:admin_views_filteredmanager_changelist")
+ )
self.assertContains(response, "PK=1")
self.assertContains(response, "PK=2")
self.assertEqual(
- self.client.get(reverse('admin:admin_views_filteredmanager_history', args=(1,))).status_code, 200
+ self.client.get(
+ reverse("admin:admin_views_filteredmanager_history", args=(1,))
+ ).status_code,
+ 200,
)
self.assertEqual(
- self.client.get(reverse('admin:admin_views_filteredmanager_history', args=(2,))).status_code, 200
+ self.client.get(
+ reverse("admin:admin_views_filteredmanager_history", args=(2,))
+ ).status_code,
+ 200,
)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminInlineFileUploadTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
file1 = tempfile.NamedTemporaryFile(suffix=".file1")
- file1.write(b'a' * (2 ** 21))
+ file1.write(b"a" * (2**21))
filename = file1.name
file1.close()
- cls.gallery = Gallery.objects.create(name='Test Gallery')
+ cls.gallery = Gallery.objects.create(name="Test Gallery")
cls.picture = Picture.objects.create(
- name='Test Picture',
+ name="Test Picture",
image=filename,
gallery=cls.gallery,
)
@@ -4100,9 +4908,9 @@ class AdminInlineFileUploadTest(TestCase):
def test_form_has_multipart_enctype(self):
response = self.client.get(
- reverse('admin:admin_views_gallery_change', args=(self.gallery.id,))
+ reverse("admin:admin_views_gallery_change", args=(self.gallery.id,))
)
- self.assertIs(response.context['has_file_field'], True)
+ self.assertIs(response.context["has_file_field"], True)
self.assertContains(response, MULTIPART_ENCTYPE)
def test_inline_file_upload_edit_validation_error_post(self):
@@ -4124,23 +4932,24 @@ class AdminInlineFileUploadTest(TestCase):
"pictures-1-image": "",
}
response = self.client.post(
- reverse('admin:admin_views_gallery_change', args=(self.gallery.id,)), post_data
+ reverse("admin:admin_views_gallery_change", args=(self.gallery.id,)),
+ post_data,
)
self.assertContains(response, b"Currently")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminInlineTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.collector = Collector.objects.create(pk=1, name='John Fowles')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.collector = Collector.objects.create(pk=1, name="John Fowles")
def setUp(self):
self.post_data = {
"name": "Test Name",
-
"widget_set-TOTAL_FORMS": "3",
"widget_set-INITIAL_FORMS": "0",
"widget_set-MAX_NUM_FORMS": "0",
@@ -4153,7 +4962,6 @@ class AdminInlineTests(TestCase):
"widget_set-2-id": "",
"widget_set-2-owner": "1",
"widget_set-2-name": "",
-
"doohickey_set-TOTAL_FORMS": "3",
"doohickey_set-INITIAL_FORMS": "0",
"doohickey_set-MAX_NUM_FORMS": "0",
@@ -4166,7 +4974,6 @@ class AdminInlineTests(TestCase):
"doohickey_set-2-owner": "1",
"doohickey_set-2-code": "",
"doohickey_set-2-name": "",
-
"grommet_set-TOTAL_FORMS": "3",
"grommet_set-INITIAL_FORMS": "0",
"grommet_set-MAX_NUM_FORMS": "0",
@@ -4179,7 +4986,6 @@ class AdminInlineTests(TestCase):
"grommet_set-2-code": "",
"grommet_set-2-owner": "1",
"grommet_set-2-name": "",
-
"whatsit_set-TOTAL_FORMS": "3",
"whatsit_set-INITIAL_FORMS": "0",
"whatsit_set-MAX_NUM_FORMS": "0",
@@ -4192,7 +4998,6 @@ class AdminInlineTests(TestCase):
"whatsit_set-2-owner": "1",
"whatsit_set-2-index": "",
"whatsit_set-2-name": "",
-
"fancydoodad_set-TOTAL_FORMS": "3",
"fancydoodad_set-INITIAL_FORMS": "0",
"fancydoodad_set-MAX_NUM_FORMS": "0",
@@ -4208,7 +5013,6 @@ class AdminInlineTests(TestCase):
"fancydoodad_set-2-owner": "1",
"fancydoodad_set-2-name": "",
"fancydoodad_set-2-expensive": "on",
-
"category_set-TOTAL_FORMS": "3",
"category_set-INITIAL_FORMS": "0",
"category_set-MAX_NUM_FORMS": "0",
@@ -4228,8 +5032,10 @@ class AdminInlineTests(TestCase):
def test_simple_inline(self):
"A simple model can be saved as inlines"
# First add a new inline
- self.post_data['widget_set-0-name'] = "Widget 1"
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data["widget_set-0-name"] = "Widget 1"
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Widget.objects.count(), 1)
@@ -4241,22 +5047,22 @@ class AdminInlineTests(TestCase):
self.assertContains(response, 'name="widget_set-0-id"')
# No file or image fields, no enctype on the forms
- self.assertIs(response.context['has_file_field'], False)
+ self.assertIs(response.context["has_file_field"], False)
self.assertNotContains(response, MULTIPART_ENCTYPE)
# Now resave that inline
- self.post_data['widget_set-INITIAL_FORMS'] = "1"
- self.post_data['widget_set-0-id'] = str(widget_id)
- self.post_data['widget_set-0-name'] = "Widget 1"
+ self.post_data["widget_set-INITIAL_FORMS"] = "1"
+ self.post_data["widget_set-0-id"] = str(widget_id)
+ self.post_data["widget_set-0-name"] = "Widget 1"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Widget.objects.count(), 1)
self.assertEqual(Widget.objects.all()[0].name, "Widget 1")
# Now modify that inline
- self.post_data['widget_set-INITIAL_FORMS'] = "1"
- self.post_data['widget_set-0-id'] = str(widget_id)
- self.post_data['widget_set-0-name'] = "Widget 1 Updated"
+ self.post_data["widget_set-INITIAL_FORMS"] = "1"
+ self.post_data["widget_set-0-id"] = str(widget_id)
+ self.post_data["widget_set-0-name"] = "Widget 1 Updated"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Widget.objects.count(), 1)
@@ -4265,8 +5071,10 @@ class AdminInlineTests(TestCase):
def test_explicit_autofield_inline(self):
"A model with an explicit autofield primary key can be saved as inlines. Regression for #8093"
# First add a new inline
- self.post_data['grommet_set-0-name'] = "Grommet 1"
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data["grommet_set-0-name"] = "Grommet 1"
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Grommet.objects.count(), 1)
@@ -4277,18 +5085,18 @@ class AdminInlineTests(TestCase):
self.assertContains(response, 'name="grommet_set-0-code"')
# Now resave that inline
- self.post_data['grommet_set-INITIAL_FORMS'] = "1"
- self.post_data['grommet_set-0-code'] = str(Grommet.objects.all()[0].code)
- self.post_data['grommet_set-0-name'] = "Grommet 1"
+ self.post_data["grommet_set-INITIAL_FORMS"] = "1"
+ self.post_data["grommet_set-0-code"] = str(Grommet.objects.all()[0].code)
+ self.post_data["grommet_set-0-name"] = "Grommet 1"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Grommet.objects.count(), 1)
self.assertEqual(Grommet.objects.all()[0].name, "Grommet 1")
# Now modify that inline
- self.post_data['grommet_set-INITIAL_FORMS'] = "1"
- self.post_data['grommet_set-0-code'] = str(Grommet.objects.all()[0].code)
- self.post_data['grommet_set-0-name'] = "Grommet 1 Updated"
+ self.post_data["grommet_set-INITIAL_FORMS"] = "1"
+ self.post_data["grommet_set-0-code"] = str(Grommet.objects.all()[0].code)
+ self.post_data["grommet_set-0-name"] = "Grommet 1 Updated"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Grommet.objects.count(), 1)
@@ -4297,9 +5105,11 @@ class AdminInlineTests(TestCase):
def test_char_pk_inline(self):
"A model with a character PK can be saved as inlines. Regression for #10992"
# First add a new inline
- self.post_data['doohickey_set-0-code'] = "DH1"
- self.post_data['doohickey_set-0-name'] = "Doohickey 1"
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data["doohickey_set-0-code"] = "DH1"
+ self.post_data["doohickey_set-0-name"] = "Doohickey 1"
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(DooHickey.objects.count(), 1)
@@ -4310,18 +5120,18 @@ class AdminInlineTests(TestCase):
self.assertContains(response, 'name="doohickey_set-0-code"')
# Now resave that inline
- self.post_data['doohickey_set-INITIAL_FORMS'] = "1"
- self.post_data['doohickey_set-0-code'] = "DH1"
- self.post_data['doohickey_set-0-name'] = "Doohickey 1"
+ self.post_data["doohickey_set-INITIAL_FORMS"] = "1"
+ self.post_data["doohickey_set-0-code"] = "DH1"
+ self.post_data["doohickey_set-0-name"] = "Doohickey 1"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(DooHickey.objects.count(), 1)
self.assertEqual(DooHickey.objects.all()[0].name, "Doohickey 1")
# Now modify that inline
- self.post_data['doohickey_set-INITIAL_FORMS'] = "1"
- self.post_data['doohickey_set-0-code'] = "DH1"
- self.post_data['doohickey_set-0-name'] = "Doohickey 1 Updated"
+ self.post_data["doohickey_set-INITIAL_FORMS"] = "1"
+ self.post_data["doohickey_set-0-code"] = "DH1"
+ self.post_data["doohickey_set-0-name"] = "Doohickey 1 Updated"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(DooHickey.objects.count(), 1)
@@ -4330,9 +5140,11 @@ class AdminInlineTests(TestCase):
def test_integer_pk_inline(self):
"A model with an integer PK can be saved as inlines. Regression for #10992"
# First add a new inline
- self.post_data['whatsit_set-0-index'] = "42"
- self.post_data['whatsit_set-0-name'] = "Whatsit 1"
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data["whatsit_set-0-index"] = "42"
+ self.post_data["whatsit_set-0-name"] = "Whatsit 1"
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Whatsit.objects.count(), 1)
@@ -4343,18 +5155,18 @@ class AdminInlineTests(TestCase):
self.assertContains(response, 'name="whatsit_set-0-index"')
# Now resave that inline
- self.post_data['whatsit_set-INITIAL_FORMS'] = "1"
- self.post_data['whatsit_set-0-index'] = "42"
- self.post_data['whatsit_set-0-name'] = "Whatsit 1"
+ self.post_data["whatsit_set-INITIAL_FORMS"] = "1"
+ self.post_data["whatsit_set-0-index"] = "42"
+ self.post_data["whatsit_set-0-name"] = "Whatsit 1"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Whatsit.objects.count(), 1)
self.assertEqual(Whatsit.objects.all()[0].name, "Whatsit 1")
# Now modify that inline
- self.post_data['whatsit_set-INITIAL_FORMS'] = "1"
- self.post_data['whatsit_set-0-index'] = "42"
- self.post_data['whatsit_set-0-name'] = "Whatsit 1 Updated"
+ self.post_data["whatsit_set-INITIAL_FORMS"] = "1"
+ self.post_data["whatsit_set-0-index"] = "42"
+ self.post_data["whatsit_set-0-name"] = "Whatsit 1 Updated"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Whatsit.objects.count(), 1)
@@ -4363,8 +5175,10 @@ class AdminInlineTests(TestCase):
def test_inherited_inline(self):
"An inherited model can be saved as inlines. Regression for #11042"
# First add a new inline
- self.post_data['fancydoodad_set-0-name'] = "Fancy Doodad 1"
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data["fancydoodad_set-0-name"] = "Fancy Doodad 1"
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(FancyDoodad.objects.count(), 1)
@@ -4376,18 +5190,18 @@ class AdminInlineTests(TestCase):
self.assertContains(response, 'name="fancydoodad_set-0-doodad_ptr"')
# Now resave that inline
- self.post_data['fancydoodad_set-INITIAL_FORMS'] = "1"
- self.post_data['fancydoodad_set-0-doodad_ptr'] = str(doodad_pk)
- self.post_data['fancydoodad_set-0-name'] = "Fancy Doodad 1"
+ self.post_data["fancydoodad_set-INITIAL_FORMS"] = "1"
+ self.post_data["fancydoodad_set-0-doodad_ptr"] = str(doodad_pk)
+ self.post_data["fancydoodad_set-0-name"] = "Fancy Doodad 1"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(FancyDoodad.objects.count(), 1)
self.assertEqual(FancyDoodad.objects.all()[0].name, "Fancy Doodad 1")
# Now modify that inline
- self.post_data['fancydoodad_set-INITIAL_FORMS'] = "1"
- self.post_data['fancydoodad_set-0-doodad_ptr'] = str(doodad_pk)
- self.post_data['fancydoodad_set-0-name'] = "Fancy Doodad 1 Updated"
+ self.post_data["fancydoodad_set-INITIAL_FORMS"] = "1"
+ self.post_data["fancydoodad_set-0-doodad_ptr"] = str(doodad_pk)
+ self.post_data["fancydoodad_set-0-name"] = "Fancy Doodad 1 Updated"
response = self.client.post(collector_url, self.post_data)
self.assertEqual(response.status_code, 302)
self.assertEqual(FancyDoodad.objects.count(), 1)
@@ -4404,42 +5218,38 @@ class AdminInlineTests(TestCase):
Category.objects.create(id=4, order=0, collector=self.collector)
# NB: The order values must be changed so that the items are reordered.
- self.post_data.update({
- "name": "Frederick Clegg",
-
- "category_set-TOTAL_FORMS": "7",
- "category_set-INITIAL_FORMS": "4",
- "category_set-MAX_NUM_FORMS": "0",
-
- "category_set-0-order": "14",
- "category_set-0-id": "1",
- "category_set-0-collector": "1",
-
- "category_set-1-order": "13",
- "category_set-1-id": "2",
- "category_set-1-collector": "1",
-
- "category_set-2-order": "1",
- "category_set-2-id": "3",
- "category_set-2-collector": "1",
-
- "category_set-3-order": "0",
- "category_set-3-id": "4",
- "category_set-3-collector": "1",
-
- "category_set-4-order": "",
- "category_set-4-id": "",
- "category_set-4-collector": "1",
-
- "category_set-5-order": "",
- "category_set-5-id": "",
- "category_set-5-collector": "1",
-
- "category_set-6-order": "",
- "category_set-6-id": "",
- "category_set-6-collector": "1",
- })
- collector_url = reverse('admin:admin_views_collector_change', args=(self.collector.pk,))
+ self.post_data.update(
+ {
+ "name": "Frederick Clegg",
+ "category_set-TOTAL_FORMS": "7",
+ "category_set-INITIAL_FORMS": "4",
+ "category_set-MAX_NUM_FORMS": "0",
+ "category_set-0-order": "14",
+ "category_set-0-id": "1",
+ "category_set-0-collector": "1",
+ "category_set-1-order": "13",
+ "category_set-1-id": "2",
+ "category_set-1-collector": "1",
+ "category_set-2-order": "1",
+ "category_set-2-id": "3",
+ "category_set-2-collector": "1",
+ "category_set-3-order": "0",
+ "category_set-3-id": "4",
+ "category_set-3-collector": "1",
+ "category_set-4-order": "",
+ "category_set-4-id": "",
+ "category_set-4-collector": "1",
+ "category_set-5-order": "",
+ "category_set-5-id": "",
+ "category_set-5-collector": "1",
+ "category_set-6-order": "",
+ "category_set-6-id": "",
+ "category_set-6-collector": "1",
+ }
+ )
+ collector_url = reverse(
+ "admin:admin_views_collector_change", args=(self.collector.pk,)
+ )
response = self.client.post(collector_url, self.post_data)
# Successful post will redirect
self.assertEqual(response.status_code, 302)
@@ -4452,105 +5262,124 @@ class AdminInlineTests(TestCase):
self.assertEqual(Category.objects.get(id=4).order, 0)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class NeverCacheTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
def setUp(self):
self.client.force_login(self.superuser)
def test_admin_index(self):
"Check the never-cache status of the main index"
- response = self.client.get(reverse('admin:index'))
+ response = self.client.get(reverse("admin:index"))
self.assertEqual(get_max_age(response), 0)
def test_app_index(self):
"Check the never-cache status of an application index"
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertEqual(get_max_age(response), 0)
def test_model_index(self):
"Check the never-cache status of a model index"
- response = self.client.get(reverse('admin:admin_views_fabric_changelist'))
+ response = self.client.get(reverse("admin:admin_views_fabric_changelist"))
self.assertEqual(get_max_age(response), 0)
def test_model_add(self):
"Check the never-cache status of a model add page"
- response = self.client.get(reverse('admin:admin_views_fabric_add'))
+ response = self.client.get(reverse("admin:admin_views_fabric_add"))
self.assertEqual(get_max_age(response), 0)
def test_model_view(self):
"Check the never-cache status of a model edit page"
- response = self.client.get(reverse('admin:admin_views_section_change', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(self.s1.pk,))
+ )
self.assertEqual(get_max_age(response), 0)
def test_model_history(self):
"Check the never-cache status of a model history page"
- response = self.client.get(reverse('admin:admin_views_section_history', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_history", args=(self.s1.pk,))
+ )
self.assertEqual(get_max_age(response), 0)
def test_model_delete(self):
"Check the never-cache status of a model delete page"
- response = self.client.get(reverse('admin:admin_views_section_delete', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_delete", args=(self.s1.pk,))
+ )
self.assertEqual(get_max_age(response), 0)
def test_login(self):
"Check the never-cache status of login views"
self.client.logout()
- response = self.client.get(reverse('admin:index'))
+ response = self.client.get(reverse("admin:index"))
self.assertEqual(get_max_age(response), 0)
def test_logout(self):
"Check the never-cache status of logout view"
- response = self.client.get(reverse('admin:logout'))
+ response = self.client.get(reverse("admin:logout"))
self.assertEqual(get_max_age(response), 0)
def test_password_change(self):
"Check the never-cache status of the password change view"
self.client.logout()
- response = self.client.get(reverse('admin:password_change'))
+ response = self.client.get(reverse("admin:password_change"))
self.assertIsNone(get_max_age(response))
def test_password_change_done(self):
"Check the never-cache status of the password change done view"
- response = self.client.get(reverse('admin:password_change_done'))
+ response = self.client.get(reverse("admin:password_change_done"))
self.assertIsNone(get_max_age(response))
def test_JS_i18n(self):
"Check the never-cache status of the JavaScript i18n view"
- response = self.client.get(reverse('admin:jsi18n'))
+ response = self.client.get(reverse("admin:jsi18n"))
self.assertIsNone(get_max_age(response))
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class PrePopulatedTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_prepopulated_on(self):
- response = self.client.get(reverse('admin:admin_views_prepopulatedpost_add'))
+ response = self.client.get(reverse("admin:admin_views_prepopulatedpost_add"))
self.assertContains(response, "&quot;id&quot;: &quot;#id_slug&quot;")
- self.assertContains(response, "&quot;dependency_ids&quot;: [&quot;#id_title&quot;]")
- self.assertContains(response, "&quot;id&quot;: &quot;#id_prepopulatedsubpost_set-0-subslug&quot;")
+ self.assertContains(
+ response, "&quot;dependency_ids&quot;: [&quot;#id_title&quot;]"
+ )
+ self.assertContains(
+ response,
+ "&quot;id&quot;: &quot;#id_prepopulatedsubpost_set-0-subslug&quot;",
+ )
def test_prepopulated_off(self):
- response = self.client.get(reverse('admin:admin_views_prepopulatedpost_change', args=(self.p1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_prepopulatedpost_change", args=(self.p1.pk,))
+ )
self.assertContains(response, "A Long Title")
self.assertNotContains(response, "&quot;id&quot;: &quot;#id_slug&quot;")
- self.assertNotContains(response, "&quot;dependency_ids&quot;: [&quot;#id_title&quot;]")
+ self.assertNotContains(
+ response, "&quot;dependency_ids&quot;: [&quot;#id_title&quot;]"
+ )
self.assertNotContains(
response,
- "&quot;id&quot;: &quot;#id_prepopulatedsubpost_set-0-subslug&quot;"
+ "&quot;id&quot;: &quot;#id_prepopulatedsubpost_set-0-subslug&quot;",
)
@override_settings(USE_THOUSAND_SEPARATOR=True)
@@ -4559,7 +5388,9 @@ class PrePopulatedTest(TestCase):
Regression test for #15938: if USE_THOUSAND_SEPARATOR is set, make sure
that maxLength (in the JavaScript) is rendered without separators.
"""
- response = self.client.get(reverse('admin:admin_views_prepopulatedpostlargeslug_add'))
+ response = self.client.get(
+ reverse("admin:admin_views_prepopulatedpostlargeslug_add")
+ )
self.assertContains(response, "&quot;maxLength&quot;: 1000") # instead of 1,000
def test_view_only_add_form(self):
@@ -4568,38 +5399,44 @@ class PrePopulatedTest(TestCase):
which is present in the add view, even if the
ModelAdmin.has_change_permission() returns False.
"""
- response = self.client.get(reverse('admin7:admin_views_prepopulatedpost_add'))
- self.assertContains(response, 'data-prepopulated-fields=')
- self.assertContains(response, '&quot;id&quot;: &quot;#id_slug&quot;')
+ response = self.client.get(reverse("admin7:admin_views_prepopulatedpost_add"))
+ self.assertContains(response, "data-prepopulated-fields=")
+ self.assertContains(response, "&quot;id&quot;: &quot;#id_slug&quot;")
def test_view_only_change_form(self):
"""
PrePopulatedPostReadOnlyAdmin.prepopulated_fields includes 'slug'. That
doesn't break a view-only change view.
"""
- response = self.client.get(reverse('admin7:admin_views_prepopulatedpost_change', args=(self.p1.pk,)))
+ response = self.client.get(
+ reverse("admin7:admin_views_prepopulatedpost_change", args=(self.p1.pk,))
+ )
self.assertContains(response, 'data-prepopulated-fields="[]"')
self.assertContains(response, '<div class="readonly">%s</div>' % self.p1.slug)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class SeleniumTests(AdminSeleniumTestCase):
- available_apps = ['admin_views'] + AdminSeleniumTestCase.available_apps
+ available_apps = ["admin_views"] + AdminSeleniumTestCase.available_apps
def setUp(self):
- self.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- self.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
+ self.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ self.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
+ )
def test_login_button_centered(self):
from selenium.webdriver.common.by import By
- self.selenium.get(self.live_server_url + reverse('admin:login'))
- button = self.selenium.find_element(By.CSS_SELECTOR, '.submit-row input')
- offset_left = button.get_property('offsetLeft')
- offset_right = (
- button.get_property('offsetParent').get_property('offsetWidth') -
- (offset_left + button.get_property('offsetWidth'))
- )
+
+ self.selenium.get(self.live_server_url + reverse("admin:login"))
+ button = self.selenium.find_element(By.CSS_SELECTOR, ".submit-row input")
+ offset_left = button.get_property("offsetLeft")
+ offset_right = button.get_property("offsetParent").get_property(
+ "offsetWidth"
+ ) - (offset_left + button.get_property("offsetWidth"))
# Use assertAlmostEqual to avoid pixel rounding errors.
self.assertAlmostEqual(offset_left, offset_right, delta=3)
@@ -4610,164 +5447,221 @@ class SeleniumTests(AdminSeleniumTestCase):
Refs #13068, #9264, #9983, #9784.
"""
from selenium.webdriver.common.by import By
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_mainprepopulated_add'))
- self.wait_for('.select2')
+
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ self.selenium.get(
+ self.live_server_url + reverse("admin:admin_views_mainprepopulated_add")
+ )
+ self.wait_for(".select2")
# Main form ----------------------------------------------------------
- self.selenium.find_element(By.ID, 'id_pubdate').send_keys('2012-02-18')
- self.select_option('#id_status', 'option two')
- self.selenium.find_element(By.ID, 'id_name').send_keys(' the mAin nÀMë and it\'s awεšomeıııİ')
- slug1 = self.selenium.find_element(By.ID, 'id_slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_slug2').get_attribute('value')
- slug3 = self.selenium.find_element(By.ID, 'id_slug3').get_attribute('value')
- self.assertEqual(slug1, 'the-main-name-and-its-awesomeiiii-2012-02-18')
- self.assertEqual(slug2, 'option-two-the-main-name-and-its-awesomeiiii')
- self.assertEqual(slug3, 'the-main-n\xe0m\xeb-and-its-aw\u03b5\u0161ome\u0131\u0131\u0131i')
+ self.selenium.find_element(By.ID, "id_pubdate").send_keys("2012-02-18")
+ self.select_option("#id_status", "option two")
+ self.selenium.find_element(By.ID, "id_name").send_keys(
+ " the mAin nÀMë and it's awεšomeıııİ"
+ )
+ slug1 = self.selenium.find_element(By.ID, "id_slug1").get_attribute("value")
+ slug2 = self.selenium.find_element(By.ID, "id_slug2").get_attribute("value")
+ slug3 = self.selenium.find_element(By.ID, "id_slug3").get_attribute("value")
+ self.assertEqual(slug1, "the-main-name-and-its-awesomeiiii-2012-02-18")
+ self.assertEqual(slug2, "option-two-the-main-name-and-its-awesomeiiii")
+ self.assertEqual(
+ slug3, "the-main-n\xe0m\xeb-and-its-aw\u03b5\u0161ome\u0131\u0131\u0131i"
+ )
# Stacked inlines with fieldsets -------------------------------------
# Initial inline
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17')
- self.select_option('#id_relatedprepopulated_set-0-status', 'option one')
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-0-name').send_keys(
- ' here is a sŤāÇkeð inline ! '
- )
- slug1 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-0-slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-0-slug2').get_attribute('value')
- self.assertEqual(slug1, 'here-is-a-stacked-inline-2011-12-17')
- self.assertEqual(slug2, 'option-one-here-is-a-stacked-inline')
- initial_select2_inputs = self.selenium.find_elements(By.CLASS_NAME, 'select2-selection')
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-0-pubdate"
+ ).send_keys("2011-12-17")
+ self.select_option("#id_relatedprepopulated_set-0-status", "option one")
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-0-name"
+ ).send_keys(" here is a sŤāÇkeð inline ! ")
+ slug1 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-0-slug1"
+ ).get_attribute("value")
+ slug2 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-0-slug2"
+ ).get_attribute("value")
+ self.assertEqual(slug1, "here-is-a-stacked-inline-2011-12-17")
+ self.assertEqual(slug2, "option-one-here-is-a-stacked-inline")
+ initial_select2_inputs = self.selenium.find_elements(
+ By.CLASS_NAME, "select2-selection"
+ )
# Inline formsets have empty/invisible forms.
# Only the 4 visible select2 inputs are initialized.
num_initial_select2_inputs = len(initial_select2_inputs)
self.assertEqual(num_initial_select2_inputs, 4)
# Add an inline
- self.selenium.find_elements(By.LINK_TEXT, 'Add another Related prepopulated')[0].click()
+ self.selenium.find_elements(By.LINK_TEXT, "Add another Related prepopulated")[
+ 0
+ ].click()
self.assertEqual(
- len(self.selenium.find_elements(By.CLASS_NAME, 'select2-selection')),
- num_initial_select2_inputs + 2
- )
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-1-pubdate').send_keys('1999-01-25')
- self.select_option('#id_relatedprepopulated_set-1-status', 'option two')
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-1-name').send_keys(
- ' now you haVe anöther sŤāÇkeð inline with a very ... '
- 'loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... '
- )
- slug1 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-1-slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-1-slug2').get_attribute('value')
+ len(self.selenium.find_elements(By.CLASS_NAME, "select2-selection")),
+ num_initial_select2_inputs + 2,
+ )
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-1-pubdate"
+ ).send_keys("1999-01-25")
+ self.select_option("#id_relatedprepopulated_set-1-status", "option two")
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-1-name"
+ ).send_keys(
+ " now you haVe anöther sŤāÇkeð inline with a very ... "
+ "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... "
+ )
+ slug1 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-1-slug1"
+ ).get_attribute("value")
+ slug2 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-1-slug2"
+ ).get_attribute("value")
# 50 characters maximum for slug1 field
- self.assertEqual(slug1, 'now-you-have-another-stacked-inline-with-a-very-lo')
+ self.assertEqual(slug1, "now-you-have-another-stacked-inline-with-a-very-lo")
# 60 characters maximum for slug2 field
- self.assertEqual(slug2, 'option-two-now-you-have-another-stacked-inline-with-a-very-l')
+ self.assertEqual(
+ slug2, "option-two-now-you-have-another-stacked-inline-with-a-very-l"
+ )
# Tabular inlines ----------------------------------------------------
# Initial inline
- element = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-0-status')
- self.selenium.execute_script('window.scrollTo(0, %s);' % element.location['y'])
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-0-pubdate').send_keys('1234-12-07')
- self.select_option('#id_relatedprepopulated_set-2-0-status', 'option two')
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-0-name').send_keys(
- 'And now, with a tÃbűlaŘ inline !!!'
- )
- slug1 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-0-slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-0-slug2').get_attribute('value')
- self.assertEqual(slug1, 'and-now-with-a-tabular-inline-1234-12-07')
- self.assertEqual(slug2, 'option-two-and-now-with-a-tabular-inline')
+ element = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-0-status"
+ )
+ self.selenium.execute_script("window.scrollTo(0, %s);" % element.location["y"])
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-0-pubdate"
+ ).send_keys("1234-12-07")
+ self.select_option("#id_relatedprepopulated_set-2-0-status", "option two")
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-0-name"
+ ).send_keys("And now, with a tÃbűlaŘ inline !!!")
+ slug1 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-0-slug1"
+ ).get_attribute("value")
+ slug2 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-0-slug2"
+ ).get_attribute("value")
+ self.assertEqual(slug1, "and-now-with-a-tabular-inline-1234-12-07")
+ self.assertEqual(slug2, "option-two-and-now-with-a-tabular-inline")
# Add an inline
# Button may be outside the browser frame.
- element = self.selenium.find_elements(By.LINK_TEXT, 'Add another Related prepopulated')[1]
- self.selenium.execute_script('window.scrollTo(0, %s);' % element.location['y'])
+ element = self.selenium.find_elements(
+ By.LINK_TEXT, "Add another Related prepopulated"
+ )[1]
+ self.selenium.execute_script("window.scrollTo(0, %s);" % element.location["y"])
element.click()
self.assertEqual(
- len(self.selenium.find_elements(By.CLASS_NAME, 'select2-selection')),
- num_initial_select2_inputs + 4
- )
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-1-pubdate').send_keys('1981-08-22')
- self.select_option('#id_relatedprepopulated_set-2-1-status', 'option one')
- self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-1-name').send_keys(
- r'tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters'
- )
- slug1 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-1-slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_relatedprepopulated_set-2-1-slug2').get_attribute('value')
- self.assertEqual(slug1, 'tabular-inline-with-ignored-characters-1981-08-22')
- self.assertEqual(slug2, 'option-one-tabular-inline-with-ignored-characters')
+ len(self.selenium.find_elements(By.CLASS_NAME, "select2-selection")),
+ num_initial_select2_inputs + 4,
+ )
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-1-pubdate"
+ ).send_keys("1981-08-22")
+ self.select_option("#id_relatedprepopulated_set-2-1-status", "option one")
+ self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-1-name"
+ ).send_keys(r'tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters')
+ slug1 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-1-slug1"
+ ).get_attribute("value")
+ slug2 = self.selenium.find_element(
+ By.ID, "id_relatedprepopulated_set-2-1-slug2"
+ ).get_attribute("value")
+ self.assertEqual(slug1, "tabular-inline-with-ignored-characters-1981-08-22")
+ self.assertEqual(slug2, "option-one-tabular-inline-with-ignored-characters")
# Add an inline without an initial inline.
# The button is outside of the browser frame.
self.selenium.execute_script("window.scrollTo(0, document.body.scrollHeight);")
- self.selenium.find_elements(By.LINK_TEXT, 'Add another Related prepopulated')[2].click()
+ self.selenium.find_elements(By.LINK_TEXT, "Add another Related prepopulated")[
+ 2
+ ].click()
self.assertEqual(
- len(self.selenium.find_elements(By.CLASS_NAME, 'select2-selection')),
- num_initial_select2_inputs + 6
+ len(self.selenium.find_elements(By.CLASS_NAME, "select2-selection")),
+ num_initial_select2_inputs + 6,
)
# Stacked Inlines without fieldsets ----------------------------------
# Initial inline.
- row_id = 'id_relatedprepopulated_set-4-0-'
- self.selenium.find_element(By.ID, f'{row_id}pubdate').send_keys('2011-12-12')
- self.select_option(f'#{row_id}status', 'option one')
- self.selenium.find_element(By.ID, f'{row_id}name').send_keys(' sŤāÇkeð inline ! ')
- slug1 = self.selenium.find_element(By.ID, f'{row_id}slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, f'{row_id}slug2').get_attribute('value')
- self.assertEqual(slug1, 'stacked-inline-2011-12-12')
- self.assertEqual(slug2, 'option-one')
+ row_id = "id_relatedprepopulated_set-4-0-"
+ self.selenium.find_element(By.ID, f"{row_id}pubdate").send_keys("2011-12-12")
+ self.select_option(f"#{row_id}status", "option one")
+ self.selenium.find_element(By.ID, f"{row_id}name").send_keys(
+ " sŤāÇkeð inline ! "
+ )
+ slug1 = self.selenium.find_element(By.ID, f"{row_id}slug1").get_attribute(
+ "value"
+ )
+ slug2 = self.selenium.find_element(By.ID, f"{row_id}slug2").get_attribute(
+ "value"
+ )
+ self.assertEqual(slug1, "stacked-inline-2011-12-12")
+ self.assertEqual(slug2, "option-one")
# Add inline.
self.selenium.find_elements(
By.LINK_TEXT,
- 'Add another Related prepopulated',
+ "Add another Related prepopulated",
)[3].click()
- row_id = 'id_relatedprepopulated_set-4-1-'
- self.selenium.find_element(By.ID, f'{row_id}pubdate').send_keys('1999-01-20')
- self.select_option(f'#{row_id}status', 'option two')
- self.selenium.find_element(By.ID, f'{row_id}name').send_keys(
- ' now you haVe anöther sŤāÇkeð inline with a very loooong '
+ row_id = "id_relatedprepopulated_set-4-1-"
+ self.selenium.find_element(By.ID, f"{row_id}pubdate").send_keys("1999-01-20")
+ self.select_option(f"#{row_id}status", "option two")
+ self.selenium.find_element(By.ID, f"{row_id}name").send_keys(
+ " now you haVe anöther sŤāÇkeð inline with a very loooong "
+ )
+ slug1 = self.selenium.find_element(By.ID, f"{row_id}slug1").get_attribute(
+ "value"
)
- slug1 = self.selenium.find_element(By.ID, f'{row_id}slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, f'{row_id}slug2').get_attribute('value')
- self.assertEqual(slug1, 'now-you-have-another-stacked-inline-with-a-very-lo')
- self.assertEqual(slug2, 'option-two')
+ slug2 = self.selenium.find_element(By.ID, f"{row_id}slug2").get_attribute(
+ "value"
+ )
+ self.assertEqual(slug1, "now-you-have-another-stacked-inline-with-a-very-lo")
+ self.assertEqual(slug2, "option-two")
# Save and check that everything is properly stored in the database
with self.wait_page_loaded():
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.assertEqual(MainPrepopulated.objects.all().count(), 1)
MainPrepopulated.objects.get(
- name=' the mAin nÀMë and it\'s awεšomeıııİ',
- pubdate='2012-02-18',
- status='option two',
- slug1='the-main-name-and-its-awesomeiiii-2012-02-18',
- slug2='option-two-the-main-name-and-its-awesomeiiii',
- slug3='the-main-nàmë-and-its-awεšomeıııi',
+ name=" the mAin nÀMë and it's awεšomeıııİ",
+ pubdate="2012-02-18",
+ status="option two",
+ slug1="the-main-name-and-its-awesomeiiii-2012-02-18",
+ slug2="option-two-the-main-name-and-its-awesomeiiii",
+ slug3="the-main-nàmë-and-its-awεšomeıııi",
)
self.assertEqual(RelatedPrepopulated.objects.all().count(), 6)
RelatedPrepopulated.objects.get(
- name=' here is a sŤāÇkeð inline ! ',
- pubdate='2011-12-17',
- status='option one',
- slug1='here-is-a-stacked-inline-2011-12-17',
- slug2='option-one-here-is-a-stacked-inline',
+ name=" here is a sŤāÇkeð inline ! ",
+ pubdate="2011-12-17",
+ status="option one",
+ slug1="here-is-a-stacked-inline-2011-12-17",
+ slug2="option-one-here-is-a-stacked-inline",
)
RelatedPrepopulated.objects.get(
# 75 characters in name field
- name=' now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo',
- pubdate='1999-01-25',
- status='option two',
- slug1='now-you-have-another-stacked-inline-with-a-very-lo',
- slug2='option-two-now-you-have-another-stacked-inline-with-a-very-l',
+ name=" now you haVe anöther sŤāÇkeð inline with a very ... loooooooooooooooooo",
+ pubdate="1999-01-25",
+ status="option two",
+ slug1="now-you-have-another-stacked-inline-with-a-very-lo",
+ slug2="option-two-now-you-have-another-stacked-inline-with-a-very-l",
)
RelatedPrepopulated.objects.get(
- name='And now, with a tÃbűlaŘ inline !!!',
- pubdate='1234-12-07',
- status='option two',
- slug1='and-now-with-a-tabular-inline-1234-12-07',
- slug2='option-two-and-now-with-a-tabular-inline',
+ name="And now, with a tÃbűlaŘ inline !!!",
+ pubdate="1234-12-07",
+ status="option two",
+ slug1="and-now-with-a-tabular-inline-1234-12-07",
+ slug2="option-two-and-now-with-a-tabular-inline",
)
RelatedPrepopulated.objects.get(
name=r'tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters',
- pubdate='1981-08-22',
- status='option one',
- slug1='tabular-inline-with-ignored-characters-1981-08-22',
- slug2='option-one-tabular-inline-with-ignored-characters',
+ pubdate="1981-08-22",
+ status="option one",
+ slug1="tabular-inline-with-ignored-characters-1981-08-22",
+ slug2="option-one-tabular-inline-with-ignored-characters",
)
def test_populate_existing_object(self):
@@ -4779,37 +5673,41 @@ class SeleniumTests(AdminSeleniumTestCase):
# Slugs are empty to start with.
item = MainPrepopulated.objects.create(
- name=' this is the mAin nÀMë',
- pubdate='2012-02-18',
- status='option two',
- slug1='',
- slug2='',
+ name=" this is the mAin nÀMë",
+ pubdate="2012-02-18",
+ status="option two",
+ slug1="",
+ slug2="",
+ )
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- object_url = self.live_server_url + reverse('admin:admin_views_mainprepopulated_change', args=(item.id,))
+ object_url = self.live_server_url + reverse(
+ "admin:admin_views_mainprepopulated_change", args=(item.id,)
+ )
self.selenium.get(object_url)
- self.selenium.find_element(By.ID, 'id_name').send_keys(' the best')
+ self.selenium.find_element(By.ID, "id_name").send_keys(" the best")
# The slugs got prepopulated since they were originally empty
- slug1 = self.selenium.find_element(By.ID, 'id_slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_slug2').get_attribute('value')
- self.assertEqual(slug1, 'this-is-the-main-name-the-best-2012-02-18')
- self.assertEqual(slug2, 'option-two-this-is-the-main-name-the-best')
+ slug1 = self.selenium.find_element(By.ID, "id_slug1").get_attribute("value")
+ slug2 = self.selenium.find_element(By.ID, "id_slug2").get_attribute("value")
+ self.assertEqual(slug1, "this-is-the-main-name-the-best-2012-02-18")
+ self.assertEqual(slug2, "option-two-this-is-the-main-name-the-best")
# Save the object
with self.wait_page_loaded():
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.get(object_url)
- self.selenium.find_element(By.ID, 'id_name').send_keys(' hello')
+ self.selenium.find_element(By.ID, "id_name").send_keys(" hello")
# The slugs got prepopulated didn't change since they were originally not empty
- slug1 = self.selenium.find_element(By.ID, 'id_slug1').get_attribute('value')
- slug2 = self.selenium.find_element(By.ID, 'id_slug2').get_attribute('value')
- self.assertEqual(slug1, 'this-is-the-main-name-the-best-2012-02-18')
- self.assertEqual(slug2, 'option-two-this-is-the-main-name-the-best')
+ slug1 = self.selenium.find_element(By.ID, "id_slug1").get_attribute("value")
+ slug2 = self.selenium.find_element(By.ID, "id_slug2").get_attribute("value")
+ self.assertEqual(slug1, "this-is-the-main-name-the-best-2012-02-18")
+ self.assertEqual(slug2, "option-two-this-is-the-main-name-the-best")
def test_collapsible_fieldset(self):
"""
@@ -4817,32 +5715,39 @@ class SeleniumTests(AdminSeleniumTestCase):
show/hide the appropriate field section.
"""
from selenium.webdriver.common.by import By
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_article_add'))
- self.assertFalse(self.selenium.find_element(By.ID, 'id_title').is_displayed())
- self.selenium.find_elements(By.LINK_TEXT, 'Show')[0].click()
- self.assertTrue(self.selenium.find_element(By.ID, 'id_title').is_displayed())
- self.assertEqual(self.selenium.find_element(By.ID, 'fieldsetcollapser0').text, "Hide")
+
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ self.selenium.get(
+ self.live_server_url + reverse("admin:admin_views_article_add")
+ )
+ self.assertFalse(self.selenium.find_element(By.ID, "id_title").is_displayed())
+ self.selenium.find_elements(By.LINK_TEXT, "Show")[0].click()
+ self.assertTrue(self.selenium.find_element(By.ID, "id_title").is_displayed())
+ self.assertEqual(
+ self.selenium.find_element(By.ID, "fieldsetcollapser0").text, "Hide"
+ )
def test_selectbox_height_collapsible_fieldset(self):
from selenium.webdriver.common.by import By
self.admin_login(
- username='super',
- password='secret',
- login_url=reverse('admin7:index'),
+ username="super",
+ password="secret",
+ login_url=reverse("admin7:index"),
)
- url = self.live_server_url + reverse('admin7:admin_views_pizza_add')
+ url = self.live_server_url + reverse("admin7:admin_views_pizza_add")
self.selenium.get(url)
- self.selenium.find_elements(By.LINK_TEXT, 'Show')[0].click()
- filter_box = self.selenium.find_element(By.ID, 'id_toppings_filter')
- from_box = self.selenium.find_element(By.ID, 'id_toppings_from')
- to_box = self.selenium.find_element(By.ID, 'id_toppings_to')
+ self.selenium.find_elements(By.LINK_TEXT, "Show")[0].click()
+ filter_box = self.selenium.find_element(By.ID, "id_toppings_filter")
+ from_box = self.selenium.find_element(By.ID, "id_toppings_from")
+ to_box = self.selenium.find_element(By.ID, "id_toppings_to")
self.assertEqual(
- to_box.get_property('offsetHeight'),
+ to_box.get_property("offsetHeight"),
(
- filter_box.get_property('offsetHeight') +
- from_box.get_property('offsetHeight')
+ filter_box.get_property("offsetHeight")
+ + from_box.get_property("offsetHeight")
),
)
@@ -4850,20 +5755,20 @@ class SeleniumTests(AdminSeleniumTestCase):
from selenium.webdriver.common.by import By
self.admin_login(
- username='super',
- password='secret',
- login_url=reverse('admin7:index'),
+ username="super",
+ password="secret",
+ login_url=reverse("admin7:index"),
)
- url = self.live_server_url + reverse('admin7:admin_views_question_add')
+ url = self.live_server_url + reverse("admin7:admin_views_question_add")
self.selenium.get(url)
- filter_box = self.selenium.find_element(By.ID, 'id_related_questions_filter')
- from_box = self.selenium.find_element(By.ID, 'id_related_questions_from')
- to_box = self.selenium.find_element(By.ID, 'id_related_questions_to')
+ filter_box = self.selenium.find_element(By.ID, "id_related_questions_filter")
+ from_box = self.selenium.find_element(By.ID, "id_related_questions_from")
+ to_box = self.selenium.find_element(By.ID, "id_related_questions_to")
self.assertEqual(
- to_box.get_property('offsetHeight'),
+ to_box.get_property("offsetHeight"),
(
- filter_box.get_property('offsetHeight') +
- from_box.get_property('offsetHeight')
+ filter_box.get_property("offsetHeight")
+ + from_box.get_property("offsetHeight")
),
)
@@ -4872,35 +5777,44 @@ class SeleniumTests(AdminSeleniumTestCase):
from selenium.webdriver.common.by import By
# First form field has a single widget
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
with self.wait_page_loaded():
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_picture_add'))
+ self.selenium.get(
+ self.live_server_url + reverse("admin:admin_views_picture_add")
+ )
self.assertEqual(
self.selenium.switch_to.active_element,
- self.selenium.find_element(By.ID, 'id_name')
+ self.selenium.find_element(By.ID, "id_name"),
)
# First form field has a MultiWidget
with self.wait_page_loaded():
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_reservation_add'))
+ self.selenium.get(
+ self.live_server_url + reverse("admin:admin_views_reservation_add")
+ )
self.assertEqual(
self.selenium.switch_to.active_element,
- self.selenium.find_element(By.ID, 'id_start_date_0')
+ self.selenium.find_element(By.ID, "id_start_date_0"),
)
def test_cancel_delete_confirmation(self):
"Cancelling the deletion of an object takes the user back one page."
from selenium.webdriver.common.by import By
+
pizza = Pizza.objects.create(name="Double Cheese")
- url = reverse('admin:admin_views_pizza_change', args=(pizza.id,))
+ url = reverse("admin:admin_views_pizza_change", args=(pizza.id,))
full_url = self.live_server_url + url
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
self.selenium.get(full_url)
- self.selenium.find_element(By.CLASS_NAME, 'deletelink').click()
+ self.selenium.find_element(By.CLASS_NAME, "deletelink").click()
# Click 'cancel' on the delete page.
- self.selenium.find_element(By.CLASS_NAME, 'cancel-link').click()
+ self.selenium.find_element(By.CLASS_NAME, "cancel-link").click()
# Wait until we're back on the change page.
- self.wait_for_text('#content h1', 'Change pizza')
+ self.wait_for_text("#content h1", "Change pizza")
self.assertEqual(self.selenium.current_url, full_url)
self.assertEqual(Pizza.objects.count(), 1)
@@ -4910,19 +5824,22 @@ class SeleniumTests(AdminSeleniumTestCase):
one page.
"""
from selenium.webdriver.common.by import By
+
pizza = Pizza.objects.create(name="Double Cheese")
topping1 = Topping.objects.create(name="Cheddar")
topping2 = Topping.objects.create(name="Mozzarella")
pizza.toppings.add(topping1, topping2)
- url = reverse('admin:admin_views_pizza_change', args=(pizza.id,))
+ url = reverse("admin:admin_views_pizza_change", args=(pizza.id,))
full_url = self.live_server_url + url
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
self.selenium.get(full_url)
- self.selenium.find_element(By.CLASS_NAME, 'deletelink').click()
+ self.selenium.find_element(By.CLASS_NAME, "deletelink").click()
# Click 'cancel' on the delete page.
- self.selenium.find_element(By.CLASS_NAME, 'cancel-link').click()
+ self.selenium.find_element(By.CLASS_NAME, "cancel-link").click()
# Wait until we're back on the change page.
- self.wait_for_text('#content h1', 'Change pizza')
+ self.wait_for_text("#content h1", "Change pizza")
self.assertEqual(self.selenium.current_url, full_url)
self.assertEqual(Pizza.objects.count(), 1)
self.assertEqual(Topping.objects.count(), 2)
@@ -4933,104 +5850,141 @@ class SeleniumTests(AdminSeleniumTestCase):
"""
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
- s1 = Section.objects.create(name='Test section')
+
+ s1 = Section.objects.create(name="Test section")
Article.objects.create(
- title='foo',
- content='<p>Middle content</p>',
+ title="foo",
+ content="<p>Middle content</p>",
date=datetime.datetime(2008, 3, 18, 11, 54, 58),
section=s1,
)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_article_changelist'))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ self.selenium.get(
+ self.live_server_url + reverse("admin:admin_views_article_changelist")
+ )
# Change popup
- self.selenium.find_element(By.ID, 'change_id_form-0-section').click()
+ self.selenium.find_element(By.ID, "change_id_form-0-section").click()
self.wait_for_and_switch_to_popup()
- self.wait_for_text('#content h1', 'Change section')
- name_input = self.selenium.find_element(By.ID, 'id_name')
+ self.wait_for_text("#content h1", "Change section")
+ name_input = self.selenium.find_element(By.ID, "id_name")
name_input.clear()
- name_input.send_keys('<i>edited section</i>')
+ name_input.send_keys("<i>edited section</i>")
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
# Hide sidebar.
- toggle_button = self.selenium.find_element(By.CSS_SELECTOR, '#toggle-nav-sidebar')
+ toggle_button = self.selenium.find_element(
+ By.CSS_SELECTOR, "#toggle-nav-sidebar"
+ )
toggle_button.click()
- select = Select(self.selenium.find_element(By.ID, 'id_form-0-section'))
- self.assertEqual(select.first_selected_option.text, '<i>edited section</i>')
+ select = Select(self.selenium.find_element(By.ID, "id_form-0-section"))
+ self.assertEqual(select.first_selected_option.text, "<i>edited section</i>")
# Rendered select2 input.
- select2_display = self.selenium.find_element(By.CLASS_NAME, 'select2-selection__rendered')
+ select2_display = self.selenium.find_element(
+ By.CLASS_NAME, "select2-selection__rendered"
+ )
# Clear button (×\n) is included in text.
- self.assertEqual(select2_display.text, '×\n<i>edited section</i>')
+ self.assertEqual(select2_display.text, "×\n<i>edited section</i>")
# Add popup
- self.selenium.find_element(By.ID, 'add_id_form-0-section').click()
+ self.selenium.find_element(By.ID, "add_id_form-0-section").click()
self.wait_for_and_switch_to_popup()
- self.wait_for_text('#content h1', 'Add section')
- self.selenium.find_element(By.ID, 'id_name').send_keys('new section')
+ self.wait_for_text("#content h1", "Add section")
+ self.selenium.find_element(By.ID, "id_name").send_keys("new section")
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
- select = Select(self.selenium.find_element(By.ID, 'id_form-0-section'))
- self.assertEqual(select.first_selected_option.text, 'new section')
- select2_display = self.selenium.find_element(By.CLASS_NAME, 'select2-selection__rendered')
+ select = Select(self.selenium.find_element(By.ID, "id_form-0-section"))
+ self.assertEqual(select.first_selected_option.text, "new section")
+ select2_display = self.selenium.find_element(
+ By.CLASS_NAME, "select2-selection__rendered"
+ )
# Clear button (×\n) is included in text.
- self.assertEqual(select2_display.text, '×\nnew section')
+ self.assertEqual(select2_display.text, "×\nnew section")
def test_inline_uuid_pk_edit_with_popup(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
- parent = ParentWithUUIDPK.objects.create(title='test')
+
+ parent = ParentWithUUIDPK.objects.create(title="test")
related_with_parent = RelatedWithUUIDPKModel.objects.create(parent=parent)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- change_url = reverse('admin:admin_views_relatedwithuuidpkmodel_change', args=(related_with_parent.id,))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ change_url = reverse(
+ "admin:admin_views_relatedwithuuidpkmodel_change",
+ args=(related_with_parent.id,),
+ )
self.selenium.get(self.live_server_url + change_url)
- self.selenium.find_element(By.ID, 'change_id_parent').click()
+ self.selenium.find_element(By.ID, "change_id_parent").click()
self.wait_for_and_switch_to_popup()
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
- select = Select(self.selenium.find_element(By.ID, 'id_parent'))
+ select = Select(self.selenium.find_element(By.ID, "id_parent"))
self.assertEqual(select.first_selected_option.text, str(parent.id))
- self.assertEqual(select.first_selected_option.get_attribute('value'), str(parent.id))
+ self.assertEqual(
+ select.first_selected_option.get_attribute("value"), str(parent.id)
+ )
def test_inline_uuid_pk_add_with_popup(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_relatedwithuuidpkmodel_add'))
- self.selenium.find_element(By.ID, 'add_id_parent').click()
+
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ self.selenium.get(
+ self.live_server_url
+ + reverse("admin:admin_views_relatedwithuuidpkmodel_add")
+ )
+ self.selenium.find_element(By.ID, "add_id_parent").click()
self.wait_for_and_switch_to_popup()
- self.selenium.find_element(By.ID, 'id_title').send_keys('test')
+ self.selenium.find_element(By.ID, "id_title").send_keys("test")
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
- select = Select(self.selenium.find_element(By.ID, 'id_parent'))
+ select = Select(self.selenium.find_element(By.ID, "id_parent"))
uuid_id = str(ParentWithUUIDPK.objects.first().id)
self.assertEqual(select.first_selected_option.text, uuid_id)
- self.assertEqual(select.first_selected_option.get_attribute('value'), uuid_id)
+ self.assertEqual(select.first_selected_option.get_attribute("value"), uuid_id)
def test_inline_uuid_pk_delete_with_popup(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
- parent = ParentWithUUIDPK.objects.create(title='test')
+
+ parent = ParentWithUUIDPK.objects.create(title="test")
related_with_parent = RelatedWithUUIDPKModel.objects.create(parent=parent)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- change_url = reverse('admin:admin_views_relatedwithuuidpkmodel_change', args=(related_with_parent.id,))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ change_url = reverse(
+ "admin:admin_views_relatedwithuuidpkmodel_change",
+ args=(related_with_parent.id,),
+ )
self.selenium.get(self.live_server_url + change_url)
- self.selenium.find_element(By.ID, 'delete_id_parent').click()
+ self.selenium.find_element(By.ID, "delete_id_parent").click()
self.wait_for_and_switch_to_popup()
self.selenium.find_element(By.XPATH, '//input[@value="Yes, I’m sure"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
- select = Select(self.selenium.find_element(By.ID, 'id_parent'))
+ select = Select(self.selenium.find_element(By.ID, "id_parent"))
self.assertEqual(ParentWithUUIDPK.objects.count(), 0)
- self.assertEqual(select.first_selected_option.text, '---------')
- self.assertEqual(select.first_selected_option.get_attribute('value'), '')
+ self.assertEqual(select.first_selected_option.text, "---------")
+ self.assertEqual(select.first_selected_option.get_attribute("value"), "")
def test_inline_with_popup_cancel_delete(self):
"""Clicking ""No, take me back" on a delete popup closes the window."""
from selenium.webdriver.common.by import By
- parent = ParentWithUUIDPK.objects.create(title='test')
+
+ parent = ParentWithUUIDPK.objects.create(title="test")
related_with_parent = RelatedWithUUIDPKModel.objects.create(parent=parent)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- change_url = reverse('admin:admin_views_relatedwithuuidpkmodel_change', args=(related_with_parent.id,))
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ change_url = reverse(
+ "admin:admin_views_relatedwithuuidpkmodel_change",
+ args=(related_with_parent.id,),
+ )
self.selenium.get(self.live_server_url + change_url)
- self.selenium.find_element(By.ID, 'delete_id_parent').click()
+ self.selenium.find_element(By.ID, "delete_id_parent").click()
self.wait_for_and_switch_to_popup()
self.selenium.find_element(By.XPATH, '//a[text()="No, take me back"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
@@ -5038,19 +5992,27 @@ class SeleniumTests(AdminSeleniumTestCase):
def test_list_editable_raw_id_fields(self):
from selenium.webdriver.common.by import By
- parent = ParentWithUUIDPK.objects.create(title='test')
- parent2 = ParentWithUUIDPK.objects.create(title='test2')
+
+ parent = ParentWithUUIDPK.objects.create(title="test")
+ parent2 = ParentWithUUIDPK.objects.create(title="test2")
RelatedWithUUIDPKModel.objects.create(parent=parent)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- change_url = reverse('admin:admin_views_relatedwithuuidpkmodel_changelist', current_app=site2.name)
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ change_url = reverse(
+ "admin:admin_views_relatedwithuuidpkmodel_changelist",
+ current_app=site2.name,
+ )
self.selenium.get(self.live_server_url + change_url)
- self.selenium.find_element(By.ID, 'lookup_id_form-0-parent').click()
+ self.selenium.find_element(By.ID, "lookup_id_form-0-parent").click()
self.wait_for_and_switch_to_popup()
# Select "parent2" in the popup.
self.selenium.find_element(By.LINK_TEXT, str(parent2.pk)).click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
# The newly selected pk should appear in the raw id input.
- value = self.selenium.find_element(By.ID, 'id_form-0-parent').get_attribute('value')
+ value = self.selenium.find_element(By.ID, "id_form-0-parent").get_attribute(
+ "value"
+ )
self.assertEqual(value, str(parent2.pk))
def test_input_element_font(self):
@@ -5059,27 +6021,31 @@ class SeleniumTests(AdminSeleniumTestCase):
adds additional CSS to handle this.
"""
from selenium.webdriver.common.by import By
- self.selenium.get(self.live_server_url + reverse('admin:login'))
- element = self.selenium.find_element(By.ID, 'id_username')
+
+ self.selenium.get(self.live_server_url + reverse("admin:login"))
+ element = self.selenium.find_element(By.ID, "id_username")
# Some browsers quotes the fonts, some don't.
fonts = [
font.strip().strip('"')
- for font in element.value_of_css_property('font-family').split(',')
+ for font in element.value_of_css_property("font-family").split(",")
]
self.assertEqual(
fonts,
- ['Roboto', 'Lucida Grande', 'Verdana', 'Arial', 'sans-serif'],
+ ["Roboto", "Lucida Grande", "Verdana", "Arial", "sans-serif"],
)
def test_search_input_filtered_page(self):
from selenium.webdriver.common.by import By
- Person.objects.create(name='Guido van Rossum', gender=1, alive=True)
- Person.objects.create(name='Grace Hopper', gender=1, alive=False)
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- person_url = reverse('admin:admin_views_person_changelist') + '?q=Gui'
+
+ Person.objects.create(name="Guido van Rossum", gender=1, alive=True)
+ Person.objects.create(name="Grace Hopper", gender=1, alive=False)
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ person_url = reverse("admin:admin_views_person_changelist") + "?q=Gui"
self.selenium.get(self.live_server_url + person_url)
self.assertGreater(
- self.selenium.find_element(By.ID, 'searchbar').rect['width'],
+ self.selenium.find_element(By.ID, "searchbar").rect["width"],
50,
)
@@ -5089,63 +6055,75 @@ class SeleniumTests(AdminSeleniumTestCase):
"""
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- add_url = reverse('admin:admin_views_box_add', current_app=site.name)
+
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ add_url = reverse("admin:admin_views_box_add", current_app=site.name)
self.selenium.get(self.live_server_url + add_url)
base_window = self.selenium.current_window_handle
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup()
popup_window_test = self.selenium.current_window_handle
- self.selenium.find_element(By.ID, 'id_title').send_keys('test')
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "id_title").send_keys("test")
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup(num_windows=3)
popup_window_test2 = self.selenium.current_window_handle
- self.selenium.find_element(By.ID, 'id_title').send_keys('test2')
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "id_title").send_keys("test2")
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup(num_windows=4)
- self.selenium.find_element(By.ID, 'id_title').send_keys('test3')
+ self.selenium.find_element(By.ID, "id_title").send_keys("test3")
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(popup_window_test2)
- select = Select(self.selenium.find_element(By.ID, 'id_next_box'))
+ select = Select(self.selenium.find_element(By.ID, "id_next_box"))
next_box_id = str(Box.objects.get(title="test3").id)
- self.assertEqual(select.first_selected_option.get_attribute('value'), next_box_id)
+ self.assertEqual(
+ select.first_selected_option.get_attribute("value"), next_box_id
+ )
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(popup_window_test)
- select = Select(self.selenium.find_element(By.ID, 'id_next_box'))
+ select = Select(self.selenium.find_element(By.ID, "id_next_box"))
next_box_id = str(Box.objects.get(title="test2").id)
- self.assertEqual(select.first_selected_option.get_attribute('value'), next_box_id)
+ self.assertEqual(
+ select.first_selected_option.get_attribute("value"), next_box_id
+ )
self.selenium.find_element(By.XPATH, '//input[@value="Save"]').click()
self.selenium.switch_to.window(base_window)
- select = Select(self.selenium.find_element(By.ID, 'id_next_box'))
+ select = Select(self.selenium.find_element(By.ID, "id_next_box"))
next_box_id = str(Box.objects.get(title="test").id)
- self.assertEqual(select.first_selected_option.get_attribute('value'), next_box_id)
+ self.assertEqual(
+ select.first_selected_option.get_attribute("value"), next_box_id
+ )
def test_related_popup_incorrect_close(self):
"""
Cleanup child popups when closing a parent popup.
"""
from selenium.webdriver.common.by import By
- self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
- add_url = reverse('admin:admin_views_box_add', current_app=site.name)
+
+ self.admin_login(
+ username="super", password="secret", login_url=reverse("admin:index")
+ )
+ add_url = reverse("admin:admin_views_box_add", current_app=site.name)
self.selenium.get(self.live_server_url + add_url)
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup()
test_window = self.selenium.current_window_handle
- self.selenium.find_element(By.ID, 'id_title').send_keys('test')
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "id_title").send_keys("test")
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup(num_windows=3)
test2_window = self.selenium.current_window_handle
- self.selenium.find_element(By.ID, 'id_title').send_keys('test2')
- self.selenium.find_element(By.ID, 'add_id_next_box').click()
+ self.selenium.find_element(By.ID, "id_title").send_keys("test2")
+ self.selenium.find_element(By.ID, "add_id_next_box").click()
self.wait_for_and_switch_to_popup(num_windows=4)
self.assertEqual(len(self.selenium.window_handles), 4)
@@ -5164,12 +6142,12 @@ class SeleniumTests(AdminSeleniumTestCase):
from selenium.webdriver.common.by import By
self.admin_login(
- username='super',
- password='secret',
- login_url=reverse('admin:index'),
+ username="super",
+ password="secret",
+ login_url=reverse("admin:index"),
)
- self.selenium.get(self.live_server_url + reverse('admin:admin_views_story_add'))
- field_title = self.selenium.find_element(By.CLASS_NAME, 'field-title')
+ self.selenium.get(self.live_server_url + reverse("admin:admin_views_story_add"))
+ field_title = self.selenium.find_element(By.CLASS_NAME, "field-title")
current_size = self.selenium.get_window_size()
try:
self.selenium.set_window_size(1024, 768)
@@ -5177,21 +6155,22 @@ class SeleniumTests(AdminSeleniumTestCase):
self.selenium.set_window_size(767, 575)
self.assertIs(field_title.is_displayed(), False)
finally:
- self.selenium.set_window_size(current_size['width'], current_size['height'])
+ self.selenium.set_window_size(current_size["width"], current_size["height"])
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_readonly_get(self):
- response = self.client.get(reverse('admin:admin_views_post_add'))
+ response = self.client.get(reverse("admin:admin_views_post_add"))
self.assertNotContains(response, 'name="posted"')
# 3 fields + 2 submit buttons + 5 inline management form fields, + 2
# hidden fields for inlines + 1 field for the inline + 2 empty form
@@ -5203,11 +6182,18 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
self.assertContains(response, "foo")
# Multiline text in a readonly field gets <br> tags
- self.assertContains(response, 'Multiline<br>test<br>string')
- self.assertContains(response, '<div class="readonly">Multiline<br>html<br>content</div>', html=True)
- self.assertContains(response, 'InlineMultiline<br>test<br>string')
+ self.assertContains(response, "Multiline<br>test<br>string")
+ self.assertContains(
+ response,
+ '<div class="readonly">Multiline<br>html<br>content</div>',
+ html=True,
+ )
+ self.assertContains(response, "InlineMultiline<br>test<br>string")
- self.assertContains(response, formats.localize(datetime.date.today() - datetime.timedelta(days=7)))
+ self.assertContains(
+ response,
+ formats.localize(datetime.date.today() - datetime.timedelta(days=7)),
+ )
self.assertContains(response, '<div class="form-row field-coolness">')
self.assertContains(response, '<div class="form-row field-awesomeness_level">')
@@ -5218,37 +6204,45 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
self.assertContains(
response,
'<div class="help">Some help text for the title (with Unicode ŠĐĆŽćžšđ)</div>',
- html=True
+ html=True,
)
self.assertContains(
response,
'<div class="help">Some help text for the content (with Unicode ŠĐĆŽćžšđ)</div>',
- html=True
+ html=True,
)
self.assertContains(
response,
'<div class="help">Some help text for the date (with Unicode ŠĐĆŽćžšđ)</div>',
- html=True
+ html=True,
)
- p = Post.objects.create(title="I worked on readonly_fields", content="Its good stuff")
- response = self.client.get(reverse('admin:admin_views_post_change', args=(p.pk,)))
+ p = Post.objects.create(
+ title="I worked on readonly_fields", content="Its good stuff"
+ )
+ response = self.client.get(
+ reverse("admin:admin_views_post_change", args=(p.pk,))
+ )
self.assertContains(response, "%d amount of cool" % p.pk)
def test_readonly_text_field(self):
p = Post.objects.create(
- title="Readonly test", content="test",
- readonly_content='test\r\n\r\ntest\r\n\r\ntest\r\n\r\ntest',
+ title="Readonly test",
+ content="test",
+ readonly_content="test\r\n\r\ntest\r\n\r\ntest\r\n\r\ntest",
)
Link.objects.create(
- url="http://www.djangoproject.com", post=p,
+ url="http://www.djangoproject.com",
+ post=p,
readonly_link_content="test\r\nlink",
)
- response = self.client.get(reverse('admin:admin_views_post_change', args=(p.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_post_change", args=(p.pk,))
+ )
# Checking readonly field.
- self.assertContains(response, 'test<br><br>test<br><br>test<br><br>test')
+ self.assertContains(response, "test<br><br>test<br><br>test<br><br>test")
# Checking readonly field in inline.
- self.assertContains(response, 'test<br>link')
+ self.assertContains(response, "test<br>link")
def test_readonly_post(self):
data = {
@@ -5258,27 +6252,29 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
"link_set-INITIAL_FORMS": "0",
"link_set-MAX_NUM_FORMS": "0",
}
- response = self.client.post(reverse('admin:admin_views_post_add'), data)
+ response = self.client.post(reverse("admin:admin_views_post_add"), data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Post.objects.count(), 1)
p = Post.objects.get()
self.assertEqual(p.posted, datetime.date.today())
data["posted"] = "10-8-1990" # some date that's not today
- response = self.client.post(reverse('admin:admin_views_post_add'), data)
+ response = self.client.post(reverse("admin:admin_views_post_add"), data)
self.assertEqual(response.status_code, 302)
self.assertEqual(Post.objects.count(), 2)
- p = Post.objects.order_by('-id')[0]
+ p = Post.objects.order_by("-id")[0]
self.assertEqual(p.posted, datetime.date.today())
def test_readonly_manytomany(self):
"Regression test for #13004"
- response = self.client.get(reverse('admin:admin_views_pizza_add'))
+ response = self.client.get(reverse("admin:admin_views_pizza_add"))
self.assertEqual(response.status_code, 200)
def test_user_password_change_limited_queryset(self):
su = User.objects.filter(is_superuser=True)[0]
- response = self.client.get(reverse('admin2:auth_user_password_change', args=(su.pk,)))
+ response = self.client.get(
+ reverse("admin2:auth_user_password_change", args=(su.pk,))
+ )
self.assertEqual(response.status_code, 404)
def test_change_form_renders_correct_null_choice_value(self):
@@ -5286,8 +6282,12 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
Regression test for #17911.
"""
choice = Choice.objects.create(choice=None)
- response = self.client.get(reverse('admin:admin_views_choice_change', args=(choice.pk,)))
- self.assertContains(response, '<div class="readonly">No opinion</div>', html=True)
+ response = self.client.get(
+ reverse("admin:admin_views_choice_change", args=(choice.pk,))
+ )
+ self.assertContains(
+ response, '<div class="readonly">No opinion</div>', html=True
+ )
def _test_readonly_foreignkey_links(self, admin_site):
"""
@@ -5295,21 +6295,23 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
registered in admin.
"""
chapter = Chapter.objects.create(
- title='Chapter 1',
- content='content',
- book=Book.objects.create(name='Book 1'),
+ title="Chapter 1",
+ content="content",
+ book=Book.objects.create(name="Book 1"),
)
- language = Language.objects.create(iso='_40', name='Test')
+ language = Language.objects.create(iso="_40", name="Test")
obj = ReadOnlyRelatedField.objects.create(
chapter=chapter,
language=language,
user=self.superuser,
)
response = self.client.get(
- reverse(f'{admin_site}:admin_views_readonlyrelatedfield_change', args=(obj.pk,)),
+ reverse(
+ f"{admin_site}:admin_views_readonlyrelatedfield_change", args=(obj.pk,)
+ ),
)
# Related ForeignKey object registered in admin.
- user_url = reverse(f'{admin_site}:auth_user_change', args=(self.superuser.pk,))
+ user_url = reverse(f"{admin_site}:auth_user_change", args=(self.superuser.pk,))
self.assertContains(
response,
'<div class="readonly"><a href="%s">super</a></div>' % user_url,
@@ -5317,7 +6319,7 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
)
# Related ForeignKey with the string primary key registered in admin.
language_url = reverse(
- f'{admin_site}:admin_views_language_change',
+ f"{admin_site}:admin_views_language_change",
args=(quote(language.pk),),
)
self.assertContains(
@@ -5326,53 +6328,61 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
html=True,
)
# Related ForeignKey object not registered in admin.
- self.assertContains(response, '<div class="readonly">Chapter 1</div>', html=True)
+ self.assertContains(
+ response, '<div class="readonly">Chapter 1</div>', html=True
+ )
def test_readonly_foreignkey_links_default_admin_site(self):
- self._test_readonly_foreignkey_links('admin')
+ self._test_readonly_foreignkey_links("admin")
def test_readonly_foreignkey_links_custom_admin_site(self):
- self._test_readonly_foreignkey_links('namespaced_admin')
+ self._test_readonly_foreignkey_links("namespaced_admin")
def test_readonly_manytomany_backwards_ref(self):
"""
Regression test for #16433 - backwards references for related objects
broke if the related field is read-only due to the help_text attribute
"""
- topping = Topping.objects.create(name='Salami')
- pizza = Pizza.objects.create(name='Americano')
+ topping = Topping.objects.create(name="Salami")
+ pizza = Pizza.objects.create(name="Americano")
pizza.toppings.add(topping)
- response = self.client.get(reverse('admin:admin_views_topping_add'))
+ response = self.client.get(reverse("admin:admin_views_topping_add"))
self.assertEqual(response.status_code, 200)
def test_readonly_manytomany_forwards_ref(self):
- topping = Topping.objects.create(name='Salami')
- pizza = Pizza.objects.create(name='Americano')
+ topping = Topping.objects.create(name="Salami")
+ pizza = Pizza.objects.create(name="Americano")
pizza.toppings.add(topping)
- response = self.client.get(reverse('admin:admin_views_pizza_change', args=(pizza.pk,)))
- self.assertContains(response, '<label>Toppings:</label>', html=True)
+ response = self.client.get(
+ reverse("admin:admin_views_pizza_change", args=(pizza.pk,))
+ )
+ self.assertContains(response, "<label>Toppings:</label>", html=True)
self.assertContains(response, '<div class="readonly">Salami</div>', html=True)
def test_readonly_onetoone_backwards_ref(self):
"""
Can reference a reverse OneToOneField in ModelAdmin.readonly_fields.
"""
- v1 = Villain.objects.create(name='Adam')
- pl = Plot.objects.create(name='Test Plot', team_leader=v1, contact=v1)
- pd = PlotDetails.objects.create(details='Brand New Plot', plot=pl)
+ v1 = Villain.objects.create(name="Adam")
+ pl = Plot.objects.create(name="Test Plot", team_leader=v1, contact=v1)
+ pd = PlotDetails.objects.create(details="Brand New Plot", plot=pl)
- response = self.client.get(reverse('admin:admin_views_plotproxy_change', args=(pl.pk,)))
- field = self.get_admin_readonly_field(response, 'plotdetails')
- pd_url = reverse('admin:admin_views_plotdetails_change', args=(pd.pk,))
+ response = self.client.get(
+ reverse("admin:admin_views_plotproxy_change", args=(pl.pk,))
+ )
+ field = self.get_admin_readonly_field(response, "plotdetails")
+ pd_url = reverse("admin:admin_views_plotdetails_change", args=(pd.pk,))
self.assertEqual(field.contents(), '<a href="%s">Brand New Plot</a>' % pd_url)
# The reverse relation also works if the OneToOneField is null.
pd.plot = None
pd.save()
- response = self.client.get(reverse('admin:admin_views_plotproxy_change', args=(pl.pk,)))
- field = self.get_admin_readonly_field(response, 'plotdetails')
- self.assertEqual(field.contents(), '-') # default empty value
+ response = self.client.get(
+ reverse("admin:admin_views_plotproxy_change", args=(pl.pk,))
+ )
+ field = self.get_admin_readonly_field(response, "plotdetails")
+ self.assertEqual(field.contents(), "-") # default empty value
def test_readonly_field_overrides(self):
"""
@@ -5380,34 +6390,47 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
AdminReadonlyField
"""
p = FieldOverridePost.objects.create(title="Test Post", content="Test Content")
- response = self.client.get(reverse('admin:admin_views_fieldoverridepost_change', args=(p.pk,)))
- self.assertContains(response, '<div class="help">Overridden help text for the date</div>')
- self.assertContains(response, '<label for="id_public">Overridden public label:</label>', html=True)
- self.assertNotContains(response, 'Some help text for the date (with Unicode ŠĐĆŽćžšđ)')
+ response = self.client.get(
+ reverse("admin:admin_views_fieldoverridepost_change", args=(p.pk,))
+ )
+ self.assertContains(
+ response, '<div class="help">Overridden help text for the date</div>'
+ )
+ self.assertContains(
+ response,
+ '<label for="id_public">Overridden public label:</label>',
+ html=True,
+ )
+ self.assertNotContains(
+ response, "Some help text for the date (with Unicode ŠĐĆŽćžšđ)"
+ )
def test_correct_autoescaping(self):
"""
Make sure that non-field readonly elements are properly autoescaped (#24461)
"""
- section = Section.objects.create(name='<a>evil</a>')
- response = self.client.get(reverse('admin:admin_views_section_change', args=(section.pk,)))
+ section = Section.objects.create(name="<a>evil</a>")
+ response = self.client.get(
+ reverse("admin:admin_views_section_change", args=(section.pk,))
+ )
self.assertNotContains(response, "<a>evil</a>", status_code=200)
self.assertContains(response, "&lt;a&gt;evil&lt;/a&gt;", status_code=200)
def test_label_suffix_translated(self):
- pizza = Pizza.objects.create(name='Americano')
- url = reverse('admin:admin_views_pizza_change', args=(pizza.pk,))
- with self.settings(LANGUAGE_CODE='fr'):
+ pizza = Pizza.objects.create(name="Americano")
+ url = reverse("admin:admin_views_pizza_change", args=(pizza.pk,))
+ with self.settings(LANGUAGE_CODE="fr"):
response = self.client.get(url)
- self.assertContains(response, '<label>Toppings\u00A0:</label>', html=True)
+ self.assertContains(response, "<label>Toppings\u00A0:</label>", html=True)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class LimitChoicesToInAdminTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -5415,25 +6438,26 @@ class LimitChoicesToInAdminTest(TestCase):
def test_limit_choices_to_as_callable(self):
"""Test for ticket 2445 changes to admin."""
threepwood = Character.objects.create(
- username='threepwood',
+ username="threepwood",
last_action=datetime.datetime.today() + datetime.timedelta(days=1),
)
marley = Character.objects.create(
- username='marley',
+ username="marley",
last_action=datetime.datetime.today() - datetime.timedelta(days=1),
)
- response = self.client.get(reverse('admin:admin_views_stumpjoke_add'))
+ response = self.client.get(reverse("admin:admin_views_stumpjoke_add"))
# The allowed option should appear twice; the limited option should not appear.
self.assertContains(response, threepwood.username, count=2)
self.assertNotContains(response, marley.username)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class RawIdFieldsTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -5441,20 +6465,18 @@ class RawIdFieldsTest(TestCase):
def test_limit_choices_to(self):
"""Regression test for 14880"""
actor = Actor.objects.create(name="Palin", age=27)
- Inquisition.objects.create(expected=True,
- leader=actor,
- country="England")
- Inquisition.objects.create(expected=False,
- leader=actor,
- country="Spain")
- response = self.client.get(reverse('admin:admin_views_sketch_add'))
+ Inquisition.objects.create(expected=True, leader=actor, country="England")
+ Inquisition.objects.create(expected=False, leader=actor, country="Spain")
+ response = self.client.get(reverse("admin:admin_views_sketch_add"))
# Find the link
- m = re.search(br'<a href="([^"]*)"[^>]* id="lookup_id_inquisition"', response.content)
+ m = re.search(
+ rb'<a href="([^"]*)"[^>]* id="lookup_id_inquisition"', response.content
+ )
self.assertTrue(m) # Got a match
- popup_url = m[1].decode().replace('&amp;', '&')
+ popup_url = m[1].decode().replace("&amp;", "&")
# Handle relative links
- popup_url = urljoin(response.request['PATH_INFO'], popup_url)
+ popup_url = urljoin(response.request["PATH_INFO"], popup_url)
# Get the popup and verify the correct objects show up in the resulting
# page. This step also tests integers, strings and booleans in the
# lookup query string; in model we define inquisition field to have a
@@ -5470,14 +6492,16 @@ class RawIdFieldsTest(TestCase):
"""Regression test for 20182"""
Actor.objects.create(name="Palin", age=27)
Actor.objects.create(name="Kilbraken", age=50, title="Judge")
- response = self.client.get(reverse('admin:admin_views_sketch_add'))
+ response = self.client.get(reverse("admin:admin_views_sketch_add"))
# Find the link
- m = re.search(br'<a href="([^"]*)"[^>]* id="lookup_id_defendant0"', response.content)
+ m = re.search(
+ rb'<a href="([^"]*)"[^>]* id="lookup_id_defendant0"', response.content
+ )
self.assertTrue(m) # Got a match
- popup_url = m[1].decode().replace('&amp;', '&')
+ popup_url = m[1].decode().replace("&amp;", "&")
# Handle relative links
- popup_url = urljoin(response.request['PATH_INFO'], popup_url)
+ popup_url = urljoin(response.request["PATH_INFO"], popup_url)
# Get the popup and verify the correct objects show up in the resulting
# page. This step tests field__isnull=0 gets parsed correctly from the
# lookup query string; in model we define defendant0 field to have a
@@ -5490,14 +6514,16 @@ class RawIdFieldsTest(TestCase):
"""Regression test for 20182"""
Actor.objects.create(name="Palin", age=27)
Actor.objects.create(name="Kilbraken", age=50, title="Judge")
- response = self.client.get(reverse('admin:admin_views_sketch_add'))
+ response = self.client.get(reverse("admin:admin_views_sketch_add"))
# Find the link
- m = re.search(br'<a href="([^"]*)"[^>]* id="lookup_id_defendant1"', response.content)
+ m = re.search(
+ rb'<a href="([^"]*)"[^>]* id="lookup_id_defendant1"', response.content
+ )
self.assertTrue(m) # Got a match
- popup_url = m[1].decode().replace('&amp;', '&')
+ popup_url = m[1].decode().replace("&amp;", "&")
# Handle relative links
- popup_url = urljoin(response.request['PATH_INFO'], popup_url)
+ popup_url = urljoin(response.request["PATH_INFO"], popup_url)
# Get the popup and verify the correct objects show up in the resulting
# page. This step tests field__isnull=1 gets parsed correctly from the
# lookup query string; in model we define defendant1 field to have a
@@ -5513,11 +6539,11 @@ class RawIdFieldsTest(TestCase):
"""
actor = Actor.objects.create(name="Palin", age=27)
Inquisition.objects.create(expected=True, leader=actor, country="England")
- response = self.client.get(reverse('admin:admin_views_inquisition_changelist'))
- self.assertContains(response, 'list-display-sketch')
+ response = self.client.get(reverse("admin:admin_views_inquisition_changelist"))
+ self.assertContains(response, "list-display-sketch")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class UserAdminTest(TestCase):
"""
Tests user CRUD functionality.
@@ -5525,50 +6551,72 @@ class UserAdminTest(TestCase):
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.adduser = User.objects.create_user(username='adduser', password='secret', is_staff=True)
- cls.changeuser = User.objects.create_user(username='changeuser', password='secret', is_staff=True)
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.adduser = User.objects.create_user(
+ username="adduser", password="secret", is_staff=True
+ )
+ cls.changeuser = User.objects.create_user(
+ username="changeuser", password="secret", is_staff=True
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
- cls.per1 = Person.objects.create(name='John Mauchly', gender=1, alive=True)
- cls.per2 = Person.objects.create(name='Grace Hopper', gender=1, alive=False)
- cls.per3 = Person.objects.create(name='Guido van Rossum', gender=1, alive=True)
+ cls.per1 = Person.objects.create(name="John Mauchly", gender=1, alive=True)
+ cls.per2 = Person.objects.create(name="Grace Hopper", gender=1, alive=False)
+ cls.per3 = Person.objects.create(name="Guido van Rossum", gender=1, alive=True)
def setUp(self):
self.client.force_login(self.superuser)
def test_save_button(self):
user_count = User.objects.count()
- response = self.client.post(reverse('admin:auth_user_add'), {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'newpassword',
- })
- new_user = User.objects.get(username='newuser')
- self.assertRedirects(response, reverse('admin:auth_user_change', args=(new_user.pk,)))
+ response = self.client.post(
+ reverse("admin:auth_user_add"),
+ {
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "newpassword",
+ },
+ )
+ new_user = User.objects.get(username="newuser")
+ self.assertRedirects(
+ response, reverse("admin:auth_user_change", args=(new_user.pk,))
+ )
self.assertEqual(User.objects.count(), user_count + 1)
self.assertTrue(new_user.has_usable_password())
def test_save_continue_editing_button(self):
user_count = User.objects.count()
- response = self.client.post(reverse('admin:auth_user_add'), {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'newpassword',
- '_continue': '1',
- })
- new_user = User.objects.get(username='newuser')
- new_user_url = reverse('admin:auth_user_change', args=(new_user.pk,))
+ response = self.client.post(
+ reverse("admin:auth_user_add"),
+ {
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "newpassword",
+ "_continue": "1",
+ },
+ )
+ new_user = User.objects.get(username="newuser")
+ new_user_url = reverse("admin:auth_user_change", args=(new_user.pk,))
self.assertRedirects(response, new_user_url, fetch_redirect_response=False)
self.assertEqual(User.objects.count(), user_count + 1)
self.assertTrue(new_user.has_usable_password())
@@ -5576,90 +6624,122 @@ class UserAdminTest(TestCase):
self.assertContains(
response,
'<li class="success">The user “<a href="%s">'
- '%s</a>” was added successfully. You may edit it again below.</li>'
+ "%s</a>” was added successfully. You may edit it again below.</li>"
% (new_user_url, new_user),
html=True,
)
def test_password_mismatch(self):
- response = self.client.post(reverse('admin:auth_user_add'), {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'mismatch',
- })
+ response = self.client.post(
+ reverse("admin:auth_user_add"),
+ {
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "mismatch",
+ },
+ )
self.assertEqual(response.status_code, 200)
- self.assertFormError(response, 'adminform', 'password', [])
- self.assertFormError(response, 'adminform', 'password2', ['The two password fields didn’t match.'])
+ self.assertFormError(response, "adminform", "password", [])
+ self.assertFormError(
+ response,
+ "adminform",
+ "password2",
+ ["The two password fields didn’t match."],
+ )
def test_user_fk_add_popup(self):
"""User addition through a FK popup should return the appropriate JavaScript response."""
- response = self.client.get(reverse('admin:admin_views_album_add'))
- self.assertContains(response, reverse('admin:auth_user_add'))
- self.assertContains(response, 'class="related-widget-wrapper-link add-related" id="add_id_owner"')
- response = self.client.get(reverse('admin:auth_user_add') + '?%s=1' % IS_POPUP_VAR)
+ response = self.client.get(reverse("admin:admin_views_album_add"))
+ self.assertContains(response, reverse("admin:auth_user_add"))
+ self.assertContains(
+ response,
+ 'class="related-widget-wrapper-link add-related" id="add_id_owner"',
+ )
+ response = self.client.get(
+ reverse("admin:auth_user_add") + "?%s=1" % IS_POPUP_VAR
+ )
self.assertNotContains(response, 'name="_continue"')
self.assertNotContains(response, 'name="_addanother"')
data = {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'newpassword',
- IS_POPUP_VAR: '1',
- '_save': '1',
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "newpassword",
+ IS_POPUP_VAR: "1",
+ "_save": "1",
}
- response = self.client.post(reverse('admin:auth_user_add') + '?%s=1' % IS_POPUP_VAR, data, follow=True)
- self.assertContains(response, '&quot;obj&quot;: &quot;newuser&quot;')
+ response = self.client.post(
+ reverse("admin:auth_user_add") + "?%s=1" % IS_POPUP_VAR, data, follow=True
+ )
+ self.assertContains(response, "&quot;obj&quot;: &quot;newuser&quot;")
def test_user_fk_change_popup(self):
"""User change through a FK popup should return the appropriate JavaScript response."""
- response = self.client.get(reverse('admin:admin_views_album_add'))
- self.assertContains(response, reverse('admin:auth_user_change', args=('__fk__',)))
- self.assertContains(response, 'class="related-widget-wrapper-link change-related" id="change_id_owner"')
- user = User.objects.get(username='changeuser')
- url = reverse('admin:auth_user_change', args=(user.pk,)) + '?%s=1' % IS_POPUP_VAR
+ response = self.client.get(reverse("admin:admin_views_album_add"))
+ self.assertContains(
+ response, reverse("admin:auth_user_change", args=("__fk__",))
+ )
+ self.assertContains(
+ response,
+ 'class="related-widget-wrapper-link change-related" id="change_id_owner"',
+ )
+ user = User.objects.get(username="changeuser")
+ url = (
+ reverse("admin:auth_user_change", args=(user.pk,)) + "?%s=1" % IS_POPUP_VAR
+ )
response = self.client.get(url)
self.assertNotContains(response, 'name="_continue"')
self.assertNotContains(response, 'name="_addanother"')
data = {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'newpassword',
- 'last_login_0': '2007-05-30',
- 'last_login_1': '13:20:10',
- 'date_joined_0': '2007-05-30',
- 'date_joined_1': '13:20:10',
- IS_POPUP_VAR: '1',
- '_save': '1',
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "newpassword",
+ "last_login_0": "2007-05-30",
+ "last_login_1": "13:20:10",
+ "date_joined_0": "2007-05-30",
+ "date_joined_1": "13:20:10",
+ IS_POPUP_VAR: "1",
+ "_save": "1",
}
response = self.client.post(url, data, follow=True)
- self.assertContains(response, '&quot;obj&quot;: &quot;newuser&quot;')
- self.assertContains(response, '&quot;action&quot;: &quot;change&quot;')
+ self.assertContains(response, "&quot;obj&quot;: &quot;newuser&quot;")
+ self.assertContains(response, "&quot;action&quot;: &quot;change&quot;")
def test_user_fk_delete_popup(self):
"""User deletion through a FK popup should return the appropriate JavaScript response."""
- response = self.client.get(reverse('admin:admin_views_album_add'))
- self.assertContains(response, reverse('admin:auth_user_delete', args=('__fk__',)))
- self.assertContains(response, 'class="related-widget-wrapper-link change-related" id="change_id_owner"')
- user = User.objects.get(username='changeuser')
- url = reverse('admin:auth_user_delete', args=(user.pk,)) + '?%s=1' % IS_POPUP_VAR
+ response = self.client.get(reverse("admin:admin_views_album_add"))
+ self.assertContains(
+ response, reverse("admin:auth_user_delete", args=("__fk__",))
+ )
+ self.assertContains(
+ response,
+ 'class="related-widget-wrapper-link change-related" id="change_id_owner"',
+ )
+ user = User.objects.get(username="changeuser")
+ url = (
+ reverse("admin:auth_user_delete", args=(user.pk,)) + "?%s=1" % IS_POPUP_VAR
+ )
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
data = {
- 'post': 'yes',
- IS_POPUP_VAR: '1',
+ "post": "yes",
+ IS_POPUP_VAR: "1",
}
response = self.client.post(url, data, follow=True)
- self.assertContains(response, '&quot;action&quot;: &quot;delete&quot;')
+ self.assertContains(response, "&quot;action&quot;: &quot;delete&quot;")
def test_save_add_another_button(self):
user_count = User.objects.count()
- response = self.client.post(reverse('admin:auth_user_add'), {
- 'username': 'newuser',
- 'password1': 'newpassword',
- 'password2': 'newpassword',
- '_addanother': '1',
- })
- new_user = User.objects.order_by('-id')[0]
- self.assertRedirects(response, reverse('admin:auth_user_add'))
+ response = self.client.post(
+ reverse("admin:auth_user_add"),
+ {
+ "username": "newuser",
+ "password1": "newpassword",
+ "password2": "newpassword",
+ "_addanother": "1",
+ },
+ )
+ new_user = User.objects.order_by("-id")[0]
+ self.assertRedirects(response, reverse("admin:auth_user_add"))
self.assertEqual(User.objects.count(), user_count + 1)
self.assertTrue(new_user.has_usable_password())
@@ -5670,17 +6750,19 @@ class UserAdminTest(TestCase):
ContentType.objects.clear_cache()
with self.assertNumQueries(10):
- response = self.client.get(reverse('admin:auth_user_change', args=(u.pk,)))
+ response = self.client.get(reverse("admin:auth_user_change", args=(u.pk,)))
self.assertEqual(response.status_code, 200)
def test_form_url_present_in_context(self):
u = User.objects.all()[0]
- response = self.client.get(reverse('admin3:auth_user_password_change', args=(u.pk,)))
+ response = self.client.get(
+ reverse("admin3:auth_user_password_change", args=(u.pk,))
+ )
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context['form_url'], 'pony')
+ self.assertEqual(response.context["form_url"], "pony")
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class GroupAdminTest(TestCase):
"""
Tests group CRUD functionality.
@@ -5688,19 +6770,24 @@ class GroupAdminTest(TestCase):
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_save_button(self):
group_count = Group.objects.count()
- response = self.client.post(reverse('admin:auth_group_add'), {
- 'name': 'newgroup',
- })
+ response = self.client.post(
+ reverse("admin:auth_group_add"),
+ {
+ "name": "newgroup",
+ },
+ )
- Group.objects.order_by('-id')[0]
- self.assertRedirects(response, reverse('admin:auth_group_changelist'))
+ Group.objects.order_by("-id")[0]
+ self.assertRedirects(response, reverse("admin:auth_group_changelist"))
self.assertEqual(Group.objects.count(), group_count + 1)
def test_group_permission_performance(self):
@@ -5710,27 +6797,36 @@ class GroupAdminTest(TestCase):
ContentType.objects.clear_cache()
with self.assertNumQueries(8):
- response = self.client.get(reverse('admin:auth_group_change', args=(g.pk,)))
+ response = self.client.get(reverse("admin:auth_group_change", args=(g.pk,)))
self.assertEqual(response.status_code, 200)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class CSSTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.s1 = Section.objects.create(name='Test section')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.s1 = Section.objects.create(name="Test section")
cls.a1 = Article.objects.create(
- content='<p>Middle content</p>', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Middle content</p>",
+ date=datetime.datetime(2008, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a2 = Article.objects.create(
- content='<p>Oldest content</p>', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Oldest content</p>",
+ date=datetime.datetime(2000, 3, 18, 11, 54, 58),
+ section=cls.s1,
)
cls.a3 = Article.objects.create(
- content='<p>Newest content</p>', date=datetime.datetime(2009, 3, 18, 11, 54, 58), section=cls.s1
+ content="<p>Newest content</p>",
+ date=datetime.datetime(2009, 3, 18, 11, 54, 58),
+ section=cls.s1,
+ )
+ cls.p1 = PrePopulatedPost.objects.create(
+ title="A Long Title", published=True, slug="a-long-title"
)
- cls.p1 = PrePopulatedPost.objects.create(title='A Long Title', published=True, slug='a-long-title')
def setUp(self):
self.client.force_login(self.superuser)
@@ -5739,7 +6835,7 @@ class CSSTest(TestCase):
"""
Fields have a CSS class name with a 'field-' prefix.
"""
- response = self.client.get(reverse('admin:admin_views_post_add'))
+ response = self.client.get(reverse("admin:admin_views_post_add"))
# The main form
self.assertContains(response, 'class="form-row field-title"')
@@ -5760,13 +6856,13 @@ class CSSTest(TestCase):
pages (#17050).
"""
# General index page
- response = self.client.get(reverse('admin:index'))
+ response = self.client.get(reverse("admin:index"))
self.assertContains(response, '<div class="app-admin_views module')
self.assertContains(response, '<tr class="model-actor">')
self.assertContains(response, '<tr class="model-album">')
# App index page
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertContains(response, '<div class="app-admin_views module')
self.assertContains(response, '<tr class="model-actor">')
self.assertContains(response, '<tr class="model-album">')
@@ -5775,14 +6871,14 @@ class CSSTest(TestCase):
"""
Ensure app and model tag are correctly read by change_form template
"""
- response = self.client.get(reverse('admin:admin_views_section_add'))
+ response = self.client.get(reverse("admin:admin_views_section_add"))
self.assertContains(response, '<body class=" app-admin_views model-section ')
def test_app_model_in_list_body_class(self):
"""
Ensure app and model tag are correctly read by change_list template
"""
- response = self.client.get(reverse('admin:admin_views_section_changelist'))
+ response = self.client.get(reverse("admin:admin_views_section_changelist"))
self.assertContains(response, '<body class=" app-admin_views model-section ')
def test_app_model_in_delete_confirmation_body_class(self):
@@ -5790,14 +6886,16 @@ class CSSTest(TestCase):
Ensure app and model tag are correctly read by delete_confirmation
template
"""
- response = self.client.get(reverse('admin:admin_views_section_delete', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_section_delete", args=(self.s1.pk,))
+ )
self.assertContains(response, '<body class=" app-admin_views model-section ')
def test_app_model_in_app_index_body_class(self):
"""
Ensure app and model tag are correctly read by app_index template
"""
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertContains(response, '<body class=" dashboard app-admin_views')
def test_app_model_in_delete_selected_confirmation_body_class(self):
@@ -5807,10 +6905,12 @@ class CSSTest(TestCase):
"""
action_data = {
ACTION_CHECKBOX_NAME: [self.s1.pk],
- 'action': 'delete_selected',
- 'index': 0,
+ "action": "delete_selected",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_section_changelist'), action_data)
+ response = self.client.post(
+ reverse("admin:admin_views_section_changelist"), action_data
+ )
self.assertContains(response, '<body class=" app-admin_views model-section ')
def test_changelist_field_classes(self):
@@ -5819,7 +6919,7 @@ class CSSTest(TestCase):
Refs #11195.
"""
Podcast.objects.create(name="Django Dose", release_date=datetime.date.today())
- response = self.client.get(reverse('admin:admin_views_podcast_changelist'))
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"))
self.assertContains(response, '<th class="field-name">')
self.assertContains(response, '<td class="field-release_date nowrap">')
self.assertContains(response, '<td class="action-checkbox">')
@@ -5832,86 +6932,113 @@ except ImportError:
@unittest.skipUnless(docutils, "no docutils installed.")
-@override_settings(ROOT_URLCONF='admin_views.urls')
-@modify_settings(INSTALLED_APPS={'append': ['django.contrib.admindocs', 'django.contrib.flatpages']})
+@override_settings(ROOT_URLCONF="admin_views.urls")
+@modify_settings(
+ INSTALLED_APPS={"append": ["django.contrib.admindocs", "django.contrib.flatpages"]}
+)
class AdminDocsTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_tags(self):
- response = self.client.get(reverse('django-admindocs-tags'))
+ response = self.client.get(reverse("django-admindocs-tags"))
# The builtin tag group exists
self.assertContains(response, "<h2>Built-in tags</h2>", count=2, html=True)
# A builtin tag exists in both the index and detail
- self.assertContains(response, '<h3 id="built_in-autoescape">autoescape</h3>', html=True)
- self.assertContains(response, '<li><a href="#built_in-autoescape">autoescape</a></li>', html=True)
+ self.assertContains(
+ response, '<h3 id="built_in-autoescape">autoescape</h3>', html=True
+ )
+ self.assertContains(
+ response,
+ '<li><a href="#built_in-autoescape">autoescape</a></li>',
+ html=True,
+ )
# An app tag exists in both the index and detail
- self.assertContains(response, '<h3 id="flatpages-get_flatpages">get_flatpages</h3>', html=True)
- self.assertContains(response, '<li><a href="#flatpages-get_flatpages">get_flatpages</a></li>', html=True)
+ self.assertContains(
+ response, '<h3 id="flatpages-get_flatpages">get_flatpages</h3>', html=True
+ )
+ self.assertContains(
+ response,
+ '<li><a href="#flatpages-get_flatpages">get_flatpages</a></li>',
+ html=True,
+ )
# The admin list tag group exists
self.assertContains(response, "<h2>admin_list</h2>", count=2, html=True)
# An admin list tag exists in both the index and detail
- self.assertContains(response, '<h3 id="admin_list-admin_actions">admin_actions</h3>', html=True)
- self.assertContains(response, '<li><a href="#admin_list-admin_actions">admin_actions</a></li>', html=True)
+ self.assertContains(
+ response, '<h3 id="admin_list-admin_actions">admin_actions</h3>', html=True
+ )
+ self.assertContains(
+ response,
+ '<li><a href="#admin_list-admin_actions">admin_actions</a></li>',
+ html=True,
+ )
def test_filters(self):
- response = self.client.get(reverse('django-admindocs-filters'))
+ response = self.client.get(reverse("django-admindocs-filters"))
# The builtin filter group exists
self.assertContains(response, "<h2>Built-in filters</h2>", count=2, html=True)
# A builtin filter exists in both the index and detail
self.assertContains(response, '<h3 id="built_in-add">add</h3>', html=True)
- self.assertContains(response, '<li><a href="#built_in-add">add</a></li>', html=True)
+ self.assertContains(
+ response, '<li><a href="#built_in-add">add</a></li>', html=True
+ )
@override_settings(
- ROOT_URLCONF='admin_views.urls',
- TEMPLATES=[{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- }],
+ ROOT_URLCONF="admin_views.urls",
+ TEMPLATES=[
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ }
+ ],
)
class ValidXHTMLTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_lang_name_present(self):
with translation.override(None):
- response = self.client.get(reverse('admin:app_list', args=('admin_views',)))
+ response = self.client.get(reverse("admin:app_list", args=("admin_views",)))
self.assertNotContains(response, ' lang=""')
self.assertNotContains(response, ' xml:lang=""')
-@override_settings(ROOT_URLCONF='admin_views.urls', USE_THOUSAND_SEPARATOR=True)
+@override_settings(ROOT_URLCONF="admin_views.urls", USE_THOUSAND_SEPARATOR=True)
class DateHierarchyTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -5927,24 +7054,27 @@ class DateHierarchyTests(TestCase):
def assert_contains_month_link(self, response, date):
self.assertContains(
- response, '?release_date__month=%d&amp;release_date__year=%d"' % (
- date.month, date.year))
+ response,
+ '?release_date__month=%d&amp;release_date__year=%d"'
+ % (date.month, date.year),
+ )
def assert_contains_day_link(self, response, date):
self.assertContains(
- response, '?release_date__day=%d&amp;'
- 'release_date__month=%d&amp;release_date__year=%d"' % (
- date.day, date.month, date.year))
+ response,
+ "?release_date__day=%d&amp;"
+ 'release_date__month=%d&amp;release_date__year=%d"'
+ % (date.day, date.month, date.year),
+ )
def test_empty(self):
"""
No date hierarchy links display with empty changelist.
"""
- response = self.client.get(
- reverse('admin:admin_views_podcast_changelist'))
- self.assertNotContains(response, 'release_date__year=')
- self.assertNotContains(response, 'release_date__month=')
- self.assertNotContains(response, 'release_date__day=')
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"))
+ self.assertNotContains(response, "release_date__year=")
+ self.assertNotContains(response, "release_date__month=")
+ self.assertNotContains(response, "release_date__day=")
def test_single(self):
"""
@@ -5952,7 +7082,7 @@ class DateHierarchyTests(TestCase):
"""
DATE = datetime.date(2000, 6, 30)
Podcast.objects.create(release_date=DATE)
- url = reverse('admin:admin_views_podcast_changelist')
+ url = reverse("admin:admin_views_podcast_changelist")
response = self.client.get(url)
self.assert_contains_day_link(response, DATE)
self.assert_non_localized_year(response, 2000)
@@ -5961,12 +7091,14 @@ class DateHierarchyTests(TestCase):
"""
day-level links appear for changelist within single month.
"""
- DATES = (datetime.date(2000, 6, 30),
- datetime.date(2000, 6, 15),
- datetime.date(2000, 6, 3))
+ DATES = (
+ datetime.date(2000, 6, 30),
+ datetime.date(2000, 6, 15),
+ datetime.date(2000, 6, 3),
+ )
for date in DATES:
Podcast.objects.create(release_date=date)
- url = reverse('admin:admin_views_podcast_changelist')
+ url = reverse("admin:admin_views_podcast_changelist")
response = self.client.get(url)
for date in DATES:
self.assert_contains_day_link(response, date)
@@ -5976,15 +7108,17 @@ class DateHierarchyTests(TestCase):
"""
month-level links appear for changelist within single year.
"""
- DATES = (datetime.date(2000, 1, 30),
- datetime.date(2000, 3, 15),
- datetime.date(2000, 5, 3))
+ DATES = (
+ datetime.date(2000, 1, 30),
+ datetime.date(2000, 3, 15),
+ datetime.date(2000, 5, 3),
+ )
for date in DATES:
Podcast.objects.create(release_date=date)
- url = reverse('admin:admin_views_podcast_changelist')
+ url = reverse("admin:admin_views_podcast_changelist")
response = self.client.get(url)
# no day-level links
- self.assertNotContains(response, 'release_date__day=')
+ self.assertNotContains(response, "release_date__day=")
for date in DATES:
self.assert_contains_month_link(response, date)
self.assert_non_localized_year(response, 2000)
@@ -5993,33 +7127,37 @@ class DateHierarchyTests(TestCase):
"""
year-level links appear for year-spanning changelist.
"""
- DATES = (datetime.date(2001, 1, 30),
- datetime.date(2003, 3, 15),
- datetime.date(2005, 5, 3))
+ DATES = (
+ datetime.date(2001, 1, 30),
+ datetime.date(2003, 3, 15),
+ datetime.date(2005, 5, 3),
+ )
for date in DATES:
Podcast.objects.create(release_date=date)
- response = self.client.get(
- reverse('admin:admin_views_podcast_changelist'))
+ response = self.client.get(reverse("admin:admin_views_podcast_changelist"))
# no day/month-level links
- self.assertNotContains(response, 'release_date__day=')
- self.assertNotContains(response, 'release_date__month=')
+ self.assertNotContains(response, "release_date__day=")
+ self.assertNotContains(response, "release_date__month=")
for date in DATES:
self.assert_contains_year_link(response, date)
# and make sure GET parameters still behave correctly
for date in DATES:
- url = '%s?release_date__year=%d' % (
- reverse('admin:admin_views_podcast_changelist'),
- date.year)
+ url = "%s?release_date__year=%d" % (
+ reverse("admin:admin_views_podcast_changelist"),
+ date.year,
+ )
response = self.client.get(url)
self.assert_contains_month_link(response, date)
self.assert_non_localized_year(response, 2000)
self.assert_non_localized_year(response, 2003)
self.assert_non_localized_year(response, 2005)
- url = '%s?release_date__year=%d&release_date__month=%d' % (
- reverse('admin:admin_views_podcast_changelist'),
- date.year, date.month)
+ url = "%s?release_date__year=%d&release_date__month=%d" % (
+ reverse("admin:admin_views_podcast_changelist"),
+ date.year,
+ date.month,
+ )
response = self.client.get(url)
self.assert_contains_day_link(response, date)
self.assert_non_localized_year(response, 2000)
@@ -6038,7 +7176,7 @@ class DateHierarchyTests(TestCase):
for i in range(answer_count):
question.answer_set.create()
- response = self.client.get(reverse('admin:admin_views_answer_changelist'))
+ response = self.client.get(reverse("admin:admin_views_answer_changelist"))
for date, answer_count in questions_data:
link = '?question__posted__year=%d"' % date.year
if answer_count > 0:
@@ -6047,7 +7185,7 @@ class DateHierarchyTests(TestCase):
self.assertNotContains(response, link)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminCustomSaveRelatedTests(TestCase):
"""
One can easily customize the way related objects are saved.
@@ -6056,104 +7194,120 @@ class AdminCustomSaveRelatedTests(TestCase):
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_should_be_able_to_edit_related_objects_on_add_view(self):
post = {
- 'child_set-TOTAL_FORMS': '3',
- 'child_set-INITIAL_FORMS': '0',
- 'name': 'Josh Stone',
- 'child_set-0-name': 'Paul',
- 'child_set-1-name': 'Catherine',
+ "child_set-TOTAL_FORMS": "3",
+ "child_set-INITIAL_FORMS": "0",
+ "name": "Josh Stone",
+ "child_set-0-name": "Paul",
+ "child_set-1-name": "Catherine",
}
- self.client.post(reverse('admin:admin_views_parent_add'), post)
+ self.client.post(reverse("admin:admin_views_parent_add"), post)
self.assertEqual(1, Parent.objects.count())
self.assertEqual(2, Child.objects.count())
- children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
+ children_names = list(
+ Child.objects.order_by("name").values_list("name", flat=True)
+ )
- self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
- self.assertEqual(['Catherine Stone', 'Paul Stone'], children_names)
+ self.assertEqual("Josh Stone", Parent.objects.latest("id").name)
+ self.assertEqual(["Catherine Stone", "Paul Stone"], children_names)
def test_should_be_able_to_edit_related_objects_on_change_view(self):
- parent = Parent.objects.create(name='Josh Stone')
- paul = Child.objects.create(parent=parent, name='Paul')
- catherine = Child.objects.create(parent=parent, name='Catherine')
+ parent = Parent.objects.create(name="Josh Stone")
+ paul = Child.objects.create(parent=parent, name="Paul")
+ catherine = Child.objects.create(parent=parent, name="Catherine")
post = {
- 'child_set-TOTAL_FORMS': '5',
- 'child_set-INITIAL_FORMS': '2',
- 'name': 'Josh Stone',
- 'child_set-0-name': 'Paul',
- 'child_set-0-id': paul.id,
- 'child_set-1-name': 'Catherine',
- 'child_set-1-id': catherine.id,
+ "child_set-TOTAL_FORMS": "5",
+ "child_set-INITIAL_FORMS": "2",
+ "name": "Josh Stone",
+ "child_set-0-name": "Paul",
+ "child_set-0-id": paul.id,
+ "child_set-1-name": "Catherine",
+ "child_set-1-id": catherine.id,
}
- self.client.post(reverse('admin:admin_views_parent_change', args=(parent.id,)), post)
+ self.client.post(
+ reverse("admin:admin_views_parent_change", args=(parent.id,)), post
+ )
- children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
+ children_names = list(
+ Child.objects.order_by("name").values_list("name", flat=True)
+ )
- self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
- self.assertEqual(['Catherine Stone', 'Paul Stone'], children_names)
+ self.assertEqual("Josh Stone", Parent.objects.latest("id").name)
+ self.assertEqual(["Catherine Stone", "Paul Stone"], children_names)
def test_should_be_able_to_edit_related_objects_on_changelist_view(self):
- parent = Parent.objects.create(name='Josh Rock')
- Child.objects.create(parent=parent, name='Paul')
- Child.objects.create(parent=parent, name='Catherine')
+ parent = Parent.objects.create(name="Josh Rock")
+ Child.objects.create(parent=parent, name="Paul")
+ Child.objects.create(parent=parent, name="Catherine")
post = {
- 'form-TOTAL_FORMS': '1',
- 'form-INITIAL_FORMS': '1',
- 'form-MAX_NUM_FORMS': '0',
- 'form-0-id': parent.id,
- 'form-0-name': 'Josh Stone',
- '_save': 'Save'
+ "form-TOTAL_FORMS": "1",
+ "form-INITIAL_FORMS": "1",
+ "form-MAX_NUM_FORMS": "0",
+ "form-0-id": parent.id,
+ "form-0-name": "Josh Stone",
+ "_save": "Save",
}
- self.client.post(reverse('admin:admin_views_parent_changelist'), post)
- children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
+ self.client.post(reverse("admin:admin_views_parent_changelist"), post)
+ children_names = list(
+ Child.objects.order_by("name").values_list("name", flat=True)
+ )
- self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
- self.assertEqual(['Catherine Stone', 'Paul Stone'], children_names)
+ self.assertEqual("Josh Stone", Parent.objects.latest("id").name)
+ self.assertEqual(["Catherine Stone", "Paul Stone"], children_names)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewLogoutTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def test_logout(self):
self.client.force_login(self.superuser)
- response = self.client.get(reverse('admin:logout'))
+ response = self.client.get(reverse("admin:logout"))
self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, 'registration/logged_out.html')
- self.assertEqual(response.request['PATH_INFO'], reverse('admin:logout'))
- self.assertFalse(response.context['has_permission'])
- self.assertNotContains(response, 'user-tools') # user-tools div shouldn't visible.
+ self.assertTemplateUsed(response, "registration/logged_out.html")
+ self.assertEqual(response.request["PATH_INFO"], reverse("admin:logout"))
+ self.assertFalse(response.context["has_permission"])
+ self.assertNotContains(
+ response, "user-tools"
+ ) # user-tools div shouldn't visible.
def test_client_logout_url_can_be_used_to_login(self):
- response = self.client.get(reverse('admin:logout'))
- self.assertEqual(response.status_code, 302) # we should be redirected to the login page.
+ response = self.client.get(reverse("admin:logout"))
+ self.assertEqual(
+ response.status_code, 302
+ ) # we should be redirected to the login page.
# follow the redirect and test results.
- response = self.client.get(reverse('admin:logout'), follow=True)
+ response = self.client.get(reverse("admin:logout"), follow=True)
self.assertContains(
response,
- '<input type="hidden" name="next" value="%s">' % reverse('admin:index'),
+ '<input type="hidden" name="next" value="%s">' % reverse("admin:index"),
)
- self.assertTemplateUsed(response, 'admin/login.html')
- self.assertEqual(response.request['PATH_INFO'], reverse('admin:login'))
+ self.assertTemplateUsed(response, "admin/login.html")
+ self.assertEqual(response.request["PATH_INFO"], reverse("admin:login"))
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminUserMessageTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
@@ -6165,59 +7319,69 @@ class AdminUserMessageTest(TestCase):
"""
action_data = {
ACTION_CHECKBOX_NAME: [1],
- 'action': 'message_%s' % level,
- 'index': 0,
+ "action": "message_%s" % level,
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_usermessenger_changelist'),
- action_data, follow=True)
- self.assertContains(response,
- '<li class="%s">Test %s</li>' % (level, level),
- html=True)
+ response = self.client.post(
+ reverse("admin:admin_views_usermessenger_changelist"),
+ action_data,
+ follow=True,
+ )
+ self.assertContains(
+ response, '<li class="%s">Test %s</li>' % (level, level), html=True
+ )
@override_settings(MESSAGE_LEVEL=10) # Set to DEBUG for this request
def test_message_debug(self):
- self.send_message('debug')
+ self.send_message("debug")
def test_message_info(self):
- self.send_message('info')
+ self.send_message("info")
def test_message_success(self):
- self.send_message('success')
+ self.send_message("success")
def test_message_warning(self):
- self.send_message('warning')
+ self.send_message("warning")
def test_message_error(self):
- self.send_message('error')
+ self.send_message("error")
def test_message_extra_tags(self):
action_data = {
ACTION_CHECKBOX_NAME: [1],
- 'action': 'message_extra_tags',
- 'index': 0,
+ "action": "message_extra_tags",
+ "index": 0,
}
- response = self.client.post(reverse('admin:admin_views_usermessenger_changelist'),
- action_data, follow=True)
- self.assertContains(response,
- '<li class="extra_tag info">Test tags</li>',
- html=True)
+ response = self.client.post(
+ reverse("admin:admin_views_usermessenger_changelist"),
+ action_data,
+ follow=True,
+ )
+ self.assertContains(
+ response, '<li class="extra_tag info">Test tags</li>', html=True
+ )
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminKeepChangeListFiltersTests(TestCase):
admin_site = site
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
- cls.joepublicuser = User.objects.create_user(username='joepublic', password='secret')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+ cls.joepublicuser = User.objects.create_user(
+ username="joepublic", password="secret"
+ )
def setUp(self):
self.client.force_login(self.superuser)
- def assertURLEqual(self, url1, url2, msg_prefix=''):
+ def assertURLEqual(self, url1, url2, msg_prefix=""):
"""
Assert that two URLs are equal despite the ordering
of their querystring. Refs #22360.
@@ -6231,101 +7395,117 @@ class AdminKeepChangeListFiltersTests(TestCase):
parsed_qs2 = dict(parse_qsl(parsed_url2.query))
for parsed_qs in [parsed_qs1, parsed_qs2]:
- if '_changelist_filters' in parsed_qs:
- changelist_filters = parsed_qs['_changelist_filters']
+ if "_changelist_filters" in parsed_qs:
+ changelist_filters = parsed_qs["_changelist_filters"]
parsed_filters = dict(parse_qsl(changelist_filters))
- parsed_qs['_changelist_filters'] = parsed_filters
+ parsed_qs["_changelist_filters"] = parsed_filters
self.assertEqual(path1, path2)
self.assertEqual(parsed_qs1, parsed_qs2)
def test_assert_url_equal(self):
# Test equality.
- change_user_url = reverse('admin:auth_user_change', args=(self.joepublicuser.pk,))
+ change_user_url = reverse(
+ "admin:auth_user_change", args=(self.joepublicuser.pk,)
+ )
self.assertURLEqual(
- 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(
+ "http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
change_user_url
),
- 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(
+ "http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
change_user_url
- )
+ ),
)
# Test inequality.
with self.assertRaises(AssertionError):
self.assertURLEqual(
- 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(
+ "http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
change_user_url
),
- 'http://testserver{}?_changelist_filters=is_staff__exact%3D1%26is_superuser__exact%3D1'.format(
+ "http://testserver{}?_changelist_filters=is_staff__exact%3D1%26is_superuser__exact%3D1".format(
change_user_url
- )
+ ),
)
# Ignore scheme and host.
self.assertURLEqual(
- 'http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(
+ "http://testserver{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
+ change_user_url
+ ),
+ "{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
change_user_url
),
- '{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url)
)
# Ignore ordering of querystring.
self.assertURLEqual(
- '{}?is_staff__exact=0&is_superuser__exact=0'.format(reverse('admin:auth_user_changelist')),
- '{}?is_superuser__exact=0&is_staff__exact=0'.format(reverse('admin:auth_user_changelist'))
+ "{}?is_staff__exact=0&is_superuser__exact=0".format(
+ reverse("admin:auth_user_changelist")
+ ),
+ "{}?is_superuser__exact=0&is_staff__exact=0".format(
+ reverse("admin:auth_user_changelist")
+ ),
)
# Ignore ordering of _changelist_filters.
self.assertURLEqual(
- '{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0'.format(change_user_url),
- '{}?_changelist_filters=is_superuser__exact%3D0%26is_staff__exact%3D0'.format(change_user_url)
+ "{}?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0".format(
+ change_user_url
+ ),
+ "{}?_changelist_filters=is_superuser__exact%3D0%26is_staff__exact%3D0".format(
+ change_user_url
+ ),
)
def get_changelist_filters(self):
return {
- 'is_superuser__exact': 0,
- 'is_staff__exact': 0,
+ "is_superuser__exact": 0,
+ "is_staff__exact": 0,
}
def get_changelist_filters_querystring(self):
return urlencode(self.get_changelist_filters())
def get_preserved_filters_querystring(self):
- return urlencode({
- '_changelist_filters': self.get_changelist_filters_querystring()
- })
+ return urlencode(
+ {"_changelist_filters": self.get_changelist_filters_querystring()}
+ )
def get_sample_user_id(self):
return self.joepublicuser.pk
def get_changelist_url(self):
- return '%s?%s' % (
- reverse('admin:auth_user_changelist',
- current_app=self.admin_site.name),
+ return "%s?%s" % (
+ reverse("admin:auth_user_changelist", current_app=self.admin_site.name),
self.get_changelist_filters_querystring(),
)
def get_add_url(self, add_preserved_filters=True):
- url = reverse('admin:auth_user_add', current_app=self.admin_site.name)
+ url = reverse("admin:auth_user_add", current_app=self.admin_site.name)
if add_preserved_filters:
- url = '%s?%s' % (url, self.get_preserved_filters_querystring())
+ url = "%s?%s" % (url, self.get_preserved_filters_querystring())
return url
def get_change_url(self, user_id=None, add_preserved_filters=True):
if user_id is None:
user_id = self.get_sample_user_id()
- url = reverse('admin:auth_user_change', args=(user_id,), current_app=self.admin_site.name)
+ url = reverse(
+ "admin:auth_user_change", args=(user_id,), current_app=self.admin_site.name
+ )
if add_preserved_filters:
- url = '%s?%s' % (url, self.get_preserved_filters_querystring())
+ url = "%s?%s" % (url, self.get_preserved_filters_querystring())
return url
def get_history_url(self, user_id=None):
if user_id is None:
user_id = self.get_sample_user_id()
return "%s?%s" % (
- reverse('admin:auth_user_history', args=(user_id,),
- current_app=self.admin_site.name),
+ reverse(
+ "admin:auth_user_history",
+ args=(user_id,),
+ current_app=self.admin_site.name,
+ ),
self.get_preserved_filters_querystring(),
)
@@ -6333,8 +7513,11 @@ class AdminKeepChangeListFiltersTests(TestCase):
if user_id is None:
user_id = self.get_sample_user_id()
return "%s?%s" % (
- reverse('admin:auth_user_delete', args=(user_id,),
- current_app=self.admin_site.name),
+ reverse(
+ "admin:auth_user_delete",
+ args=(user_id,),
+ current_app=self.admin_site.name,
+ ),
self.get_preserved_filters_querystring(),
)
@@ -6345,7 +7528,7 @@ class AdminKeepChangeListFiltersTests(TestCase):
# Check the `change_view` link has the correct querystring.
detail_link = re.search(
'<a href="(.*?)">{}</a>'.format(self.joepublicuser.username),
- response.content.decode()
+ response.content.decode(),
)
self.assertURLEqual(detail_link[1], self.get_change_url())
@@ -6357,49 +7540,49 @@ class AdminKeepChangeListFiltersTests(TestCase):
# Check the form action.
form_action = re.search(
'<form action="(.*?)" method="post" id="user_form" novalidate>',
- response.content.decode()
+ response.content.decode(),
+ )
+ self.assertURLEqual(
+ form_action[1], "?%s" % self.get_preserved_filters_querystring()
)
- self.assertURLEqual(form_action[1], '?%s' % self.get_preserved_filters_querystring())
# Check the history link.
history_link = re.search(
- '<a href="(.*?)" class="historylink">History</a>',
- response.content.decode()
+ '<a href="(.*?)" class="historylink">History</a>', response.content.decode()
)
self.assertURLEqual(history_link[1], self.get_history_url())
# Check the delete link.
delete_link = re.search(
- '<a href="(.*?)" class="deletelink">Delete</a>',
- response.content.decode()
+ '<a href="(.*?)" class="deletelink">Delete</a>', response.content.decode()
)
self.assertURLEqual(delete_link[1], self.get_delete_url())
# Test redirect on "Save".
post_data = {
- 'username': 'joepublic',
- 'last_login_0': '2007-05-30',
- 'last_login_1': '13:20:10',
- 'date_joined_0': '2007-05-30',
- 'date_joined_1': '13:20:10',
+ "username": "joepublic",
+ "last_login_0": "2007-05-30",
+ "last_login_1": "13:20:10",
+ "date_joined_0": "2007-05-30",
+ "date_joined_1": "13:20:10",
}
- post_data['_save'] = 1
+ post_data["_save"] = 1
response = self.client.post(self.get_change_url(), data=post_data)
self.assertRedirects(response, self.get_changelist_url())
- post_data.pop('_save')
+ post_data.pop("_save")
# Test redirect on "Save and continue".
- post_data['_continue'] = 1
+ post_data["_continue"] = 1
response = self.client.post(self.get_change_url(), data=post_data)
self.assertRedirects(response, self.get_change_url())
- post_data.pop('_continue')
+ post_data.pop("_continue")
# Test redirect on "Save and add new".
- post_data['_addanother'] = 1
+ post_data["_addanother"] = 1
response = self.client.post(self.get_change_url(), data=post_data)
self.assertRedirects(response, self.get_add_url())
- post_data.pop('_addanother')
+ post_data.pop("_addanother")
def test_change_view_without_preserved_filters(self):
response = self.client.get(self.get_change_url(add_preserved_filters=False))
@@ -6414,35 +7597,41 @@ class AdminKeepChangeListFiltersTests(TestCase):
# Check the form action.
form_action = re.search(
'<form action="(.*?)" method="post" id="user_form" novalidate>',
- response.content.decode()
+ response.content.decode(),
+ )
+ self.assertURLEqual(
+ form_action[1], "?%s" % self.get_preserved_filters_querystring()
)
- self.assertURLEqual(form_action[1], '?%s' % self.get_preserved_filters_querystring())
post_data = {
- 'username': 'dummy',
- 'password1': 'test',
- 'password2': 'test',
+ "username": "dummy",
+ "password1": "test",
+ "password2": "test",
}
# Test redirect on "Save".
- post_data['_save'] = 1
+ post_data["_save"] = 1
response = self.client.post(self.get_add_url(), data=post_data)
- self.assertRedirects(response, self.get_change_url(User.objects.get(username='dummy').pk))
- post_data.pop('_save')
+ self.assertRedirects(
+ response, self.get_change_url(User.objects.get(username="dummy").pk)
+ )
+ post_data.pop("_save")
# Test redirect on "Save and continue".
- post_data['username'] = 'dummy2'
- post_data['_continue'] = 1
+ post_data["username"] = "dummy2"
+ post_data["_continue"] = 1
response = self.client.post(self.get_add_url(), data=post_data)
- self.assertRedirects(response, self.get_change_url(User.objects.get(username='dummy2').pk))
- post_data.pop('_continue')
+ self.assertRedirects(
+ response, self.get_change_url(User.objects.get(username="dummy2").pk)
+ )
+ post_data.pop("_continue")
# Test redirect on "Save and add new".
- post_data['username'] = 'dummy3'
- post_data['_addanother'] = 1
+ post_data["username"] = "dummy3"
+ post_data["_addanother"] = 1
response = self.client.post(self.get_add_url(), data=post_data)
self.assertRedirects(response, self.get_add_url())
- post_data.pop('_addanother')
+ post_data.pop("_addanother")
def test_add_view_without_preserved_filters(self):
response = self.client.get(self.get_add_url(add_preserved_filters=False))
@@ -6451,18 +7640,20 @@ class AdminKeepChangeListFiltersTests(TestCase):
def test_delete_view(self):
# Test redirect on "Delete".
- response = self.client.post(self.get_delete_url(), {'post': 'yes'})
+ response = self.client.post(self.get_delete_url(), {"post": "yes"})
self.assertRedirects(response, self.get_changelist_url())
def test_url_prefix(self):
context = {
- 'preserved_filters': self.get_preserved_filters_querystring(),
- 'opts': User._meta,
+ "preserved_filters": self.get_preserved_filters_querystring(),
+ "opts": User._meta,
}
- prefixes = ('', '/prefix/', '/後台/')
+ prefixes = ("", "/prefix/", "/後台/")
for prefix in prefixes:
with self.subTest(prefix=prefix), override_script_prefix(prefix):
- url = reverse('admin:auth_user_changelist', current_app=self.admin_site.name)
+ url = reverse(
+ "admin:auth_user_changelist", current_app=self.admin_site.name
+ )
self.assertURLEqual(
self.get_changelist_url(),
add_preserved_filters(context, url),
@@ -6473,40 +7664,44 @@ class NamespacedAdminKeepChangeListFiltersTests(AdminKeepChangeListFiltersTests)
admin_site = site2
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class TestLabelVisibility(TestCase):
- """ #11277 -Labels of hidden fields in admin were not hidden. """
+ """#11277 -Labels of hidden fields in admin were not hidden."""
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_all_fields_visible(self):
- response = self.client.get(reverse('admin:admin_views_emptymodelvisible_add'))
+ response = self.client.get(reverse("admin:admin_views_emptymodelvisible_add"))
self.assert_fieldline_visible(response)
- self.assert_field_visible(response, 'first')
- self.assert_field_visible(response, 'second')
+ self.assert_field_visible(response, "first")
+ self.assert_field_visible(response, "second")
def test_all_fields_hidden(self):
- response = self.client.get(reverse('admin:admin_views_emptymodelhidden_add'))
+ response = self.client.get(reverse("admin:admin_views_emptymodelhidden_add"))
self.assert_fieldline_hidden(response)
- self.assert_field_hidden(response, 'first')
- self.assert_field_hidden(response, 'second')
+ self.assert_field_hidden(response, "first")
+ self.assert_field_hidden(response, "second")
def test_mixin(self):
- response = self.client.get(reverse('admin:admin_views_emptymodelmixin_add'))
+ response = self.client.get(reverse("admin:admin_views_emptymodelmixin_add"))
self.assert_fieldline_visible(response)
- self.assert_field_hidden(response, 'first')
- self.assert_field_visible(response, 'second')
+ self.assert_field_hidden(response, "first")
+ self.assert_field_visible(response, "second")
def assert_field_visible(self, response, field_name):
self.assertContains(response, '<div class="fieldBox field-%s">' % field_name)
def assert_field_hidden(self, response, field_name):
- self.assertContains(response, '<div class="fieldBox field-%s hidden">' % field_name)
+ self.assertContains(
+ response, '<div class="fieldBox field-%s hidden">' % field_name
+ )
def assert_fieldline_visible(self, response):
self.assertContains(response, '<div class="form-row field-first field-second">')
@@ -6515,28 +7710,31 @@ class TestLabelVisibility(TestCase):
self.assertContains(response, '<div class="form-row hidden')
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminViewOnSiteTests(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
-
- cls.s1 = State.objects.create(name='New York')
- cls.s2 = State.objects.create(name='Illinois')
- cls.s3 = State.objects.create(name='California')
- cls.c1 = City.objects.create(state=cls.s1, name='New York')
- cls.c2 = City.objects.create(state=cls.s2, name='Chicago')
- cls.c3 = City.objects.create(state=cls.s3, name='San Francisco')
- cls.r1 = Restaurant.objects.create(city=cls.c1, name='Italian Pizza')
- cls.r2 = Restaurant.objects.create(city=cls.c1, name='Boulevard')
- cls.r3 = Restaurant.objects.create(city=cls.c2, name='Chinese Dinner')
- cls.r4 = Restaurant.objects.create(city=cls.c2, name='Angels')
- cls.r5 = Restaurant.objects.create(city=cls.c2, name='Take Away')
- cls.r6 = Restaurant.objects.create(city=cls.c3, name='The Unknown Restaurant')
- cls.w1 = Worker.objects.create(work_at=cls.r1, name='Mario', surname='Rossi')
- cls.w2 = Worker.objects.create(work_at=cls.r1, name='Antonio', surname='Bianchi')
- cls.w3 = Worker.objects.create(work_at=cls.r1, name='John', surname='Doe')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+
+ cls.s1 = State.objects.create(name="New York")
+ cls.s2 = State.objects.create(name="Illinois")
+ cls.s3 = State.objects.create(name="California")
+ cls.c1 = City.objects.create(state=cls.s1, name="New York")
+ cls.c2 = City.objects.create(state=cls.s2, name="Chicago")
+ cls.c3 = City.objects.create(state=cls.s3, name="San Francisco")
+ cls.r1 = Restaurant.objects.create(city=cls.c1, name="Italian Pizza")
+ cls.r2 = Restaurant.objects.create(city=cls.c1, name="Boulevard")
+ cls.r3 = Restaurant.objects.create(city=cls.c2, name="Chinese Dinner")
+ cls.r4 = Restaurant.objects.create(city=cls.c2, name="Angels")
+ cls.r5 = Restaurant.objects.create(city=cls.c2, name="Take Away")
+ cls.r6 = Restaurant.objects.create(city=cls.c3, name="The Unknown Restaurant")
+ cls.w1 = Worker.objects.create(work_at=cls.r1, name="Mario", surname="Rossi")
+ cls.w2 = Worker.objects.create(
+ work_at=cls.r1, name="Antonio", surname="Bianchi"
+ )
+ cls.w3 = Worker.objects.create(work_at=cls.r1, name="John", surname="Doe")
def setUp(self):
self.client.force_login(self.superuser)
@@ -6553,26 +7751,37 @@ class AdminViewOnSiteTests(TestCase):
# not included on the parent form, and the family_name of the parent
# does not match that of the child
post_data = {
- 'family_name': 'Test1',
- 'dependentchild_set-TOTAL_FORMS': '1',
- 'dependentchild_set-INITIAL_FORMS': '0',
- 'dependentchild_set-MAX_NUM_FORMS': '1',
- 'dependentchild_set-0-id': '',
- 'dependentchild_set-0-parent': '',
- 'dependentchild_set-0-family_name': 'Test2',
+ "family_name": "Test1",
+ "dependentchild_set-TOTAL_FORMS": "1",
+ "dependentchild_set-INITIAL_FORMS": "0",
+ "dependentchild_set-MAX_NUM_FORMS": "1",
+ "dependentchild_set-0-id": "",
+ "dependentchild_set-0-parent": "",
+ "dependentchild_set-0-family_name": "Test2",
}
- response = self.client.post(reverse('admin:admin_views_parentwithdependentchildren_add'), post_data)
- self.assertFormError(response, 'adminform', 'some_required_info', ['This field is required.'])
+ response = self.client.post(
+ reverse("admin:admin_views_parentwithdependentchildren_add"), post_data
+ )
+ self.assertFormError(
+ response, "adminform", "some_required_info", ["This field is required."]
+ )
msg = "The form 'adminform' in context 0 does not contain the non-field error 'Error'"
with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormError(response, 'adminform', None, ['Error'])
+ self.assertFormError(response, "adminform", None, ["Error"])
self.assertFormsetError(
- response, 'inline_admin_formset', 0, None,
- ['Children must share a family name with their parents in this contrived test case']
+ response,
+ "inline_admin_formset",
+ 0,
+ None,
+ [
+ "Children must share a family name with their parents in this contrived test case"
+ ],
)
msg = "The formset 'inline_admin_formset' in context 22 does not contain any non-form errors."
with self.assertRaisesMessage(AssertionError, msg):
- self.assertFormsetError(response, 'inline_admin_formset', None, None, ['Error'])
+ self.assertFormsetError(
+ response, "inline_admin_formset", None, None, ["Error"]
+ )
def test_change_view_form_and_formsets_run_validation(self):
"""
@@ -6580,26 +7789,38 @@ class AdminViewOnSiteTests(TestCase):
Verifying that if the parent form fails validation, the inlines also
run validation even if validation is contingent on parent form data
"""
- pwdc = ParentWithDependentChildren.objects.create(some_required_info=6, family_name='Test1')
+ pwdc = ParentWithDependentChildren.objects.create(
+ some_required_info=6, family_name="Test1"
+ )
# The form validation should fail because 'some_required_info' is
# not included on the parent form, and the family_name of the parent
# does not match that of the child
post_data = {
- 'family_name': 'Test2',
- 'dependentchild_set-TOTAL_FORMS': '1',
- 'dependentchild_set-INITIAL_FORMS': '0',
- 'dependentchild_set-MAX_NUM_FORMS': '1',
- 'dependentchild_set-0-id': '',
- 'dependentchild_set-0-parent': str(pwdc.id),
- 'dependentchild_set-0-family_name': 'Test1',
+ "family_name": "Test2",
+ "dependentchild_set-TOTAL_FORMS": "1",
+ "dependentchild_set-INITIAL_FORMS": "0",
+ "dependentchild_set-MAX_NUM_FORMS": "1",
+ "dependentchild_set-0-id": "",
+ "dependentchild_set-0-parent": str(pwdc.id),
+ "dependentchild_set-0-family_name": "Test1",
}
response = self.client.post(
- reverse('admin:admin_views_parentwithdependentchildren_change', args=(pwdc.id,)), post_data
+ reverse(
+ "admin:admin_views_parentwithdependentchildren_change", args=(pwdc.id,)
+ ),
+ post_data,
+ )
+ self.assertFormError(
+ response, "adminform", "some_required_info", ["This field is required."]
)
- self.assertFormError(response, 'adminform', 'some_required_info', ['This field is required.'])
self.assertFormsetError(
- response, 'inline_admin_formset', 0, None,
- ['Children must share a family name with their parents in this contrived test case']
+ response,
+ "inline_admin_formset",
+ 0,
+ None,
+ [
+ "Children must share a family name with their parents in this contrived test case"
+ ],
)
def test_check(self):
@@ -6613,33 +7834,48 @@ class AdminViewOnSiteTests(TestCase):
CityAdmin.view_on_site = lambda obj: obj.get_absolute_url()
self.assertEqual(admin.check(), [])
CityAdmin.view_on_site = []
- self.assertEqual(admin.check(), [
- Error(
- "The value of 'view_on_site' must be a callable or a boolean value.",
- obj=CityAdmin,
- id='admin.E025',
- ),
- ])
+ self.assertEqual(
+ admin.check(),
+ [
+ Error(
+ "The value of 'view_on_site' must be a callable or a boolean value.",
+ obj=CityAdmin,
+ id="admin.E025",
+ ),
+ ],
+ )
finally:
# Restore the original values for the benefit of other tests.
CityAdmin.view_on_site = True
def test_false(self):
"The 'View on site' button is not displayed if view_on_site is False"
- response = self.client.get(reverse('admin:admin_views_restaurant_change', args=(self.r1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_restaurant_change", args=(self.r1.pk,))
+ )
content_type_pk = ContentType.objects.get_for_model(Restaurant).pk
- self.assertNotContains(response, reverse('admin:view_on_site', args=(content_type_pk, 1)))
+ self.assertNotContains(
+ response, reverse("admin:view_on_site", args=(content_type_pk, 1))
+ )
def test_true(self):
"The default behavior is followed if view_on_site is True"
- response = self.client.get(reverse('admin:admin_views_city_change', args=(self.c1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_city_change", args=(self.c1.pk,))
+ )
content_type_pk = ContentType.objects.get_for_model(City).pk
- self.assertContains(response, reverse('admin:view_on_site', args=(content_type_pk, self.c1.pk)))
+ self.assertContains(
+ response, reverse("admin:view_on_site", args=(content_type_pk, self.c1.pk))
+ )
def test_callable(self):
"The right link is displayed if view_on_site is a callable"
- response = self.client.get(reverse('admin:admin_views_worker_change', args=(self.w1.pk,)))
- self.assertContains(response, '"/worker/%s/%s/"' % (self.w1.surname, self.w1.name))
+ response = self.client.get(
+ reverse("admin:admin_views_worker_change", args=(self.w1.pk,))
+ )
+ self.assertContains(
+ response, '"/worker/%s/%s/"' % (self.w1.surname, self.w1.name)
+ )
def test_missing_get_absolute_url(self):
"None is returned if model doesn't have get_absolute_url"
@@ -6647,51 +7883,66 @@ class AdminViewOnSiteTests(TestCase):
self.assertIsNone(model_admin.get_view_on_site_url(Worker()))
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class InlineAdminViewOnSiteTest(TestCase):
-
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
-
- cls.s1 = State.objects.create(name='New York')
- cls.s2 = State.objects.create(name='Illinois')
- cls.s3 = State.objects.create(name='California')
- cls.c1 = City.objects.create(state=cls.s1, name='New York')
- cls.c2 = City.objects.create(state=cls.s2, name='Chicago')
- cls.c3 = City.objects.create(state=cls.s3, name='San Francisco')
- cls.r1 = Restaurant.objects.create(city=cls.c1, name='Italian Pizza')
- cls.r2 = Restaurant.objects.create(city=cls.c1, name='Boulevard')
- cls.r3 = Restaurant.objects.create(city=cls.c2, name='Chinese Dinner')
- cls.r4 = Restaurant.objects.create(city=cls.c2, name='Angels')
- cls.r5 = Restaurant.objects.create(city=cls.c2, name='Take Away')
- cls.r6 = Restaurant.objects.create(city=cls.c3, name='The Unknown Restaurant')
- cls.w1 = Worker.objects.create(work_at=cls.r1, name='Mario', surname='Rossi')
- cls.w2 = Worker.objects.create(work_at=cls.r1, name='Antonio', surname='Bianchi')
- cls.w3 = Worker.objects.create(work_at=cls.r1, name='John', surname='Doe')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
+
+ cls.s1 = State.objects.create(name="New York")
+ cls.s2 = State.objects.create(name="Illinois")
+ cls.s3 = State.objects.create(name="California")
+ cls.c1 = City.objects.create(state=cls.s1, name="New York")
+ cls.c2 = City.objects.create(state=cls.s2, name="Chicago")
+ cls.c3 = City.objects.create(state=cls.s3, name="San Francisco")
+ cls.r1 = Restaurant.objects.create(city=cls.c1, name="Italian Pizza")
+ cls.r2 = Restaurant.objects.create(city=cls.c1, name="Boulevard")
+ cls.r3 = Restaurant.objects.create(city=cls.c2, name="Chinese Dinner")
+ cls.r4 = Restaurant.objects.create(city=cls.c2, name="Angels")
+ cls.r5 = Restaurant.objects.create(city=cls.c2, name="Take Away")
+ cls.r6 = Restaurant.objects.create(city=cls.c3, name="The Unknown Restaurant")
+ cls.w1 = Worker.objects.create(work_at=cls.r1, name="Mario", surname="Rossi")
+ cls.w2 = Worker.objects.create(
+ work_at=cls.r1, name="Antonio", surname="Bianchi"
+ )
+ cls.w3 = Worker.objects.create(work_at=cls.r1, name="John", surname="Doe")
def setUp(self):
self.client.force_login(self.superuser)
def test_false(self):
"The 'View on site' button is not displayed if view_on_site is False"
- response = self.client.get(reverse('admin:admin_views_state_change', args=(self.s1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_state_change", args=(self.s1.pk,))
+ )
content_type_pk = ContentType.objects.get_for_model(City).pk
- self.assertNotContains(response, reverse('admin:view_on_site', args=(content_type_pk, self.c1.pk)))
+ self.assertNotContains(
+ response, reverse("admin:view_on_site", args=(content_type_pk, self.c1.pk))
+ )
def test_true(self):
"The 'View on site' button is displayed if view_on_site is True"
- response = self.client.get(reverse('admin:admin_views_city_change', args=(self.c1.pk,)))
+ response = self.client.get(
+ reverse("admin:admin_views_city_change", args=(self.c1.pk,))
+ )
content_type_pk = ContentType.objects.get_for_model(Restaurant).pk
- self.assertContains(response, reverse('admin:view_on_site', args=(content_type_pk, self.r1.pk)))
+ self.assertContains(
+ response, reverse("admin:view_on_site", args=(content_type_pk, self.r1.pk))
+ )
def test_callable(self):
"The right link is displayed if view_on_site is a callable"
- response = self.client.get(reverse('admin:admin_views_restaurant_change', args=(self.r1.pk,)))
- self.assertContains(response, '"/worker_inline/%s/%s/"' % (self.w1.surname, self.w1.name))
+ response = self.client.get(
+ reverse("admin:admin_views_restaurant_change", args=(self.r1.pk,))
+ )
+ self.assertContains(
+ response, '"/worker_inline/%s/%s/"' % (self.w1.surname, self.w1.name)
+ )
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class GetFormsetsWithInlinesArgumentTest(TestCase):
"""
#23934 - When adding a new model instance in the admin, the 'obj' argument
@@ -6703,31 +7954,43 @@ class GetFormsetsWithInlinesArgumentTest(TestCase):
@classmethod
def setUpTestData(cls):
- cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
+ cls.superuser = User.objects.create_superuser(
+ username="super", password="secret", email="super@example.com"
+ )
def setUp(self):
self.client.force_login(self.superuser)
def test_explicitly_provided_pk(self):
- post_data = {'name': '1'}
- response = self.client.post(reverse('admin:admin_views_explicitlyprovidedpk_add'), post_data)
+ post_data = {"name": "1"}
+ response = self.client.post(
+ reverse("admin:admin_views_explicitlyprovidedpk_add"), post_data
+ )
self.assertEqual(response.status_code, 302)
- post_data = {'name': '2'}
- response = self.client.post(reverse('admin:admin_views_explicitlyprovidedpk_change', args=(1,)), post_data)
+ post_data = {"name": "2"}
+ response = self.client.post(
+ reverse("admin:admin_views_explicitlyprovidedpk_change", args=(1,)),
+ post_data,
+ )
self.assertEqual(response.status_code, 302)
def test_implicitly_generated_pk(self):
- post_data = {'name': '1'}
- response = self.client.post(reverse('admin:admin_views_implicitlygeneratedpk_add'), post_data)
+ post_data = {"name": "1"}
+ response = self.client.post(
+ reverse("admin:admin_views_implicitlygeneratedpk_add"), post_data
+ )
self.assertEqual(response.status_code, 302)
- post_data = {'name': '2'}
- response = self.client.post(reverse('admin:admin_views_implicitlygeneratedpk_change', args=(1,)), post_data)
+ post_data = {"name": "2"}
+ response = self.client.post(
+ reverse("admin:admin_views_implicitlygeneratedpk_change", args=(1,)),
+ post_data,
+ )
self.assertEqual(response.status_code, 302)
-@override_settings(ROOT_URLCONF='admin_views.urls')
+@override_settings(ROOT_URLCONF="admin_views.urls")
class AdminSiteFinalCatchAllPatternTests(TestCase):
"""
Verifies the behaviour of the admin catch-all view.
@@ -6738,107 +8001,116 @@ class AdminSiteFinalCatchAllPatternTests(TestCase):
* Otherwise Http404.
* Catch-all view disabled via AdminSite.final_catch_all_view.
"""
+
def test_unknown_url_redirects_login_if_not_authenticated(self):
- unknown_url = '/test_admin/admin/unknown/'
+ unknown_url = "/test_admin/admin/unknown/"
response = self.client.get(unknown_url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), unknown_url))
+ self.assertRedirects(
+ response, "%s?next=%s" % (reverse("admin:login"), unknown_url)
+ )
def test_unknown_url_404_if_authenticated(self):
superuser = User.objects.create_superuser(
- username='super',
- password='secret',
- email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
)
self.client.force_login(superuser)
- unknown_url = '/test_admin/admin/unknown/'
+ unknown_url = "/test_admin/admin/unknown/"
response = self.client.get(unknown_url)
self.assertEqual(response.status_code, 404)
def test_known_url_redirects_login_if_not_authenticated(self):
- known_url = reverse('admin:admin_views_article_changelist')
+ known_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(known_url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), known_url))
+ self.assertRedirects(
+ response, "%s?next=%s" % (reverse("admin:login"), known_url)
+ )
def test_known_url_missing_slash_redirects_login_if_not_authenticated(self):
- known_url = reverse('admin:admin_views_article_changelist')[:-1]
+ known_url = reverse("admin:admin_views_article_changelist")[:-1]
response = self.client.get(known_url)
# Redirects with the next URL also missing the slash.
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), known_url))
+ self.assertRedirects(
+ response, "%s?next=%s" % (reverse("admin:login"), known_url)
+ )
def test_non_admin_url_shares_url_prefix(self):
- url = reverse('non_admin')[:-1]
+ url = reverse("non_admin")[:-1]
response = self.client.get(url)
# Redirects with the next URL also missing the slash.
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), url))
+ self.assertRedirects(response, "%s?next=%s" % (reverse("admin:login"), url))
def test_url_without_trailing_slash_if_not_authenticated(self):
- url = reverse('admin:article_extra_json')
+ url = reverse("admin:article_extra_json")
response = self.client.get(url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), url))
+ self.assertRedirects(response, "%s?next=%s" % (reverse("admin:login"), url))
def test_unkown_url_without_trailing_slash_if_not_authenticated(self):
- url = reverse('admin:article_extra_json')[:-1]
+ url = reverse("admin:article_extra_json")[:-1]
response = self.client.get(url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), url))
+ self.assertRedirects(response, "%s?next=%s" % (reverse("admin:login"), url))
@override_settings(APPEND_SLASH=True)
def test_missing_slash_append_slash_true_unknown_url(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- unknown_url = '/test_admin/admin/unknown/'
+ unknown_url = "/test_admin/admin/unknown/"
response = self.client.get(unknown_url[:-1])
self.assertEqual(response.status_code, 404)
@override_settings(APPEND_SLASH=True)
def test_missing_slash_append_slash_true(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin:admin_views_article_changelist')
+ known_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
- self.assertRedirects(response, known_url, status_code=301, target_status_code=403)
+ self.assertRedirects(
+ response, known_url, status_code=301, target_status_code=403
+ )
@override_settings(APPEND_SLASH=True)
def test_missing_slash_append_slash_true_script_name(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin:admin_views_article_changelist')
- response = self.client.get(known_url[:-1], SCRIPT_NAME='/prefix/')
+ known_url = reverse("admin:admin_views_article_changelist")
+ response = self.client.get(known_url[:-1], SCRIPT_NAME="/prefix/")
self.assertRedirects(
response,
- '/prefix' + known_url,
+ "/prefix" + known_url,
status_code=301,
fetch_redirect_response=False,
)
- @override_settings(APPEND_SLASH=True, FORCE_SCRIPT_NAME='/prefix/')
+ @override_settings(APPEND_SLASH=True, FORCE_SCRIPT_NAME="/prefix/")
def test_missing_slash_append_slash_true_force_script_name(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin:admin_views_article_changelist')
+ known_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
self.assertRedirects(
response,
- '/prefix' + known_url,
+ "/prefix" + known_url,
status_code=301,
fetch_redirect_response=False,
)
@@ -6846,129 +8118,150 @@ class AdminSiteFinalCatchAllPatternTests(TestCase):
@override_settings(APPEND_SLASH=True)
def test_missing_slash_append_slash_true_non_staff_user(self):
user = User.objects.create_user(
- username='user',
- password='secret',
- email='user@example.com',
+ username="user",
+ password="secret",
+ email="user@example.com",
is_staff=False,
)
self.client.force_login(user)
- known_url = reverse('admin:admin_views_article_changelist')
+ known_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
- self.assertRedirects(response, '/test_admin/admin/login/?next=/test_admin/admin/admin_views/article')
+ self.assertRedirects(
+ response,
+ "/test_admin/admin/login/?next=/test_admin/admin/admin_views/article",
+ )
@override_settings(APPEND_SLASH=False)
def test_missing_slash_append_slash_false(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin:admin_views_article_changelist')
+ known_url = reverse("admin:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
self.assertEqual(response.status_code, 404)
@override_settings(APPEND_SLASH=True)
def test_single_model_no_append_slash(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin9:admin_views_actor_changelist')
+ known_url = reverse("admin9:admin_views_actor_changelist")
response = self.client.get(known_url[:-1])
self.assertEqual(response.status_code, 404)
# Same tests above with final_catch_all_view=False.
def test_unknown_url_404_if_not_authenticated_without_final_catch_all_view(self):
- unknown_url = '/test_admin/admin10/unknown/'
+ unknown_url = "/test_admin/admin10/unknown/"
response = self.client.get(unknown_url)
self.assertEqual(response.status_code, 404)
def test_unknown_url_404_if_authenticated_without_final_catch_all_view(self):
superuser = User.objects.create_superuser(
- username='super',
- password='secret',
- email='super@example.com',
+ username="super",
+ password="secret",
+ email="super@example.com",
)
self.client.force_login(superuser)
- unknown_url = '/test_admin/admin10/unknown/'
+ unknown_url = "/test_admin/admin10/unknown/"
response = self.client.get(unknown_url)
self.assertEqual(response.status_code, 404)
- def test_known_url_redirects_login_if_not_authenticated_without_final_catch_all_view(self):
- known_url = reverse('admin10:admin_views_article_changelist')
+ def test_known_url_redirects_login_if_not_authenticated_without_final_catch_all_view(
+ self,
+ ):
+ known_url = reverse("admin10:admin_views_article_changelist")
response = self.client.get(known_url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin10:login'), known_url))
+ self.assertRedirects(
+ response, "%s?next=%s" % (reverse("admin10:login"), known_url)
+ )
- def test_known_url_missing_slash_redirects_with_slash_if_not_authenticated_without_final_catch_all_view(self):
- known_url = reverse('admin10:admin_views_article_changelist')
+ def test_known_url_missing_slash_redirects_with_slash_if_not_authenticated_without_final_catch_all_view(
+ self,
+ ):
+ known_url = reverse("admin10:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
- self.assertRedirects(response, known_url, status_code=301, fetch_redirect_response=False)
+ self.assertRedirects(
+ response, known_url, status_code=301, fetch_redirect_response=False
+ )
def test_non_admin_url_shares_url_prefix_without_final_catch_all_view(self):
- url = reverse('non_admin10')
+ url = reverse("non_admin10")
response = self.client.get(url[:-1])
self.assertRedirects(response, url, status_code=301)
- def test_url_without_trailing_slash_if_not_authenticated_without_final_catch_all_view(self):
- url = reverse('admin10:article_extra_json')
+ def test_url_without_trailing_slash_if_not_authenticated_without_final_catch_all_view(
+ self,
+ ):
+ url = reverse("admin10:article_extra_json")
response = self.client.get(url)
- self.assertRedirects(response, '%s?next=%s' % (reverse('admin10:login'), url))
+ self.assertRedirects(response, "%s?next=%s" % (reverse("admin10:login"), url))
- def test_unkown_url_without_trailing_slash_if_not_authenticated_without_final_catch_all_view(self):
- url = reverse('admin10:article_extra_json')[:-1]
+ def test_unkown_url_without_trailing_slash_if_not_authenticated_without_final_catch_all_view(
+ self,
+ ):
+ url = reverse("admin10:article_extra_json")[:-1]
response = self.client.get(url)
# Matches test_admin/admin10/admin_views/article/<path:object_id>/
- self.assertRedirects(response, url + '/', status_code=301, fetch_redirect_response=False)
+ self.assertRedirects(
+ response, url + "/", status_code=301, fetch_redirect_response=False
+ )
@override_settings(APPEND_SLASH=True)
- def test_missing_slash_append_slash_true_unknown_url_without_final_catch_all_view(self):
+ def test_missing_slash_append_slash_true_unknown_url_without_final_catch_all_view(
+ self,
+ ):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- unknown_url = '/test_admin/admin10/unknown/'
+ unknown_url = "/test_admin/admin10/unknown/"
response = self.client.get(unknown_url[:-1])
self.assertEqual(response.status_code, 404)
@override_settings(APPEND_SLASH=True)
def test_missing_slash_append_slash_true_without_final_catch_all_view(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin10:admin_views_article_changelist')
+ known_url = reverse("admin10:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
- self.assertRedirects(response, known_url, status_code=301, target_status_code=403)
+ self.assertRedirects(
+ response, known_url, status_code=301, target_status_code=403
+ )
@override_settings(APPEND_SLASH=False)
def test_missing_slash_append_slash_false_without_final_catch_all_view(self):
superuser = User.objects.create_user(
- username='staff',
- password='secret',
- email='staff@example.com',
+ username="staff",
+ password="secret",
+ email="staff@example.com",
is_staff=True,
)
self.client.force_login(superuser)
- known_url = reverse('admin10:admin_views_article_changelist')
+ known_url = reverse("admin10:admin_views_article_changelist")
response = self.client.get(known_url[:-1])
self.assertEqual(response.status_code, 404)
# Outside admin.
def test_non_admin_url_404_if_not_authenticated(self):
- unknown_url = '/unknown/'
+ unknown_url = "/unknown/"
response = self.client.get(unknown_url)
# Does not redirect to the admin login.
self.assertEqual(response.status_code, 404)
diff --git a/tests/admin_views/urls.py b/tests/admin_views/urls.py
index 355e082b68..c1e673d811 100644
--- a/tests/admin_views/urls.py
+++ b/tests/admin_views/urls.py
@@ -10,23 +10,31 @@ def non_admin_view(request):
urlpatterns = [
- path('test_admin/admin/doc/', include('django.contrib.admindocs.urls')),
- path('test_admin/admin/secure-view/', views.secure_view, name='secure_view'),
- path('test_admin/admin/secure-view2/', views.secure_view2, name='secure_view2'),
- path('test_admin/admin/', admin.site.urls),
- path('test_admin/admin2/', customadmin.site.urls),
- path('test_admin/admin3/', (admin.site.get_urls(), 'admin', 'admin3'), {'form_url': 'pony'}),
- path('test_admin/admin4/', customadmin.simple_site.urls),
- path('test_admin/admin5/', admin.site2.urls),
- path('test_admin/admin6/', admin.site6.urls),
- path('test_admin/admin7/', admin.site7.urls),
+ path("test_admin/admin/doc/", include("django.contrib.admindocs.urls")),
+ path("test_admin/admin/secure-view/", views.secure_view, name="secure_view"),
+ path("test_admin/admin/secure-view2/", views.secure_view2, name="secure_view2"),
+ path("test_admin/admin/", admin.site.urls),
+ path("test_admin/admin2/", customadmin.site.urls),
+ path(
+ "test_admin/admin3/",
+ (admin.site.get_urls(), "admin", "admin3"),
+ {"form_url": "pony"},
+ ),
+ path("test_admin/admin4/", customadmin.simple_site.urls),
+ path("test_admin/admin5/", admin.site2.urls),
+ path("test_admin/admin6/", admin.site6.urls),
+ path("test_admin/admin7/", admin.site7.urls),
# All admin views accept `extra_context` to allow adding it like this:
- path('test_admin/admin8/', (admin.site.get_urls(), 'admin', 'admin-extra-context'), {'extra_context': {}}),
- path('test_admin/admin9/', admin.site9.urls),
- path('test_admin/admin10/', admin.site10.urls),
- path('test_admin/has_permission_admin/', custom_has_permission_admin.site.urls),
- path('test_admin/autocomplete_admin/', autocomplete_site.urls),
+ path(
+ "test_admin/admin8/",
+ (admin.site.get_urls(), "admin", "admin-extra-context"),
+ {"extra_context": {}},
+ ),
+ path("test_admin/admin9/", admin.site9.urls),
+ path("test_admin/admin10/", admin.site10.urls),
+ path("test_admin/has_permission_admin/", custom_has_permission_admin.site.urls),
+ path("test_admin/autocomplete_admin/", autocomplete_site.urls),
# Shares the admin URL prefix.
- path('test_admin/admin/non_admin_view/', non_admin_view, name='non_admin'),
- path('test_admin/admin10/non_admin_view/', non_admin_view, name='non_admin10'),
+ path("test_admin/admin/non_admin_view/", non_admin_view, name="non_admin"),
+ path("test_admin/admin10/non_admin_view/", non_admin_view, name="non_admin10"),
]
diff --git a/tests/admin_views/views.py b/tests/admin_views/views.py
index 430f084693..e3dd549ca4 100644
--- a/tests/admin_views/views.py
+++ b/tests/admin_views/views.py
@@ -7,6 +7,6 @@ def secure_view(request):
return HttpResponse(str(request.POST))
-@staff_member_required(redirect_field_name='myfield')
+@staff_member_required(redirect_field_name="myfield")
def secure_view2(request):
return HttpResponse(str(request.POST))