В админке Django отсутствуют кнопки «Добавить / Редактировать» при использовании get_form () - PullRequest
0 голосов
/ 23 октября 2018

При переопределении метода get_form() в классе ModelAdmin значки «Добавить» и «Изменить» (знак плюс и карандаш) не отображаются рядом с какими-либо полями на странице администратора, даже если разрешения правильные.Как только я удаляю переопределенный метод get_form(), появляются значки.Я использую фабрику форм для визуализации класса ModelForm, чтобы выполнить некоторую фильтрацию наборов запросов на основе текущего пользователя, поэтому я не могу использовать form = <ModelForm> в администраторе (форма должна захватывать объект HttpRequest).

(с использованием Django 2.1 и Python 3.6)

admin.py

@admin.register(Reservation)
class ReservationAdmin(admin.ModelAdmin):
    list_display = ('room', 'check_in_date', 'check_out_date', 'guest', 'reserved_by', 'reserved_on')
    inlines = (RoomChangeInline,)


    fieldsets = ( 
    (None, {
        'fields': (
            ('room', 'guest'),
            ('check_in_date', 'check_out_date'),
            ('adults', 'children'),
            ('subtotal', 'taxes', 'deposit'),
            ('reserved_by', 'reserved_on')
        )
    }),)   

    def get_form(self, request, obj=None, **kwargs):
        return reservation_admin_form_factory(request)

forms.py

def reservation_admin_form_factory(request):
    class ReservationAdminForm(forms.ModelForm):
        class Meta: 
            model = Reservation
            exclude = []
            widgets = {
                'check_in_date': forms.DateInput(attrs={'type': 'date'}),
                'check_out_date': forms.DateInput(attrs={'type': 'date'})
            }

        """ I have an __init__() method, but even if I remove it 
        the problem remains, so I am not showing it here. """

    return ReservationAdminForm

1 Ответ

0 голосов
/ 23 октября 2018

Чтобы отобразить кнопки Добавить / Редактировать на странице изменения администратора Django при переопределении ModelAdmin get_form(), вам нужно обернуть виджет поля в RelatedFieldWidgetWrapper примерно так:

forms.py

from django import forms
from django.conf import settings
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
from django.db.models.fields.reverse_related import ManyToOneRel

def reservation_admin_form_factory(request, admin_site):
    class ReservationAdminForm(forms.ModelForm):
        class Meta:
            model = Reservation
            exclude = []

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            rel = ManyToOneRel(Reservation.guest, Guest, 'id')
            self.fields['guest'].widget = RelatedFieldWidgetWrapper(
                 self.fields['guest'].widget, rel, admin_site, 
                     can_change_related=True)

Обратите внимание на приведенное выше использование фабрики форм (reservation_admin_form_factory) для захвата объекта admin_site, который необходим для RelatedFieldWidgetWrapper.

admin.py *

@admin.register(Reservation)
class ReservationAdmin(admin.ModelAdmin):
    list_display = ('check_in_date', 'check_out_date')

    def get_form(self, request, obj=None, **kwargs):
        self.form = reservation_admin_form_factory(request, admin.site)
        return super().get_form(request, obj, **kwargs)
...