吊坠到内联形式的多对多关系 [英] pendant to inline formsets for many-to-many relations
问题描述
遵循Kevin Dias在这篇文章,我尝试为两个相关模型生成一个表单。这似乎适用于一对多关系,但是我遇到使用多对多关系的问题。
这是一个用户角色的示例代码管理:
#models.py
pre>
从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))
这些设置导致错误消息
< 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 forManyToManyField
. 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屋!