简体   繁体   English

创建django表单

[英]creating django forms

I'm struggling to get my head round django forms.. I've been reading various documentation but just can't quite grasp the concepts. 我正在努力让我的头脑旋转django形式..我一直在阅读各种文档,但只是不能完全掌握这些概念。 I have got to grips with models, views and templates. 我必须掌握模型,视图和模板。 What I am trying to do is to create a form with various fields composing of dropdown lists and checkboxes which are populated by values in a database. 我要做的是创建一个包含下拉列表和复选框的各种字段的表单,这些复选框由数据库中的值填充。

I have a working app called vms. 我有一个名为vms的应用程序。 Using the models.py I have a built a simple schema that holds size and type. 使用models.py我有一个构建一个包含大小和类型的简单模式。 Size consists of 'small', 'medium' & 'large'. 大小由'小','中'和'大'组成。 Type is 'windows' & 'linux'. 类型是'windows'和'linux'。 Using the admin site, I can add an extra size, for example 'Extra Large'. 使用管理站点,我可以添加额外的大小,例如“超大”。

What I would like to do is create a form that has a drop down list of the vm sizes. 我想要做的是创建一个具有vm大小下拉列表的表单。 If an extra size gets added via the admin site, I would like that size to appear in the drop down list. 如果通过管理站点添加了额外的大小,我希望该大小显示在下拉列表中。

I would submit my attempts at the code, but actually am struggling with the concepts. 我会提交我对代码的尝试,但实际上我正在努力解决这些问题。 Can anyone help guide me in how to accomplish the above? 任何人都可以帮助指导我如何完成上述任务?

Thanks Oli 谢谢奥利

Forms are just a tool to simplify and speed-up (the development of) the process of fetching POST data from the request. 表单只是简化和加速(开发)从请求中获取POST数据的过程的工具。 A manual way would be to do request.POST.get('somefield') for all the fields there are in some HTML form. 手动方式是对某些HTML表单中的所有字段执行request.POST.get('somefield') But Django can do better than that... 但是Django可以做得更好......

In its essence, a Form class holds a number of Fields and performs these tasks: 从本质上讲,Form类包含许多Fields并执行以下任务:

  1. display HTML inputs, 显示HTML输入,
  2. collect and validate data when user submits it, 用户提交数据时收集和验证数据,
  3. if fields don't validate, return the values along with error messages to HTML, 如果字段未验证,则将值与错误消息一起返回到HTML,
  4. if all fields validate, provide form.cleaned_data dictionary as a convenient way to access these values in view. 如果所有字段都有效,请提供form.cleaned_data字典作为在视图中访问这些值的便捷方式。

With these values, I could then manually create a new instance of a MyModel and save it. 有了这些值,我就可以手动创建一个MyModel的新实例并保存它。 Of course, I would have to define a Field in the Form for every Field in MyModel model. 当然,我必须在MyModel模型中为每个Field定义一个Field。

This means that, basically, I could do something like this: 这意味着,基本上,我可以这样做:
(forgive me for not testing this code, so I can't vouch that it's 100% correct) (原谅我没有测试这段代码,所以我不能保证它是100%正确的)

models.py:

    class MyModel(models.Model):
        field1 = models.CharField(max_length=40, blank=False, null=False)
        field2 = models.CharField(max_length=60, blank=True, null=True)

forms.py:

    class FormForMyModel(forms.Form):
        form_field1 = forms.CharField(max_length=40, required=True)
        form_field2 = forms.CharField(max_length=60, required=False)

views.py:

    def create_a_my_model(request):
        if request.method == 'POST':
            form = FormForMyModel(request.POST)
            if form.is_valid():
                my_model = MyModel()
                my_model.field1 = form.cleaned_data.get('form_field1', 'default1')
                my_model.field2 = form.cleaned_data.get('form_field2', 'default2')
                my_model.save()
        else:        
            form = FormForMyModel()
        context_data = {'form': form}
        return HttpResponse('templtate.html', context_data)

