吊坠到内联形式的多对多关系 [英] pendant to inline formsets for many-to-many relations

查看:135
本文介绍了吊坠到内联形式的多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

遵循Kevin Dias在这篇文章,我尝试为两个相关模型生成一个表单。这似乎适用于一对多关系,但是我遇到使用多对多关系的问题。



这是一个用户角色的示例代码管理:

 #models.py 
从django.db导入模型

类角色(models.Model):#为每个角色可以有多个用户
role_name = models.CharField(max_length = 20)

类用户(models.Model):#每个用户都可以多个角色
name = models.CharField(max_length = 20)
role = models.ManyToManyField(Role,through ='UserRole')

class UserRole(models.Model) #表存储哪个用户有哪些角色
role = models.ForeignKey(Role)
user = models.ForeignKey(User)

#forms.py
from import django.forms import modelForm
from django.forms.models import inlineformset_factory

from rightmanagement.models import Role,User

class UserForm(ModelForm):
类Meta:
model =用户

RoleFormSet = inlineformset_factory(User,Role)#这可能是导致问题的行

#views.py
from django.http import HttpResponseRedirect
from rightmanagement.models import User
from rightmanagement.forms import RoleFormSet,UserForm

#从django.views.generic导入CreateView
class UserCreate(CreateView)创建视图

模型= User
form_class = UserForm

def get(self,request,* args,** kwargs):

处理GET请求并实例化空白版本形式为
及其内联表单。

self.object =无
form_class = self.get_form_class()
form = self.get_form(form_class)
role_form = RoleFormSet()
return self.render_to_response(
self.get_context_data(form = form,
role_form = role_form))

def post(self,request,* args,** kwargs) :

处理POST请求,实例化表单实例及其内联
表单与传递的POST变量,然后检查
有效性。

self.object =无
form_class = self.get_form_class()
form = self.get_form(form_class)
role_form = RoleFormSet(self.request
if(form.is_valid()and role_form.is_valid()):
return self.form_valid(form,role_form)
else:
return self.form_invalid form,role_form)

def form_valid(self,form,role_form):

如果所有表单都有效,则调用。创建配方实例以及
相关的成分和说明,然后重定向到
成功页面。

self.object = form.save()
role_form.instance = self.object
role_form.save()
返回HttpResponseRedirect(self.get_success_url ())

def form_invalid(self,form,role_form):

如果表单无效,则调用。使用
数据填充的表单和错误重新呈现上下文数据。

return self.render_to_response(
self.get_context_data(form = form,
role_form = role_form))
pre>

这些设置导致错误消息< class'rightmanagement.models.Role'>没有ForeignKey到< class'rightmanagement .models.User'>



做了一些研究,我发现这一点: Django inlineformset_factory和ManyToMany字段。似乎内联表单仅适用于 ForeignKey 但不是 ManyToManyField 。另外文档可以这样解释。



然而,我认为在特定情况下是外键而不是多对多许多关系没有任何意义。 Django的内置内联格式的吊坠如何看起来像多对多的关系?目的是构建一个表单,允许将用户分配给已经存在的角色或创建新角色,并将其分配给用户(如果尚不存在)。

解决方案

您可能知道,您无法使用内联表单来编辑多对多关系。但是,您可以编辑通过模型。因此,对于您的内联表单,您只需要将模型设置为直通模型,如下所示:

  RoleFormSet = inlineformset_factory(UserRole ,User.role.though)


Following Kevin Dias instructions in this article, I try to generate one form for two related models. This seems to work for one-to-many relations, however I run into problems using many-to-many relations.

Here is some example code for a user-role management:

#models.py
from django.db import models

class Role(models.Model): # for each role there can be multiple users
    role_name=models.CharField(max_length=20)

class User(models.Model): # each user can have multiple roles
    name=models.CharField(max_length=20)
    role=models.ManyToManyField(Role, through='UserRole')

class UserRole(models.Model): # table to store which user has which roles
    role=models.ForeignKey(Role)
    user=models.ForeignKey(User)

# forms.py
from django.forms import ModelForm
from django.forms.models import inlineformset_factory

from rightmanagement.models import Role, User

class UserForm(ModelForm):
    class Meta:
        model = User

RoleFormSet = inlineformset_factory(User, Role) # this is probably the line that causes the problem

# views.py
from django.http import HttpResponseRedirect
from rightmanagement.models import User
from rightmanagement.forms import RoleFormSet, UserForm

# Create view
from django.views.generic import CreateView
class UserCreate(CreateView):
    model = User
    form_class = UserForm

def get(self, request, *args, **kwargs):
        """
        Handles GET requests and instantiates blank versions of the form
        and its inline formsets.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        role_form = RoleFormSet()
        return self.render_to_response(
            self.get_context_data(form=form,
                                  role_form=role_form))

def post(self, request, *args, **kwargs):
        """
        Handles POST requests, instantiating a form instance and its inline
        formsets with the passed POST variables and then checking them for
        validity.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        role_form = RoleFormSet(self.request.POST)
        if (form.is_valid() and role_form.is_valid()):
            return self.form_valid(form, role_form)
        else:
            return self.form_invalid(form, role_form)

def form_valid(self, form, role_form):
        """
        Called if all forms are valid. Creates a Recipe instance along with
        associated Ingredients and Instructions and then redirects to a
        success page.
        """
        self.object = form.save()
        role_form.instance = self.object
        role_form.save()
        return HttpResponseRedirect(self.get_success_url())

def form_invalid(self, form, role_form):
        """
        Called if a form is invalid. Re-renders the context data with the
        data-filled forms and errors.
        """
        return self.render_to_response(
            self.get_context_data(form=form,
                                  role_form=role_form))

These settings lead to the error message <class 'rightmanagement.models.Role'> has no ForeignKey to <class 'rightmanagement.models.User'>.

Doing some research I found this: Django inlineformset_factory and ManyToMany fields. It seems like inline formsets are only for ForeignKey but not for ManyToManyField. Also the docs can be interpreted like this.

However, I think in the particular case a foreign key instead of a many-to-many relation wouldn't make any sense. How would a pendant to Django's built-in inline formset look like for many-to-many relations? The aim would be to build a form that allows to either assign the user to roles that already exist or create new roles and assign them to the user if they do not exist yet.

解决方案

As you're probably aware, you can't edit many-to-many relationships with inline formsets. You can, however, edit the through model. So for your inline formset, you just need to set the model to the through model, like so:

RoleFormSet = inlineformset_factory(UserRole, User.role.though)

这篇关于吊坠到内联形式的多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