ModelForm的表单类是否可以更改属性?

时间:2013-05-28 10:13:01

标签: python django forms

我在StackOverflow中阅读了关于forms.Form vs forms.ModelForm的一些帖子。

似乎当表单的数据库中已有表时,最好使用ModelForm,这样就不必再次声明所有属性,因为它们已存在于相应的类中model.py

所以我的问题是

  1. 如何排除原始类的一系列属性,以下是排除表达式okie?

    class CreatePositionForm(ModelForm):  
        class Meta:  
            model = job_position 
            exclude = ('create_date','post_date','is_valid',)
    
  2. 使用ModelForm时,是否意味着原始属性不应该更改,并且在Meta类之前不会再有代码?(就像上面的代码一样)

  3. 任何人都可以告诉我使用表单而不仅仅是HTML的好处 表单标签,除了它有助于报告错误

    form.field_name.errors
    

    我是Django的新学员,如果这些问题看起来很愚蠢,请耐心等待,非常感谢你的澄清!

6 个答案:

答案 0 :(得分:2)

似乎“验证”对3来说是一个很大的答案 - 它通常是Web框架的一个主要特征。至于不使用HTML标签,还有DRY principle:如果您已经定义了表单的字段(用于验证目的),为什么还要在模板中复制它?有一个关于表单外观的单一事实来源(在Django中,Form个对象,或ModelFormModel s),并派生出来你可以从那个单一的来源(HTML)。

答案 1 :(得分:2)

1 - 是的,这是可以使用的,

exclude = ['create_date','post_date','is_valid']

更多关于此处的模型表单 - https://docs.djangoproject.com/en/dev/topics/forms/modelforms/

2-你不能改变模型形式的属性是错误的, 您可以通过在类中定义相同的属性来过度使用它 你可以做任何像普通形式的事情来覆盖初始,选择等  exa -

from django.forms import ModelForm, DateField
class CreatePositionForm(ModelForm):
    created_date = DateField(label="when created")
    def __init__( self, *args, **kwargs ):
        super( CreatePositionForm, self ).__init__( *args, **kwargs )
        self.fields['your_choice_field'].choices = choice_list 
    class Meta:  
        model = job_position 
        exclude = ['create_date','post_date','is_valid']

3-最有价值的好处是它自己启用表单验证,无论你是否编写自己的html,你都必须编写长行代码。 对于exa - 你给了一个char字段它会抛出一个错误,并将错误类添加到html上的字段属性,这是一个很大的优点。 从这些开始,它可以减少编写html的开销,同时开发以检查功能。

答案 2 :(得分:1)

  1. exclude should be a list(虽然您也可以使用元组,但只需引用文档,请参阅注释)。您应该将其更改为 -

    exclude = ['create_date','post_date','is_valid']
    
  2. 没有那样的。你可以改变你想要的任何东西。您可以添加自定义窗口小部件,更改窗体域属性,甚至可以向其添加更多窗体域。 ModelForm只是使您的模型和表单更加耦合,以便正确地进行验证。如果您使用Form代替模型所具有的相同字段,则必须重新定义字段类型。

  3. 使用Form可以减轻您管理字段属性的难度。如果您在模型中更改某些内容,更改将自动反映到表单的HTML。您不必每次都手动更改HTML。它还可以帮助您进行自动验证。

答案 3 :(得分:1)

Form和ModelForm都扩展了同一个类:

class BaseModelForm(BaseForm)
class Form(BaseForm)

所以:

  1. 可以这样排除,但问题出在保存时:如果需要或者没有默认值,则必须处理代码中的排除字段

  2. 您可以向ModelForm对象添加额外的属性:

    类CreatePositionForm(ModelForm):
        new_field = forms.CharField(max_length = 100)     class Meta:
            model = job_position         exclude =('create_date','post_date','is_valid',) 但是你必须将它们包含在字段列表中(如果你想渲染它们):

    .... 类Meta:     ....     fields = [...,'new_field',...]

    保存时,您需要照顾该字段。

  3. 表单具有基于您使用的FormField和Widget类型的默认验证。 ModelForms还具有基于模型字段的验证,每个字段/每个表单的错误报告,直接保存到数据库。除此之外,我发现在使用formset(每页多个表单)时更容易使用modelforms。

答案 4 :(得分:1)

正如django docs所述:

  

如果您正在构建一个数据库驱动的应用程序,那么您可能会拥有与Django模型紧密相关的表单。例如,您可能有一个BlogComment模型,并且您想要创建一个允许人们提交注释的表单。在这种情况下,在表单中定义字段类型将是多余的,因为您已经在模型中定义了字段。

     

出于这个原因,Django提供了一个帮助器类,可以让你从Django模型创建一个Form类。

当您需要与任何已定义模型密切相关的表单时,ModelForm非常有用。 ModelForm对form.Form类的优势在于您不需要编写额外的代码。例如:假设您的模型定义如下:

class Profile(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField()
    phone = models.IntegerField()
    profile_summary = models.TextField()
    # .. some more fields ..

现在让我们使用3种不同的方法创建一个表单,看看哪一个最容易实现。

简单的HTML表单

对于纯HTML表单,您需要在模板中实现表单元素,然后自行验证数据,如下所示。

<form id="profile-form">
    <div>
        <label>First Name</label>
        <input name="first_name" type="text" />
    </div>
    <div>
        <label>Last Name</label>
        <input name="last_name" type="text" />
    </div>
    <div>
        <label>Email</label>
        <input name="email" type="text" />
    </div>
    <div>
        <label>Phone Number</label>
        <input name="phone" type="text" />
    </div>
    <div>
        <label>Profile Summary</label>
        <textarea name="profile_summary"></textarea>
    </div>
</form>

然后在视图中:

def update_profile(request):
    if request.method == 'POST'
        first_name = request.POST.get('first_name')
        # Do this for all the fields and validate them 
        # manually

使用forms.Form类

使用django.forms.Form类,您可以按如下方式定义表单

from django import forms

class ProfileForm(forms.Form):
    first_name = forms.CharField()
    last_name = forms.CharField()
    email = forms.EmailField()
    phone = forms.IntegerField()
    summary = forms.TextField()
    # Notice the code duplication here
    # we already have this defined in our models.

使用ModelForm类

from django import forms

class ProfileForm(forms.ModelForm)
    class Meta:
        model = models.Profile

因此,使用ModelForm类,您只需在4-5行代码中创建表单,并让django为您执行验证并显示表单错误。

现在回答你的问题,

  1. 有两种方法可以从表单类中排除特定字段。您可以使用exclude或定义fields
  2. 排除

    from django import forms
    
    class ProfileForm(forms.ModelForm)
        class Meta:
            model = models.Profile
            exclude = ('phone',)
    

    <强>字段

    from django import forms
    
    class ProfileForm(forms.ModelForm)
        class Meta:
            model = models.Profile
            fields = ('first_name', 'last_name', 'email', 'profile_summary')
    
    1. 我真的不明白你的意思original attributes are not supposed to be changed ???

    2. 使用ModelForm的好处

      • 少代码/无代码重复
      • 表单验证
      • 表单错误
      • 快速
      • 漂亮的代码

答案 5 :(得分:0)

你可以使用ModelForm并更改原始属性,但在大多数情况下Django做得很好!

Django表单非常有用,您可以执行高级验证,添加一些业务逻辑。好吧,django Forms呈现HTML,但即使你的Django项目不提供HTML,你可能仍在使用Django表单。

您的排除代码似乎没问题,但请注意使用Meta.excludes被视为安全风险。使用Meta.fields