首页 > 解决方案 > Django 识别基于类的视图并形成多个模型

问题描述

我正在进行我的第二个 Django 项目。在我的第一个项目中,我使用了所有通用视图,只有最基本的表单直接绑定到使用UpdateView.

在这个项目中,我正在尝试实现用户配置文件功能。我的自定义用户模型有一些额外的虚拟字段,以便我可以操作数据。我将其称为CustomUser模型。我还有一个UserAddress包含地址的模型,因为用户可以拥有多个地址。我已经尝试寻找其他问题,并且我得到了类似的问题,但总是缺少一些东西:

基于 Django 类的视图 - 具有两个模型表单的 UpdateView - 一个提交

将多个 ModelForms 与基于类的视图一起使用

单个 django ModelForm 中的多个模型?

Django:使用表单的一个模板中的多个模型

最后一两天我一直在寻找“Django 方式”来做我想做的事情,但没有运气。我最初的想法是我可以使用一个模板,将两个 ModelForm 封装在一个<form>标签中。然后视图将处理每个表单并更新CustomUser模型并创建或更新UserAddress模型。我已经想出了如何使用基本ViewCBV 将功能组合在一起,但我怀疑我正在复制很多我可能已经在 Django 中找到的功能。这是我的观点,我在其中手动处理表单实例化,并将context.

class UserDetailsView(View):

    def get(self, request):
        user = request.user
        user_basic = CustomUser.objects.get(pk=user.pk)
        basic_form = UserBasicForm(instance=user_basic)

        user_address = UserAddress.objects.get(user=user.pk)   
        billing_address_form = UserAddressForm(instance = user_address)

        context = {'basic_form':basic_form,'billing_address_form':billing_address_form}

        return render(request, 'mainapp/profile.html', context)

post在这一点上是一样的,因为我还没有完成实际的验证和保存。

class UserBasicForm(forms.ModelForm):

    class Meta(forms.ModelForm):
        model = CustomUser
        fields = (
            'username',
            'first_name',
            'last_name',
            )
        labels = {
            'username':'Username',
            'first_name':'First Name',
            'last_name':'Last Name',
            }

class UserAddressForm(forms.ModelForm):

    class Meta(forms.ModelForm):
        model = UserAddress
        fields = (
            'description',
            'addressee',
            'company',
            'address_1',
            'address_2',
            'city',
            'prov_state',
            'post_zip',
            'country',
            )
        labels = {
            'description':'Address Description',
            'addressee':'Addressee',
            'company':'Company Name',
            'address_1':'Address',
            'address_2':'Address 2',
            'city':'City',
            'prov_state':'Province or State',
            'post_zip':'Postal or Zip Code',
            'country':'Country',
            }

class CustomUser(AbstractUser):
    objects = CustomUserManager()

    def __str__(self):
        return self.email

class UserAddress(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)

    description = models.CharField(max_length = 256, default='Description')

    addressee = models.CharField(max_length = 256,)
    company = models.CharField(max_length = 256, default='Self')
    address_1 = models.CharField(max_length = 256,)
    address_2 = models.CharField(max_length = 256,)
    city = models.CharField(max_length = 256,)
    prov_state = models.CharField(max_length = 256,)
    post_zip = models.CharField(max_length = 256,)
    country = models.CharField(max_length = 256,)

    def __str__(self):
        return self.description

请对我放轻松,我会接受所提供的大多数建议。

编辑 在查看了其他一些 SO 问题和 Django 表单示例之后,看来最终答案可能不是 SO 材料。也就是说,我的观察是,对于 Django 内置 CBV,“最佳”基本视图是您可以最小化或简化您添加的代码的视图。在这种情况下,为我的项目使用 TemplateView 或 FormView 仅取决于我选择重写或覆盖哪些方法,为此,我仍然愿意接受建议。

标签: djangodjango-modelsdjango-formsdjango-templatesdjango-views

解决方案


我会做这样的事情(使用更好的形式):

class UserCreationMultiForm(MultiModelForm):
    form_classes = {
        'basic': UserBasicForm,
        'address': UserAddressForm,
    }


class UserDetailsView(View):
    template = "mainapp/profile.html"
    form_class = UserCreationMultiForm
    success_url = reverse_lazy('home')

    def form_valid(self, form):
        # Save the user first, because the profile needs a user before it
        # can be saved.
        user = form['basic'].save()
        address = form['address'].save(commit=False)
        address.user = user
        address.save()
        return redirect(self.get_success_url())

然后将模板中的表单重命名form.basicform.address


推荐阅读