【问题标题】:How do I exclude an inherited field in a form in Django?如何在 Django 中排除表单中的继承字段?
【发布时间】:2011-07-19 16:31:10
【问题描述】:

我有以下形式和继承形式:

class UsuarioAdminForm(ModelForm):

    first_name = forms.CharField(label='Nombre', help_text = 'Nombre del usuario', required=True)
    last_name = forms.CharField(label='Apellidos', help_text = 'Apellidos del usuario', required=True)
    dni = ESIdentityCardNumberField(help_text = 'DNI del usuario', required=True, widget = forms.TextInput(attrs = {'size': 9}))
    username = forms.CharField(label='Login', help_text = 'Requerido. 30 caracteres o menos. Letras, números y @/./+/-/_', widget = forms.TextInput(attrs = {'size': 15}))
    #password = forms.CharField(widget=forms.PasswordInput(attrs = {'size': 12}), label='Contraseña', help_text = 'Contraseña del usuario')
    email = forms.EmailField(help_text = 'Correo electrónico del usuario', required=True)
    movil = ESPhoneNumberField(help_text = 'Movil principal del usuario', required=True, widget = forms.TextInput(attrs = {'size': 9 }))
    is_staff = forms.BooleanField(label = "Administrador", help_text = 'Marque la casilla si desea crear un administrador')
    tipo_u = forms.ChoiceField(label = 'Tipo de usuario', choices = TipoUsuarios)
    def clean(self):
        try:
            cleaned_data = self.cleaned_data
            movil = self.cleaned_data['movil']
            dni = self.cleaned_data['dni']
            email = self.cleaned_data['email']
        except:
            raise forms.ValidationError(u'Todos los campos del Formulario son Obligatorios.')

        return cleaned_data

    class Meta:
        model = Usuario
        exclude = ('is_active','date_joined', 'last_login', 'user_permissions', 'tipo', 'groups', 'is_superuser', )


class UsuarioForm(UsuarioAdminForm):

    is_staff = None

    def __init__(self, *args, **kwargs):
        self.is_staff = None
        super(UsuarioForm,self).__init__(*args, **kwargs)

    class Meta:
        model = Usuario
        exclude = ('is_staff', 'is_active','date_joined', 'last_login', 'user_permissions', 'tipo', 'groups', 'is_superuser', 'password', )

但是当我创建一个 UsuarioForm 对象时,为什么它会显示 is_staff 字段?

更新:

如果我输入self.fields['is_staff'] = None,我会得到下一个错误:

TemplateSyntaxError 在 /sms/usuarios/add/user/

渲染时捕获 AttributeError: “NoneType”对象没有属性 '标签'

【问题讨论】:

  • 添加然后删除更容易,创建没有“is_staff”字段的 UsuarioForm 并且 UsuarioAdminForm 只有一个 - 实际的“is_staff=..”(这是最简单的并且将始终有效)。要删除类属性,您可以使用 del(self.is_staff) (在 init 中)但这可能会产生额外的后果,因为涉及到 MetaClasses - 所以尽量不要使用它。 :)

标签: python django django-forms


【解决方案1】:

也许你可以改变这些行的顺序:

def __init__(self, *args, **kwargs):
    super(UsuarioForm,self).__init__(*args, **kwargs)        
    self.is_staff = None

你也可以这样做:

def __init__(self, *args, **kwargs):
    super(UsuarioForm,self).__init__(*args, **kwargs)
    self.fields.pop('is_staff')

【讨论】:

    【解决方案2】:

    这是一个老问题,但从 Django 1.7.x 开始,您可以执行以下操作:

    class UsuarioForm(UsuarioAdminForm):
    
        is_staff = None
    
        class Meta:
            model = Usuario
            exclude = ('is_active', 'date_joined', 'last_login', 'user_permissions', 'tipo', 'groups', 'is_superuser', 'password')
    

    Metaexclude 部分仅用于排除ModelForm 元素,但可以通过在声明中将其设置为None 来排除任何表单元素。

    来自Django docs on subclassing forms

    可以以声明方式删除从父级继承的字段 通过在子类上将字段名称设置为 None 来创建类。为了 示例:

    >>> from django import forms
    
    >>> class ParentForm(forms.Form):
    ...     name = forms.CharField()
    ...     age = forms.IntegerField()
    
    >>> class ChildForm(ParentForm):
    ...     name = None
    
    >>> ChildForm().fields.keys()
    ... ['age']
    

    编辑

    我认为上述示例在给出的示例中有效,但它似乎不适用于由于 ModelForm 上的 Meta 而创建的字段。我认为在这些情况下,您需要从父级的 Meta 继承并更改给定的字段。

    【讨论】:

      【解决方案3】:

      Django 表单实例将字段存储在表单本身的 'fields' 属性中,因此在您的 init 中,调用 super 之后,您需要类似以下内容:

      self.fields['is_staff'] = None
      

      这应该可以解决您的问题;设置 self.is_staff 只是一个不相关的变量(您在类上设置的 is_staff 是类变量而不是实例变量)。

      【讨论】:

      • 如果我把 self.fields['is_staff'] = None 我得到下一个错误: TemplateSyntaxError at /sms/usuarios/add/user/ Caught AttributeError while rendering: 'NoneType' object has no attribute '标签'
      • 您需要在显示时添加逻辑以仅在对象具有它时才显示它。如果这仅在管理部分很重要,那么您实际上可以只使用 ModelAdmin 类上的“排除”设置。 docs.djangoproject.com/en/1.2/ref/contrib/admin/…
      • 将字段设置为 None 将使所有事情变得最糟糕,如果您需要 - 从列表中删除它(使用 del)但 不要将其设置为 None 因为它预计将是 BaseField 的一个实例,并且不会严重崩溃
      猜你喜欢
      • 2017-08-09
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多