覆盖formfield_for_choice_field抛出键错误

时间:2017-04-11 16:45:08

标签: django django-forms django-admin

在内联管理员中重写formfield_for_choice_field即使我什么都没改变,也会抛出关键错误?

ProfileInline:

class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False
    classes = ['collapse', ]
    form = ProfileForm
    readonly_fields = ('thumbnail_img', )
    extra = 1
    max_num = 1
    min_num = 1
    fieldsets = (
        (None, {
            'fields': (
                'thumbnail_img', 'avatar', 'nickname', 'gender',
                'phone_number', 'birth_place', 'birth_date', 'angkatan',
                'year_registered', 'year_graduation', 'religion', 'jobs'
            )
        }),
        ('Alamat saat sekolah di sman 3 Padang', {
            'fields': ('old_address', )
        }),
        ('Alamat sekarang', {
            'fields': ('curr_country', 'curr_province',
                   'curr_city', 'curr_street')
        }),
        ('Media Sosial', {
            'fields': ('link_facebook', 'link_twitter', 'link_instagram',
                   'link_whatsup', 'link_bbm')
        }),
        ('Sembunyikan Data Pribadi', {
            'fields': ('show_phone', 'show_curr_address', 'show_jobs',
                   'show_social_link', 'show_family')
        })
    )

    def formfield_for_choice_field(self, db_field, request, **kwargs):
        super(ProfileInline, self).formfield_for_choice_field(db_field, request, **kwargs)

键错误:

enter image description here

回溯:

Internal Server Error: /admin/accounts/alumni/add/
Traceback (most recent call last):
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\forms\forms.py", line 144, in __getitem__
    field = self.fields[name]
KeyError: 'gender'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
    response = get_response(request)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\core\handlers\base.py", line 217, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\core\handlers\base.py", line 215, in _get_response
    response = response.render()
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\response.py", line 109, in render
    self.content = self.rendered_content
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\response.py", line 86, in rendered_content
    content = template.render(context, self._request)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\backends\django.py", line 66, in render
    return self.template.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 208, in render
    return self._render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 199, in _render
    return self.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 174, in render
    return compiled_parent._render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 199, in _render
    return self.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 174, in render
    return compiled_parent._render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 199, in _render
    return self.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 70, in render
    result = block.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 70, in render
    result = block.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 210, in render
    return template.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 210, in render
    return self._render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 199, in _render
    return self.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\loader_tags.py", line 210, in render
    return template.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 210, in render
    return self._render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 199, in _render
    return self.nodelist.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 994, in render
    bit = node.render_annotated(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\base.py", line 961, in render_annotated
    return self.render(context)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\template\defaulttags.py", line 165, in render
    values = list(values)
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\contrib\admin\helpers.py", line 115, in __iter__
    yield AdminField(self.form, field, is_first=(i == 0))
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\contrib\admin\helpers.py", line 127, in __init__
    self.field = form[field]  # A django.forms.BoundField instance
  File "C:\Users\afdallismen\Envs\ikasmantri\lib\site-packages\django\forms\forms.py", line 150, in __getitem__
    ', '.join(sorted(f for f in self.fields)),
KeyError: "Key 'gender' not found in 'ProfileForm'. Choices are: avatar, birth_date, birth_place, curr_city, curr_country, curr_province, curr_street, id, jobs, link_bbm, link_facebook, link_instagram, link_twitter, link_whatsup, nickname,
old_address, phone_number, show_curr_address, show_family, show_jobs, show_phone, show_social_link, user."
[11/Apr/2017 23:52:29] "GET /admin/accounts/alumni/add/ HTTP/1.1" 500 381609

ProfileForm:

class ProfileForm(forms.ModelForm):
    curr_street = Address._meta.get_field('street').formfield()
    curr_city = Address._meta.get_field('city').formfield()
    curr_province = Address._meta.get_field('province').formfield()
    curr_country = Address._meta.get_field('country').formfield()

    class Meta:
        model = Profile
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        self.fields['birth_date'].input_formats = settings.DATE_INPUT_FORMATS
        if self.instance.pk is not None:
            self.fields['curr_street'].initial = self.instance.address.street
            self.fields['curr_city'].initial = self.instance.address.city
            self.fields[
                'curr_province'].initial = self.instance.address.province
            self.fields['curr_country'].initial = self.instance.address.country
        self.helper = FormHelper()
        self.helper.form_tag = False

我尝试从内联中删除fieldset,并且不会抛出任何错误。字段集是否是原因?

回顾追溯,我发现找不到的密钥是使用选择的字段。

这是我的模型的子集:

class Profile(models.Model):
    GENDER_CHOICES = choices.GENDER_CHOICES
    RELIGION_CHOICES = choices.RELIGION_CHOICES
    ANGKATAN_CHOICES = choices.ANGKATAN_CHOICES
    YEAR_REGISTERED_CHOICES = choices.YEAR_REGISTERED_CHOICES
    YEAR_GRADUATION_CHOICES = choices.YEAR_GRADUATION_CHOICES

    gender = models.CharField(
        verbose_name="jenis kelamin",
        max_length=1,
        choices=GENDER_CHOICES
    )
    angkatan = models.PositiveIntegerField(
        verbose_name="angkatan",
        choices=ANGKATAN_CHOICES,
        help_text="Angkatan di Sman 3 Padang."
    )
    year_registered = models.PositiveIntegerField(
        verbose_name="tahun masuk",
        choices=YEAR_REGISTERED_CHOICES,
        help_text="Tahun masuk di Sman 3 Padang."
    )
    year_graduation = models.PositiveIntegerField(
        verbose_name="tahun lulus",
        choices=YEAR_GRADUATION_CHOICES,
        help_text="Tahun lulus dari Sman 3 Padang."
    )
    religion = models.PositiveIntegerField(
        verbose_name="agama",
        choices=RELIGION_CHOICES
    )

在ProfileForm中找不到这5个字段。

通过在f​​ormfield_for_choice_field中调用super并使用django.contrib.admin.options.BaseModelAdmin类中的基本实现,找到了一些黑客:

def formfield_for_choice_field(self, db_field, request, **kwargs):
    # super(ProfileInline, self).formfield_for_choice_field(db_field, request, **kwargs)
    if db_field.name == "angkatan" and not request.user.is_superuser:
        kwargs['choices'] = (
            (request.user.admin.angkatan, str(request.user.admin.angkatan)),
        )

    # Base implementation bellow
    if db_field.name in self.radio_fields:
        # Avoid stomping on custom widget/choices arguments.
        if 'widget' not in kwargs:
            kwargs['widget'] = widgets.AdminRadioSelect(attrs={
                'class': get_ul_class(self.radio_fields[db_field.name]),
            })
        if 'choices' not in kwargs:
            kwargs['choices'] = db_field.get_choices(
                include_blank=db_field.blank,
                blank_choice=[('', _('None'))]
            )
    return db_field.formfield(**kwargs)

1 个答案:

答案 0 :(得分:1)

formfield_for_choice_field覆盖应返回一些内容。你应该这样写:

def formfield_for_choice_field(self, db_field, request, **kwargs):
    if db_field.name == "some_field":
        # do stuff
    return super(ProfileInline, self).formfield_for_choice_field(db_field, request, **kwargs)

您应该知道formfield_for_choice_field解释下面的note。详细解释了here