Skip to main content

在 Django 中同时处理多个表单的基于类的视图

项目描述

# django-shapeshifter

Django 中的一个常见问题是如何拥有一个视图,尤其是一个
可以同时显示和处理多个表单的基于类的视图。`django-shapeshifter` 旨在
使这个问题变得更简单。

现在,`django-shapeshifter` 可以
在单个视图中处理任何(理论上)数量的表单。
为多个标准表单或模型表单提供了一个视图类。要混合和匹配这些表单类型,您需要做一些
额外的工作。以下是如何使用该软件包:

## 安装

`$ pip install django-shapeshifter`

您不需要将 `shapeshifter` 添加到 `INSTALLED_APPS` 中。

## 用法

使用 `django-shapeshifter` 就像使用 Django 内置的基于类的
视图一样。您应该能够将提供的视图与您
已经在项目中使用的大多数 mixin 一起使用,例如 `LoginRequiredMixin`。某些 mixin 可能必须重构,例如在 `form_valid()` 方法上触发的 `SuccessMessageMixin`。

让我们看看使用几个标准形式的视图:

*interests/views.py*
```python
from django.urls import reverse_lazy

from shapeshifter.views import MultiFormView

from . 导入表单


类 InterestFormsView(MultiFormView):
form_classes = (forms.ContactForm, forms.InterestsForm, forms.GDPRForm)
template_name = 'interests/forms.html'
success_url = reverse_lazy('interests:thanks')
```

但是你需要在模板中做什么呢?视图的上下文将包含
一个新成员 `forms`,您可以对其进行迭代以显示每个表单:

*interests/templates/interests/forms.html*
``html
{% extends 'layout.html' %}

{%屏蔽内容 %}
<h3>请在下方填写您的兴趣!</h3>

<form method="POST">
{% csrf_token %}
{% for form in forms %}
{{ form.as_p }}
{% endfor % }
<input type="submit" value="Save" />
</form>
{% endblock content %}
```

这将生成一个包含所有三个表单的模板,
单个`<form>`标签。**所有表单必须一起提交。**
提交后,Django 将使用适当的提交数据填写每个表单,
验证它们,然后重定向到您的 `success_url`。

但是仅使用上面的代码,表单数据不会发生任何事情。要控制
它,您需要覆盖视图中的 `forms_valid` 方法。这
可能看起来像:

*interests/views.py*
```python
class InterestsFormView(MultiFormView):
...
def forms_valid(self):
forms = self.get_forms()
contact_form = forms['contactform']
interest_form =表格['interestsform']
gdpr = 表格['gdprform']

如果不是 gdpr.data['accept']:
messages.error("您必须接受 GDPR 条款。")
return HttpResponseRedirect(reverse_lazy('interests:forms'))
salesforce_client.send(zip(contact_form.data.items() ,
interest_form.data.items()))
return super().forms_valid()
```

上面的代码并不是一个完整的例子,但应该让您了解
如何处理表单数据。

### 模型表单呢?

上述所有代码也对模型表单有效,但有一个例外。对于
模型表单,您将扩展而不是扩展 `MultiFormView`
`MultiModelFormView`。类之间有两个主要区别,但
最重要的一个是 `forms_valid` 将在每个
表单上调用 `form.save()`。这是一个示例,允许用户在一个表单上编辑他们的 `User` `first_name` 和 `last_name`,以及他们的第一个 `Profile` `name`:

*my_app/models.py*
``python
from django.contrib。 auth.models 导入用户

类 Profile(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(User, related_name='profiles', on_delete=models.CASCADE)
```

*my_app/forms .py*
```python
from django.contrib.auth.models import User

from .models import Profile

class UserForm(forms.ModelForm):
元类:
模型=用户

字段=[
'first_name',
'last_name',
]

类ProfileForm(forms.ModelForm):
元类:
模型=组
字段=[
'name',
]

标签={
'name':'配置文件名称',
}
```

*my_app/views.py*
```python
from shapeshifter.views import MultiModelFormView
from shapeshifter.mixins import MultiSuccessMessageMixin

from .forms import UserForm,

ProfileForm class UserUpdateView(LoginRequiredMixin, MultiSuccessMessageMixin, MultiModelFormView):
form_classes = (UserForm, ProfileForm)
template_name = 'my_app/forms.html' success_url
= reverse_lazy('home')

def get_instances(self):
instances = {
'userform': self.request.user,
'profileform': profile_instance = Profile .objects.filter(
user=self.request.user,
).first(),
}

return instances
```

### 如果我想混合模型和标准形式怎么办?

