2013-03-11 3 views
2

Я не могу понять, почему метод clean_field() не вызывается для встроенной формы, которая обновляется в представлении администратора. Код, который у меня есть, кажется прямым (см. Краткое описание ниже).Django - clean_field() не вызывается для обновлений в встроенной форме администратора

Когда я изменить Primary форму через интерфейс администратора (http://admin/..../primary/1/), как и ожидалось, я вижу:

  • Admin.PrimaryAdminForm.clean_myfield() под названием
  • Admin.PrimaryAdminForm.clean() называется
  • Model.Primary.clean() называется

Однако, когда я изменить Primary как видно, как инлайн по мнению администратора о членстве (http://admin/..../membership/1/), я ОНЛ у см:

  • Model.Primary.clean() под названием

Я попытался поместить «DEF clean_myfield (сам):» метод в следующих местах, но не может видеть его получить выполнен из Членство встраиваемая Первичная форма:

  • Model.Primary.clean_myfield
  • Admin.PrimaryAdmin.clean_myfield
  • Admin.PrimaryAdminForm.clea n_myfield
  • Admin.PrimaryAdminInline.clean_myfield

Есть ли где-нибудь еще в этом clean_myfield код должен быть помещен?

Я прочитал (и перечитал) документы Django по [формам и проверке поля] [docs.djangoproject.com/en/dev/ref/forms/validation/#form-and-field-validation], что дает большой охват, но нет ничего на встроенной проверке. Я также читал docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin, но не помогал для встроенной специальной проверки. Есть ли другая документация по этому поводу?

--->Ответа на этот вопрос Austin дал ссылку на doc: «Если не указано» (см. Его ссылку), что подразумевает ответ. Я добавил request to improve документы по этой теме.

После дальнейшего экспериментирования я нашел обходной путь, поставив код в Model.Primary.clean() метод:

def clean(self): 
    data = self.myfield 
    data += "_extra" # not actual cleaning code 
    self.myfield = data 

Так что вопрос остается: Почему Model.clean(), как представляется, только место, чтобы ввести проверку встроенной формы администратора, а не метод clean_myfield (self)?

--->Ответа на этот вопрос Austin. Мне нужно было добавить form = PrimaryAdminForm в PrimaryInline. При этом добавлении PrimaryAdminForm.clean_myfield (self) вызывается, когда PrimaryInline myfield обновляется в форме членства. Корректировка кода была обновлена ​​из-за добавленной ссылки на форму.

Код синопсис:

Нет forms.py файл - все модели обновляются через интерфейс администратора

models.py:

class Membership(models.Model): 
    name = models.CharField(max_length=NAME_LENGTH, 
     null=True, blank=True, verbose_name="Membership Name Tag", 
     help_text="Name of membership") 

class Primary(models.Model): 
    user = models.OneToOneField(User, verbose_name="User Name") 
    membership = models.OneToOneField(Membership, verbose_name="Membership Name") 
    myfield = models.CharField("My Field", max_length=20, null=True, blank=True) 


    # clean method altered as in Update comment 
    # Why must this be here? Why not in clean_myfield(self) 
    def clean(self): 
     data = self.myfield 
     data += "_extra" # not actual cleaning code 
     self.myfield = data 

admin.py :

class MembershipAdminForm(ModelForm): 
    class Meta: 
     model = Membership 

class PrimaryAdminForm(ModelForm): 
    class Meta: 
     model = Primary 

    def clean_myfield(self): 
     data = self.cleaned_data['myfield'] 
     data += "_extra" # not actual cleaning code 
     return unicode(data) 

    def clean(self): 
     cleaned_data = super(PrimaryAdminForm, self).clean() 
     # not actual cleaning code 
     return cleaned_data 

# EDIT2: Moved PrimaryInline so it's defined after PrimaryAdminForm 
class PrimaryInline(admin.StackedInline): 
    model = Primary 
    form = PrimaryAdminForm #EDIT2 as recommended by Austin 
    raw_id_fields = ['user'] 
    verbose_name_plural = 'Primary Member' 
    fieldsets = ((None, {'classes': ('mbship',), 
         'fields': ('user', 'myfield')}),) 

class MembershipAdmin(admin.ModelAdmin): 
    form = MembershipAdminForm 

    # inlines 
    inlines = [PrimaryInline, ] 

    fieldsets = ((None, {'classes': ('mbship',), 
         'fields': ('name'), }),) 

class PrimaryAdmin(admin.ModelAdmin): 
    form = PrimaryAdminForm 
    list_display = ('__unicode__', 'user', 'status', 'date_used') 
    search_fields = ['user__first_name', 'user__last_name', 'user__email'] 

    fieldsets = ((None, {'classes': ('mbship',), 
         'fields': ('user', 'membership', 'myfield'), }),) 

    def clean_myfield(self): 
     data = self.cleaned_data['myfield'] 
     data += "_extra" # not actual cleaning code 
     return unicode(data) 
+0

Обновлено, чтобы отразить ответ Остина. – ChrisFreeman

ответ

7

Валидация происходит на ModelForm объектах, а не ModelAdmin объектов. Если вы хотите переопределить любые чистые методы, тогда вам нужно создать собственный потомок ModelForm для каждой требуемой модели.

В вашем примере класс PrimaryInline не указывает form. If not specified, используемая форма будет ModelForm, которая не имеет никаких ваших собственных чистых методов.

Попробуйте это:

class PrimaryInline(admin.StackedInline): 
    # ... existing code ... 
    form = PrimaryAdminForm 

Это теперь будет использовать пользовательские PrimaryAdminForm с соответствующими clean() методами.

+0

Спасибо Остин! Я хотел бы, чтобы в django docs был пример, показывающий как модель, так и форму, указанные для одного и того же определения класса. Я попросил обновить doc. Извините, я буду новым, чтобы поднять ваш ответ (я когда-нибудь вернусь, чтобы сделать это). – ChrisFreeman

+0

Наконец-то! Достаточно очков для голосования! (2 1/2 года спустя) – ChrisFreeman

Смежные вопросы