Hey, everyone!
I’ve got a problem, that i need to rename a field in a specific inline, that uses both form and a formset, but it doesn’t change at all.
Usage: Admin Panel, no specific views.
Inline:
class AuthorOnlyInline(GenericTabularInline):
model = Author
extra = 1
formset = AuthorInlineFormset
fields = ("employee",)
autocomplete_fields = ["employee"]
def formfield_for_foreignkey(
self, db_field: ForeignKey, request: HttpRequest, **kwargs: Any
) -> ModelChoiceField | None:
if db_field.name == "employee":
kwargs["label"] = "составитель"
return super().formfield_for_foreignkey(db_field, request, **kwargs)
def get_formset(self, request, obj=None, **kwargs):
FormSet = super().get_formset(request, obj, **kwargs)
class RequestFormSet(FormSet):
def __init__(self, *args, **kwargs):
kwargs["request"] = request
super().__init__(*args, **kwargs)
return RequestFormSet
classes = (
"author-inline",
"author_only-inline",
)
Form and Formset:
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = "__all__"
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super().__init__(*args, **kwargs)
if self.request and self.instance and self.instance.pk:
if not self.can_edit():
for field in self.fields:
self.fields[field].disabled = True
self.fields[field].widget.attrs["readonly"] = True
def can_edit(self):
"""Проверка, может ли текущий пользователь редактировать эту запись."""
if not self.request or not self.instance:
return True
if self.request.user.is_superuser:
return True
return self.instance.employee == self.request.user
class AuthorInlineFormset(BaseGenericInlineFormSet):
def __init__(self, *args, **kwargs):
self.form = AuthorForm
self.request = kwargs.pop("request", None)
self.parent_instance = kwargs.get("instance", None)
if self.parent_instance and self.parent_instance.pk:
self.extra = 0
self.initial_authors = []
else:
self.extra = 1
self.initial_authors = [
{
"employee": self.request.user,
}
]
super().__init__(*args, initial=self.initial_authors, **kwargs)
def _construct_form(self, i, **kwargs):
"""Передаем request в каждую форму."""
kwargs["request"] = self.request
return super()._construct_form(i, **kwargs)
@property
def _new_init(self):
"""Инициализируется ли formset в первый раз"""
return self.extra == 1
def save(self, commit=True):
result = super().save(commit=False)
if self._new_init and len(self.forms) != len(result):
for initial_author, initial_form in zip(
self.initial_authors[::-1],
self.forms[: len(self.initial_authors)][::-1],
):
if not any(
instance.employee == initial_author["employee"]
for instance in result
):
result.insert(
0,
self.model(
content_object=self.instance,
employee=initial_author["employee"],
int_affiliation=initial_author.get("int_affiliation", 1),
role=initial_author.get("role"),
),
)
for author in result:
author.department_at_moment = author.employee.department
if author.employee == self.request.user:
author.has_read = True
if commit:
author.save()
return result
Idk if it’s needed, but,
ModelAdmin that uses that inline: The AbstractAdmin is a model that’s just tuned up ModelAdmin, even without it the error still stands
@admin.register(Publication)
class PublicationAdmin(AbstractAdmin):
list_display = ("id", "publication_type", "display_authors", "total_affiliation")
autocomplete_fields = ["grant"]
change_form_template = "admin/publications/publication/change_form.html"
inlines = [
AuthorWithoutRoleInline,
AuthorOnlyInline,
AuthorInline,
ArticleInline,
MonographInline,
FieldResearchReportInline,
CollectionInline,
]
def get_fieldsets(self, request, obj=None):
"""Разделяем поля на две группы: до и после инлайна автора"""
fieldsets = (
(
"Основная информация",
{
"fields": (
"publication_type",
"grant",
),
},
),
(
"Дополнительная информация",
{
"fields": (
"year_publication",
"quarter_publication",
"foreign_work",
),
},
),
)
return fieldsets
def display_authors(self, obj):
"""
Возвращает строку со всеми авторами, привязанными к этой публикации.
"""
authors = Author.objects.filter(
content_type__model="publication", object_id=obj.id
)
author_names = [str(author.employee) for author in authors]
return ",\n".join(author_names) if author_names else "Нет авторов"
display_authors.short_description = "Авторы"
def save_formset(self, request, form, formset, change):
if isinstance(formset, AuthorInlineFormset):
if request.POST["publication_type"] in ("collection", "article"):
id_pub = "0"
elif request.POST["publication_type"] in ("monograph"):
id_pub = "3-0"
elif request.POST["publication_type"] in ("field_research_report"):
id_pub = "2-0"
formset.initial_authors[0]["int_affiliation"] = request.POST.get(
f"core-author-content_type-object_id-{id_pub}-int_affiliation", 1
)
formset.initial_authors[0]["role"] = request.POST.get(
f"core-author-content_type-object_id-{id_pub}-role"
)
formset.save()
def save_related(self, request, form, formsets, change):
"""
Вызывается после сохранения всех инлайнов (авторов).
"""
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=change)
form.instance.total_affiliation = form.instance.calculate_total_affiliation()
form.instance.save(update_fields=["total_affiliation"])
def get_formsets_with_inlines(self, request, obj=None):
formsets_with_inlines = super().get_formsets_with_inlines(request, obj)
if obj:
filtered_formsets = []
for formset, inline in formsets_with_inlines:
if (
(
isinstance(inline, AuthorWithoutRoleInline)
and obj.publication_type in ("collection", "article")
)
or (
isinstance(inline, AuthorInline)
and obj.publication_type == "monograph"
)
or (
isinstance(inline, AuthorOnlyInline)
and obj.publication_type == "field_research_report"
)
):
filtered_formsets.append((formset, inline))
elif (
(
isinstance(inline, ArticleInline)
and obj.publication_type == "article"
)
or (
isinstance(inline, MonographInline)
and obj.publication_type == "monograph"
)
or (
isinstance(inline, FieldResearchReportInline)
and obj.publication_type == "field_research_report"
)
or (
isinstance(inline, CollectionInline)
and obj.publication_type == "collection"
)
):
filtered_formsets.append((formset, inline))
return filtered_formsets
if request.method == "POST":
publication_type = request.POST.get("publication_type")
filtered_formsets = []
for formset, inline in formsets_with_inlines:
if (
(
isinstance(inline, AuthorWithoutRoleInline)
and publication_type in ("collection", "article")
)
or (
isinstance(inline, AuthorInline)
and publication_type == "monograph"
)
or (
isinstance(inline, AuthorOnlyInline)
and publication_type == "field_research_report"
)
):
filtered_formsets.append((formset, inline))
elif (
(
isinstance(inline, ArticleInline)
and publication_type == "article"
)
or (
isinstance(inline, MonographInline)
and publication_type == "monograph"
)
or (
isinstance(inline, FieldResearchReportInline)
and publication_type == "field_research_report"
)
or (
isinstance(inline, CollectionInline)
and publication_type == "collection"
)
):
filtered_formsets.append((formset, inline))
return filtered_formsets
return formsets_with_inlines
Please, help!
P. S.
If i use the form = AuthorForm in the Inline then everything works…