没关系!您必须在视图中覆盖 `forms_valid` 以
处理每个表单,但其他一切都应该完全相同。

## API

`MultiFormView`(和继承的`MultiModelFormView`)扩展了Django的
`TemplateView`。
此外,它还为表单的实例化和处理添加了一些方法。可以覆盖所有这些以自定义
视图的行为。

下面是每个属性及其默认值,以及每个方法及其
签名和返回值。

### 属性

* `initial = {}` - 每个表单的初始值。应该是一个 `dict`
,格式如下:

```python
initial = {
'contactform': {
'name': 'Katherine Johnson'
}
}
```

其中 `ContactForm` 是表单的类名'重新提供初始
的值。

* `form_classes = None` - `Form`(或`ModelForm`,如果使用
`MultiModelFormView`)类的列表或元组。**不要实例化类,只需提供
名称**)。

* `success_url = None` -
正确填写表单后将用户重定向到的 URL。这可以是 URL 或 `reverse_lazy` 实例。

### 方法

* `get_form_classes(self)` - 返回视图的 `form_classes` 属性。
如果您需要动态设置应
包含在视图中的表单,请覆盖此方法。

* `get_forms(self) -> dict` - 使用 `get_form_kwargs` 中的 `kwargs` 实例化每个表单,
并将它们全部作为 dict 返回,其中键是标准化的
表单类名的版本。如果您需要更改
表单的实例化方式,请覆盖它。

* `get_form_class_name(self, form_class) -> str` - 将表单的类
名转换为小写字符串。`ContactForm` 将变为 `contactform`。您可以
覆盖它以为您的表单提供不同的标准化名称。

* `get_form_kwargs(self, form_class) -> dict` - 返回
用于创建表单的关键字参数的字典。为每个表单加上小写的类
名前缀,为表单提供任何“初始”参数,如果视图被
请求为“POST”或“PUT”,则为表单提供“数据”和“文件”
。对于`MultiModelFormView`,该方法还提供了`instance`
形式。重写此方法以添加或更改表单 kwargs。

* `validate_forms(self) -> bool` - 为每个表单调用 `form.is_valid()` 并
返回整个表单集的结果。
如果您的表单需要任何特殊的验证步骤,请覆盖此方法。

* `forms_valid(self)` - 如果所有表单都通过验证,则调用此方法。在
`MultiFormView` 中,此方法只是重定向到 `success_url`。对于基于
模型的版本,`MultiModelFormView`,此方法在每个表单上调用`form.save()`
,然后重定向。
重写此方法以更改表单全部有效时发生的情况。

* `forms_invalid(self)` - 如果任何表单未通过验证检查,则
方法被执行。默认情况下,它会重新渲染视图,显示
带有错误的表单。如果您需要
在并非所有表单都有效的情况下发生其他事情,您可以覆盖此方法。

### `MultiModelFormView` 的额外属性和方法

如上所述,`MultiModelFormView` 中的一些处理方式不同。

* `instances = {}` - 这个属性应该是一个以小写形式的类
名作为键的字典。这些值应该是用于表单的实例。

* `get_instances(self)` - 返回 `instances` 的值。如果
您需要动态获取表单的实例,请覆盖它。

### `MultiSuccessMessageMixin` 属性和方法

* `success_message = None` - 包含要通过 Django 消息框架添加的成功消息的字符串。

* `get_success_message(self)` - 返回成功消息的方法。默认为 self.success_message。

* `forms_valid(self)` - 添加成功消息后返回响应。

## 贡献

感谢您的关注、时间和精力!捐款总是
受欢迎的,我们会尽快审核(也就是说,我们都是
志愿者,有其他工作/职责,所以可能需要一段时间)。

请分叉此存储库并在“shapeshifter”包中进行更改。
请务必为任何功能更改添加测试。一旦所有测试通过,您
可以提交一个拉取请求,其中包含您的更改、更改背后的理由以及
维护人员需要采取的任何特殊步骤来测试您的更改或
复制您正在修复的错误。**请务必将您的名字添加到
以下贡献者列表中!**

### 贡献者

* Kenneth Love
* Lacey Williams Henschel
* Tim Allen

## 这个名字是什么?和版本?

原来的名字已经被占用了,所以必须找到一个新的名字。由于这个
包处理多种形式,所以 `shapeshifter` 是一个很好的双关语(shapeshifter
可以采用多种形式)。

版本号以发布日期为准。


项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

django-shapeshifter-18.9.23.tar.gz (13.5 kB 查看哈希)

已上传 source

内置分布

django_shapeshifter-18.9.23-py2.py3-none-any.whl (15.6 kB 查看哈希

已上传 py2 py3