15

我正在努力了解 django 表单。我一直在阅读各种文档,但不能完全掌握这些概念。我必须掌握模型、视图和模板。我要做的是创建一个表单,其中包含由数据库中的值填充的下拉列表和复选框的各种字段。

我有一个名为 vms 的工作应用程序。使用models.py,我构建了一个简单的模式来保存大小和类型。尺寸包括“小”、“中”和“大”。类型是“windows”和“linux”。使用管理站点,我可以添加额外的尺寸,例如“特大号”。

我想做的是创建一个包含 vm 大小下拉列表的表单。如果通过管理站点添加了额外的尺寸,我希望该尺寸出现在下拉列表中。

我会提交我对代码的尝试,但实际上我正在努力解决这些概念。谁能帮助指导我如何完成上述工作?

谢谢奥利

4

3 回答 3

36

表单只是一种工具,用于简化和加速(开发)从请求中获取 POST 数据的过程。一种手动方法是request.POST.get('somefield')对某些 HTML 表单中的所有字段进行处理。但是 Django 可以做得更好……

从本质上讲,Form 类包含许多字段并执行以下任务:

  1. 显示 HTML 输入,
  2. 在用户提交数据时收集和验证数据,
  3. 如果字段未验证,则将值与错误消息一起返回到 HTML,
  4. 如果所有字段都有效,则提供form.cleaned_data字典作为访问视图中这些值的便捷方式。

使用这些值,我可以手动创建 a 的新实例MyModel并保存它。当然,我必须在表单中为 MyModel 模型中的每个字段定义一个字段。

这意味着,基本上,我可以做这样的事情:(请
原谅我没有测试这段代码,所以我不能保证它是 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)

(这可以用更少的几行代码编写,但它的意思是尽可能清晰)

请注意,模型字段和表单字段之间没有关系!创建 MyModel 实例时,我们必须手动为其赋值。

上面的示例概述了通用表单工作流程。在复杂的情况下通常需要它,但在这个例子这样简单的情况下却不需要。

对于这个例子(以及很多现实世界的例子),Django 可以做得比这更好......

您可以在上面的示例中注意到两个烦人的问题:

  1. 我必须分别定义 Fields onMyModel和 Fields on FormForMyModel。然而,这两组(类型)的字段之间有很多相似之处,所以这是一种重复的工作。添加标签、验证器等时,相似性会增加。
  2. 创建MyModel实例有点傻,必须手动分配所有这些值。

这就是ModelForm的用武之地。

这些行为基本上就像一个常规形式(实际上,它们从常规形式扩展而来的),但它们可以为我节省一些工作(当然是我刚刚概述的两个问题 :))。

那么回到两个问题:

  1. 我没有为每个模型字段定义一个表单字段,而是简单地model = MyModelMeta类中定义。这指示表单从模型字段自动生成表单字段。

  2. 模型表格有save可用的方法。这可用于在视图中的一行中创建模型实例,而不是逐个字段手动分配。

所以,让我们用一个来做上面的例子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)

希望这可以稍微清除 Django 表单的使用。

还有一点需要注意 - 在ModelForm. 这些将不会被使用,form.save()但仍然可以form.cleaned_data像在常规表单中一样访问。

于 2012-08-12T18:19:59.017 回答
2

您之前尝试过使用 ModelForms 吗?据我了解,您希望根据您创建的模型创建一个表单,对吗?

假设您的模型称为 Temp。您可以创建一个与此模型(和您的问题)相关的表单,如下所示:

表格.py

from django.forms import ModelForm

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

ModelForm 会自动将模型中的选择/选择映射到表单版本。

如果您打算稍后在模板中使用它,执行以下操作将自动创建一个带有选项的下拉菜单:

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

希望这能回答你的问题!

于 2012-08-12T17:21:23.293 回答
0

只需在您的模型表单中使用 CharField,如下所示:

SIZES_CHOICES = (
    ('size1', 'M'),
    ('size2', 'L'),
)
size = models.CharField(max_length=100, choices=SIZES_CHOICES, default=size1)

在上面的代码中,size1 是将作为名称“size1”存储在您的数据库中的值,在下拉菜单中,将有一个选项是右侧的“M”。您可以提及任何名称这些选项。

于 2020-07-24T05:38:02.593 回答