mirror of
https://github.com/django/django.git
synced 2024-12-23 09:36:06 +00:00
536 lines
13 KiB
Python
536 lines
13 KiB
Python
from django import forms
|
|
from django.contrib import admin
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import models
|
|
|
|
from .models import (
|
|
Author,
|
|
BinaryTree,
|
|
CapoFamiglia,
|
|
Chapter,
|
|
Child,
|
|
ChildModel1,
|
|
ChildModel2,
|
|
Class,
|
|
Consigliere,
|
|
Course,
|
|
CourseProxy,
|
|
CourseProxy1,
|
|
CourseProxy2,
|
|
EditablePKBook,
|
|
ExtraTerrestrial,
|
|
Fashionista,
|
|
FootNote,
|
|
Holder,
|
|
Holder2,
|
|
Holder3,
|
|
Holder4,
|
|
Holder5,
|
|
Inner,
|
|
Inner2,
|
|
Inner3,
|
|
Inner4Stacked,
|
|
Inner4Tabular,
|
|
Inner5Stacked,
|
|
Inner5Tabular,
|
|
NonAutoPKBook,
|
|
NonAutoPKBookChild,
|
|
Novel,
|
|
NovelReadonlyChapter,
|
|
OutfitItem,
|
|
ParentModelWithCustomPk,
|
|
Person,
|
|
Photo,
|
|
Photographer,
|
|
Poll,
|
|
Profile,
|
|
ProfileCollection,
|
|
Question,
|
|
ReadOnlyInline,
|
|
ShoppingWeakness,
|
|
ShowInlineChild,
|
|
ShowInlineParent,
|
|
Sighting,
|
|
SomeChildModel,
|
|
SomeParentModel,
|
|
SottoCapo,
|
|
Teacher,
|
|
Title,
|
|
TitleCollection,
|
|
UUIDChild,
|
|
UUIDParent,
|
|
)
|
|
|
|
site = admin.AdminSite(name="admin")
|
|
|
|
|
|
class BookInline(admin.TabularInline):
|
|
model = Author.books.through
|
|
|
|
|
|
class NonAutoPKBookTabularInline(admin.TabularInline):
|
|
model = NonAutoPKBook
|
|
classes = ("collapse",)
|
|
|
|
|
|
class NonAutoPKBookChildTabularInline(admin.TabularInline):
|
|
model = NonAutoPKBookChild
|
|
classes = ("collapse",)
|
|
|
|
|
|
class NonAutoPKBookStackedInline(admin.StackedInline):
|
|
model = NonAutoPKBook
|
|
classes = ("collapse",)
|
|
|
|
|
|
class EditablePKBookTabularInline(admin.TabularInline):
|
|
model = EditablePKBook
|
|
|
|
|
|
class EditablePKBookStackedInline(admin.StackedInline):
|
|
model = EditablePKBook
|
|
|
|
|
|
class AuthorAdmin(admin.ModelAdmin):
|
|
inlines = [
|
|
BookInline,
|
|
NonAutoPKBookTabularInline,
|
|
NonAutoPKBookStackedInline,
|
|
EditablePKBookTabularInline,
|
|
EditablePKBookStackedInline,
|
|
NonAutoPKBookChildTabularInline,
|
|
]
|
|
|
|
|
|
class PhotoInlineMixin:
|
|
model = Photo
|
|
extra = 2
|
|
fieldsets = [
|
|
(None, {"fields": ["image", "title"]}),
|
|
(
|
|
"Details",
|
|
{"fields": ["description", "creation_date"], "classes": ["collapse"]},
|
|
),
|
|
(
|
|
"Details", # Fieldset name intentionally duplicated
|
|
{"fields": ["update_date", "updated_by"]},
|
|
),
|
|
]
|
|
|
|
|
|
class PhotoTabularInline(PhotoInlineMixin, admin.TabularInline):
|
|
pass
|
|
|
|
|
|
class PhotoStackedExtra2Inline(PhotoInlineMixin, admin.StackedInline):
|
|
pass
|
|
|
|
|
|
class PhotoStackedExtra3Inline(PhotoInlineMixin, admin.StackedInline):
|
|
extra = 3
|
|
|
|
|
|
class PhotoStackedCollapsibleInline(PhotoInlineMixin, admin.StackedInline):
|
|
fieldsets = []
|
|
classes = ["collapse"]
|
|
|
|
|
|
class PhotographerAdmin(admin.ModelAdmin):
|
|
fieldsets = [
|
|
(None, {"fields": ["firstname", "fullname"]}),
|
|
("Advanced options", {"fields": ["nationality", "residency"]}),
|
|
(
|
|
"Advanced options", # Fieldset name intentionally duplicated
|
|
{"fields": ["siblings", "children"], "classes": ["collapse"]},
|
|
),
|
|
]
|
|
inlines = [
|
|
PhotoTabularInline,
|
|
PhotoTabularInline,
|
|
PhotoStackedExtra2Inline,
|
|
PhotoStackedExtra3Inline,
|
|
PhotoStackedCollapsibleInline,
|
|
]
|
|
|
|
|
|
class InnerInline(admin.StackedInline):
|
|
model = Inner
|
|
can_delete = False
|
|
readonly_fields = ("readonly",) # For bug #13174 tests.
|
|
|
|
|
|
class HolderAdmin(admin.ModelAdmin):
|
|
class Media:
|
|
js = ("my_awesome_admin_scripts.js",)
|
|
|
|
|
|
class ReadOnlyInlineInline(admin.TabularInline):
|
|
model = ReadOnlyInline
|
|
readonly_fields = ["name"]
|
|
|
|
|
|
class InnerInline2(admin.StackedInline):
|
|
model = Inner2
|
|
|
|
class Media:
|
|
js = ("my_awesome_inline_scripts.js",)
|
|
|
|
|
|
class InnerInline2Tabular(admin.TabularInline):
|
|
model = Inner2
|
|
|
|
|
|
class CustomNumberWidget(forms.NumberInput):
|
|
class Media:
|
|
js = ("custom_number.js",)
|
|
|
|
|
|
class InnerInline3(admin.StackedInline):
|
|
model = Inner3
|
|
formfield_overrides = {
|
|
models.IntegerField: {"widget": CustomNumberWidget},
|
|
}
|
|
|
|
class Media:
|
|
js = ("my_awesome_inline_scripts.js",)
|
|
|
|
|
|
class TitleForm(forms.ModelForm):
|
|
title1 = forms.CharField(max_length=100)
|
|
|
|
def clean(self):
|
|
cleaned_data = self.cleaned_data
|
|
title1 = cleaned_data.get("title1")
|
|
title2 = cleaned_data.get("title2")
|
|
if title1 != title2:
|
|
raise ValidationError("The two titles must be the same")
|
|
return cleaned_data
|
|
|
|
|
|
class TitleInline(admin.TabularInline):
|
|
model = Title
|
|
form = TitleForm
|
|
extra = 1
|
|
|
|
|
|
class Inner4StackedInline(admin.StackedInline):
|
|
model = Inner4Stacked
|
|
show_change_link = True
|
|
|
|
|
|
class Inner4TabularInline(admin.TabularInline):
|
|
model = Inner4Tabular
|
|
show_change_link = True
|
|
|
|
|
|
class Holder4Admin(admin.ModelAdmin):
|
|
inlines = [Inner4StackedInline, Inner4TabularInline]
|
|
|
|
|
|
class Inner5StackedInline(admin.StackedInline):
|
|
model = Inner5Stacked
|
|
classes = ("collapse",)
|
|
|
|
|
|
class Inner5TabularInline(admin.TabularInline):
|
|
model = Inner5Tabular
|
|
classes = ("collapse",)
|
|
|
|
|
|
class Holder5Admin(admin.ModelAdmin):
|
|
inlines = [Inner5StackedInline, Inner5TabularInline]
|
|
|
|
|
|
class InlineWeakness(admin.TabularInline):
|
|
model = ShoppingWeakness
|
|
extra = 1
|
|
|
|
|
|
class WeaknessForm(forms.ModelForm):
|
|
extra_field = forms.CharField()
|
|
|
|
class Meta:
|
|
model = ShoppingWeakness
|
|
fields = "__all__"
|
|
|
|
|
|
class WeaknessInlineCustomForm(admin.TabularInline):
|
|
model = ShoppingWeakness
|
|
form = WeaknessForm
|
|
|
|
|
|
class FootNoteForm(forms.ModelForm):
|
|
extra_field = forms.CharField()
|
|
|
|
class Meta:
|
|
model = FootNote
|
|
fields = "__all__"
|
|
|
|
|
|
class FootNoteNonEditableInlineCustomForm(admin.TabularInline):
|
|
model = FootNote
|
|
form = FootNoteForm
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return False
|
|
|
|
|
|
class QuestionInline(admin.TabularInline):
|
|
model = Question
|
|
readonly_fields = ["call_me"]
|
|
|
|
def call_me(self, obj):
|
|
return "Callable in QuestionInline"
|
|
|
|
|
|
class PollAdmin(admin.ModelAdmin):
|
|
inlines = [QuestionInline]
|
|
|
|
def call_me(self, obj):
|
|
return "Callable in PollAdmin"
|
|
|
|
|
|
class ChapterInline(admin.TabularInline):
|
|
model = Chapter
|
|
readonly_fields = ["call_me"]
|
|
|
|
def call_me(self, obj):
|
|
return "Callable in ChapterInline"
|
|
|
|
|
|
class NovelAdmin(admin.ModelAdmin):
|
|
inlines = [ChapterInline]
|
|
|
|
|
|
class ReadOnlyChapterInline(admin.TabularInline):
|
|
model = Chapter
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return False
|
|
|
|
|
|
class NovelReadonlyChapterAdmin(admin.ModelAdmin):
|
|
inlines = [ReadOnlyChapterInline]
|
|
|
|
|
|
class ConsigliereInline(admin.TabularInline):
|
|
model = Consigliere
|
|
|
|
|
|
class SottoCapoInline(admin.TabularInline):
|
|
model = SottoCapo
|
|
|
|
|
|
class ProfileInline(admin.TabularInline):
|
|
model = Profile
|
|
extra = 1
|
|
|
|
|
|
# admin for #18433
|
|
class ChildModel1Inline(admin.TabularInline):
|
|
model = ChildModel1
|
|
|
|
|
|
class ChildModel2Inline(admin.StackedInline):
|
|
model = ChildModel2
|
|
|
|
|
|
# admin for #19425 and #18388
|
|
class BinaryTreeAdmin(admin.TabularInline):
|
|
model = BinaryTree
|
|
|
|
def get_extra(self, request, obj=None, **kwargs):
|
|
extra = 2
|
|
if obj:
|
|
return extra - obj.binarytree_set.count()
|
|
return extra
|
|
|
|
def get_max_num(self, request, obj=None, **kwargs):
|
|
max_num = 3
|
|
if obj:
|
|
return max_num - obj.binarytree_set.count()
|
|
return max_num
|
|
|
|
|
|
# admin for #19524
|
|
class SightingInline(admin.TabularInline):
|
|
model = Sighting
|
|
|
|
|
|
# admin and form for #18263
|
|
class SomeChildModelForm(forms.ModelForm):
|
|
class Meta:
|
|
fields = "__all__"
|
|
model = SomeChildModel
|
|
widgets = {
|
|
"position": forms.HiddenInput,
|
|
}
|
|
labels = {"readonly_field": "Label from ModelForm.Meta"}
|
|
help_texts = {"readonly_field": "Help text from ModelForm.Meta"}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields["name"].label = "new label"
|
|
|
|
|
|
class SomeChildModelInline(admin.TabularInline):
|
|
model = SomeChildModel
|
|
form = SomeChildModelForm
|
|
readonly_fields = ("readonly_field",)
|
|
|
|
|
|
class StudentInline(admin.StackedInline):
|
|
model = Child
|
|
extra = 1
|
|
fieldsets = [
|
|
("Name", {"fields": ("name",), "classes": ("collapse",)}),
|
|
]
|
|
|
|
|
|
class TeacherAdmin(admin.ModelAdmin):
|
|
inlines = [StudentInline]
|
|
|
|
|
|
class AuthorTabularInline(admin.TabularInline):
|
|
model = Author
|
|
|
|
|
|
class FashonistaStackedInline(admin.StackedInline):
|
|
model = Fashionista
|
|
|
|
|
|
# Admin for #30231
|
|
class ClassStackedHorizontal(admin.StackedInline):
|
|
model = Class
|
|
extra = 1
|
|
filter_horizontal = ["person"]
|
|
|
|
|
|
class ClassAdminStackedHorizontal(admin.ModelAdmin):
|
|
inlines = [ClassStackedHorizontal]
|
|
|
|
|
|
class ClassTabularHorizontal(admin.TabularInline):
|
|
model = Class
|
|
extra = 1
|
|
filter_horizontal = ["person"]
|
|
|
|
|
|
class ClassAdminTabularHorizontal(admin.ModelAdmin):
|
|
inlines = [ClassTabularHorizontal]
|
|
|
|
|
|
class ClassTabularVertical(admin.TabularInline):
|
|
model = Class
|
|
extra = 1
|
|
filter_vertical = ["person"]
|
|
|
|
|
|
class ClassAdminTabularVertical(admin.ModelAdmin):
|
|
inlines = [ClassTabularVertical]
|
|
|
|
|
|
class ClassStackedVertical(admin.StackedInline):
|
|
model = Class
|
|
extra = 1
|
|
filter_vertical = ["person"]
|
|
|
|
|
|
class ClassAdminStackedVertical(admin.ModelAdmin):
|
|
inlines = [ClassStackedVertical]
|
|
|
|
|
|
class ChildHiddenFieldForm(forms.ModelForm):
|
|
class Meta:
|
|
model = SomeChildModel
|
|
fields = ["name", "position", "parent"]
|
|
widgets = {"position": forms.HiddenInput}
|
|
|
|
def _post_clean(self):
|
|
super()._post_clean()
|
|
if self.instance is not None and self.instance.position == 1:
|
|
self.add_error(None, ValidationError("A non-field error"))
|
|
|
|
|
|
class ChildHiddenFieldTabularInline(admin.TabularInline):
|
|
model = SomeChildModel
|
|
form = ChildHiddenFieldForm
|
|
|
|
|
|
class ChildHiddenFieldInFieldsGroupStackedInline(admin.StackedInline):
|
|
model = SomeChildModel
|
|
form = ChildHiddenFieldForm
|
|
fields = [("name", "position")]
|
|
|
|
|
|
class ChildHiddenFieldOnSingleLineStackedInline(admin.StackedInline):
|
|
model = SomeChildModel
|
|
form = ChildHiddenFieldForm
|
|
fields = ("name", "position")
|
|
|
|
|
|
class ShowInlineChildInline(admin.StackedInline):
|
|
model = ShowInlineChild
|
|
|
|
|
|
class UUIDChildInline(admin.StackedInline):
|
|
model = UUIDChild
|
|
exclude = ("id",)
|
|
|
|
|
|
class UUIDParentModelAdmin(admin.ModelAdmin):
|
|
model = UUIDParent
|
|
inlines = [UUIDChildInline]
|
|
|
|
|
|
class ShowInlineParentAdmin(admin.ModelAdmin):
|
|
def get_inlines(self, request, obj):
|
|
if obj is not None and obj.show_inlines:
|
|
return [ShowInlineChildInline]
|
|
return []
|
|
|
|
|
|
site.register(TitleCollection, inlines=[TitleInline])
|
|
# Test bug #12561 and #12778
|
|
# only ModelAdmin media
|
|
site.register(Holder, HolderAdmin, inlines=[InnerInline])
|
|
# ModelAdmin and Inline media
|
|
site.register(Holder2, HolderAdmin, inlines=[InnerInline2, InnerInline2Tabular])
|
|
# only Inline media
|
|
site.register(Holder3, inlines=[InnerInline3])
|
|
|
|
site.register(Poll, PollAdmin)
|
|
site.register(Novel, NovelAdmin)
|
|
site.register(NovelReadonlyChapter, NovelReadonlyChapterAdmin)
|
|
site.register(Fashionista, inlines=[InlineWeakness])
|
|
site.register(Holder4, Holder4Admin)
|
|
site.register(Holder5, Holder5Admin)
|
|
site.register(Author, AuthorAdmin)
|
|
site.register(
|
|
CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline, ReadOnlyInlineInline]
|
|
)
|
|
site.register(ProfileCollection, inlines=[ProfileInline])
|
|
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
|
|
site.register(BinaryTree, inlines=[BinaryTreeAdmin])
|
|
site.register(ExtraTerrestrial, inlines=[SightingInline])
|
|
site.register(SomeParentModel, inlines=[SomeChildModelInline])
|
|
site.register([Question, Inner4Stacked, Inner4Tabular])
|
|
site.register(Teacher, TeacherAdmin)
|
|
site.register(Chapter, inlines=[FootNoteNonEditableInlineCustomForm])
|
|
site.register(OutfitItem, inlines=[WeaknessInlineCustomForm])
|
|
site.register(Person, inlines=[AuthorTabularInline, FashonistaStackedInline])
|
|
site.register(Photographer, PhotographerAdmin)
|
|
site.register(Course, ClassAdminStackedHorizontal)
|
|
site.register(CourseProxy, ClassAdminStackedVertical)
|
|
site.register(CourseProxy1, ClassAdminTabularVertical)
|
|
site.register(CourseProxy2, ClassAdminTabularHorizontal)
|
|
site.register(ShowInlineParent, ShowInlineParentAdmin)
|
|
site.register(UUIDParent, UUIDParentModelAdmin)
|
|
# Used to test hidden fields in tabular and stacked inlines.
|
|
site2 = admin.AdminSite(name="tabular_inline_hidden_field_admin")
|
|
site2.register(SomeParentModel, inlines=[ChildHiddenFieldTabularInline])
|
|
site3 = admin.AdminSite(name="stacked_inline_hidden_field_in_group_admin")
|
|
site3.register(SomeParentModel, inlines=[ChildHiddenFieldInFieldsGroupStackedInline])
|
|
site4 = admin.AdminSite(name="stacked_inline_hidden_field_on_single_line_admin")
|
|
site4.register(SomeParentModel, inlines=[ChildHiddenFieldOnSingleLineStackedInline])
|