(this could be written with a few lines of code less, but it's meant to be as clear as possible) (这可以用少量代码编写,但它意味着尽可能清晰)

Notice there are no relation between model Fields and form Fields! 请注意,模型字段和表单字段之间没有关系! We have to manually assign values to MyModel instance when creating it. 我们必须在创建MyModel实例时手动为其分配值。

The above example outlines generic form workflow. 上面的示例概述了通用表单工作流程。 It is often needed in complex situations, but not in such a simple one as is this example. 在复杂情况下经常需要它,但不是像这个例子那样简单。

For this example (and a LOT of real-world examples), Django can do better than that... 对于这个例子(以及很多真实世界的例子),Django可以做得更好......

You can notice two annoying issues in the above example: 您可以在上面的示例中发现两个恼人的问题:

  1. I have to define Fields on MyModel and Fields on FormForMyModel separately. 我不得不定义中的字段MyModel和字段FormForMyModel分开。 However, there is a lot of similarity between those two groups (types) of Fields, so that's kind of duplicate work. 但是,这两个字段组(类型)之间存在很多相似之处,因此这是一种重复的工作。 The similarity grows when adding labels, validators, etc. 添加标签,验证器等时,相似性会增加。
  2. creating of MyModel instance is a bit silly, having to assign all those values manually. 创建MyModel实例有点傻,必须手动分配所有这些值。

This is where a ModelForm comes in. 这就是ModelForm的用武之地。

These act basically just like a regular form (actually, they are extended from regular forms), but they can save me some of the work (the two issues I just outlined, of course :) ). 这些行为基本上就像一个常规形式(实际上,它们从常规形式扩展而来),但它们可以节省我的一些工作(我刚才概述的两个问题,当然:))。

So back to the two issues: 回到这两个问题:

  1. Instead of defining a form Field for each model Field, I simply define model = MyModel in the the Meta class. 我没有为每个模型字段定义一个表单Field,而只是在Meta类中定义了model = MyModel This instructs the Form to automatically generate form Fields from model Fields. 这指示表单从模型字段自动生成表单字段。

  2. Model forms have save method available. 模型表单具有可用的save方法。 This can be used to create instance of model in one line in the view, instead of manually assigning field-by-field. 这可用于在视图中的一行中创建模型实例,而不是手动分配逐个字段。

So, lets make the example above with a ModelForm : 所以,让我们用ModelForm制作上面的ModelForm

models.py:

    class MyModel(models.Model):
        field1 = models.CharField(max_length=40, blank=False, null=False)
        field2 = models.CharField(max_length=60, blank=True, null=True)

forms.py:

    class MyModelForm(forms.ModelForm):  # extending ModelForm, not Form as before
        class Meta:
            model = MyModel

views.py:

    def create_a_my_model(request):
        if request.method == 'POST':
            form = MyModelForm(request.POST)
            if form.is_valid():
                # save the model to database, directly from the form:
                my_model = form.save()  # reference to my_model is often not needed at all, a simple form.save() is ok
                # alternatively:
                # my_model = form.save(commit=False)  # create model, but don't save to database
                # my.model.something = whatever  # if I need to do something before saving it
                # my.model.save()
        else:        
            form = MyModelForm()
        context_data = {'form': form}
        return HttpResponse('templtate.html', context_data)

Hope this clears up the usage of Django forms a bit. 希望这能清除Django表单的用法。

Just one more note - it is perfectly ok to define form Fields on a ModelForm . 还有一个注意事项 - 在ModelForm上定义表单字段是完全可以的。 These will not be used in form.save() but can still be access with form.cleaned_data just as in a regular Form. 这些不会在form.save()使用,但仍可以使用form.cleaned_data访问,就像在常规表单中一样。

Have you tried working with ModelForms before? 您之前尝试过使用ModelForms吗? As I understand, you're looking to create a form based on the model you created right? 据我了解,您是否希望根据您创建的模型创建表单?

Lets say your model is called Temp. 让我们说你的模型叫做Temp。 You can create a form that correlates with this model (and your question) like this: 您可以创建一个与此模型(和您的问题)相关的表单,如下所示:

forms.py forms.py

from django.forms import ModelForm

class TempForm(ModelForm):
  class Meta:
    model = Temp

The ModelForm will automatically map the selections/choices from your model to a form version. ModelForm会自动将您的模型中的选择/选项映射到表单版本。

If you plan on using this in a template later, doing something like this will automatically create a drop-down menu with choices: 如果您打算稍后在模板中使用它,执行此类操作将自动创建一个包含以下选项的下拉菜单:

<form>
  <label for="id_size">Size</label>
  {{ form.size }}
</form>

Hope that answers your question! 希望这能回答你的问题!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM