Django - 使用表单和视图中的中间表处理多对多的好方法是什么
假设我有以下模型 -
class Item(models.Model):
name = models.CharField(max_length=150)
value = models.DecimalField(max_digits=12,decimal_places=2)
class Organization(models.Model):
name = models.CharField(max_length=150)
items = models.ManyToManyField(Item, through='Customizable')
class Customizable(models.Model):
organization = models.ForeignKey(Organization)
item = models.ForeignKey (Item)
value = models.DecimalField(max_digits=12,decimal_places=2)
通常,当项目
被“分配”给组织
时,它们将具有与相关中最初记录的相同值>Item
对象。但在某些情况下,分配给组织的项目可能具有被覆盖的值
(因此出现了中介模型)。由于覆盖原始值很少发生(但确实发生),我希望允许用户只需从 Item
实例列表中选择所需的 items
即可将它们分配给组织实例。批量分配完成后,用户可以选择覆盖各个值。
所以我有以下简单的 ModelForm -
class AssignItemsForm(forms.ModelForm):
items = forms.ModelMultipleChoiceField(queryset=Item.objects.all(),required=False,widget=forms.CheckboxSelectMultiple)
class Meta:
model = Organization
exclude = ('name',)
现在由于我有一个 through
模型,简单的 form.save() 将不起作用。我需要 (i) 保存与用户选择的项目相对应的Customized
实例,并且 (ii) 确保持久化的可自定义实例具有从item
获取的相应值
中获取的正确值
通过foreignkey关联的实例。
我试图在视图中处理它(但我的思想被阻止了)-
def assign_items(request, oid):
organization = Organization.objects.get(id=oid)
if request.method == 'POST':
form = AssignItemsForm(data=request.POST, instance=organization)
if form.is_valid():
current_organization = form.save(commit=False)
#
#placeholder to save Customizable instances here
#
return HttpResponseRedirect(reverse('redirect-someplace-else'))
else:
form = AssignItemsForm(instance=organization,)
return render_to_response("assign_items.html", {"form": form,}, context_instance=RequestContext(request))
Suppose I have the following models -
class Item(models.Model):
name = models.CharField(max_length=150)
value = models.DecimalField(max_digits=12,decimal_places=2)
class Organization(models.Model):
name = models.CharField(max_length=150)
items = models.ManyToManyField(Item, through='Customizable')
class Customizable(models.Model):
organization = models.ForeignKey(Organization)
item = models.ForeignKey (Item)
value = models.DecimalField(max_digits=12,decimal_places=2)
More often than not, when items
are "assigned" to an organization
, they will have the same value as originally recorded in the related Item
object. But in certain cases, an item assigned to an organization may have an overridden value
(hence the intermediary model). Since overriding the original value happens rarely (but it does happen) I want to allow the user to simply select desired items
from a list of Item
instances to assign them to an organization instance. The user will then have the option of overriding individual values later after bulk assignment is complete.
So I have the following simple ModelForm -
class AssignItemsForm(forms.ModelForm):
items = forms.ModelMultipleChoiceField(queryset=Item.objects.all(),required=False,widget=forms.CheckboxSelectMultiple)
class Meta:
model = Organization
exclude = ('name',)
Now since I have a through
model, a simple form.save() won't work. I need to
(i) save Customizable
instances corresponding to the items selected by the user and
(ii) make sure the persisted Customizable
instances have the proper value
taken from the corresponding value
taken from the item
instance related by foreignkey .
I am trying to handle it in a view (but my mind is blocked) -
def assign_items(request, oid):
organization = Organization.objects.get(id=oid)
if request.method == 'POST':
form = AssignItemsForm(data=request.POST, instance=organization)
if form.is_valid():
current_organization = form.save(commit=False)
#
#placeholder to save Customizable instances here
#
return HttpResponseRedirect(reverse('redirect-someplace-else'))
else:
form = AssignItemsForm(instance=organization,)
return render_to_response("assign_items.html", {"form": form,}, context_instance=RequestContext(request))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您必须使用
save_m2m
方法:在此处查看更多信息:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method
You would have to use
save_m2m
method:Look here for more info:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method
我会以不同的方式处理这个问题。您有一个 M2M 中介模型。因此,我认为
AssignItemsForm
应该由这个中介模型支持。因此,我将其更改如下:接下来,是允许用户选择不同值的问题。为此,我将模型的
value
字段设为可选 (required = False
)。然后我检查用户是否提供了明确的值。如果不是,我假设将使用Item
的默认值。为此,我重写了表单的clean
方法:最后我在管理中测试了它。
这样您就可以继续使用
form.save()
从而避免在视图中进行自定义操作。您必须稍微更改一下视图,以确保自动选择组织来分配项目。I'd approach this in a different way. You have an intermediary model for your m2m. Hence I'd argue that
AssignItemsForm
should be backed by this intermediary model. Therefore I'd change it as follows:Next, the matter of allowing users to choose a different value. In order to do this I've made the
value
field of the model optional (required = False
). I then check if the user has supplied an explicit value. If not I assume that theItem
's default value is to be used. For this I am overriding theclean
method of the form:And finally I tested this in admin.
This way you can continue to use
form.save()
thereby avoiding custom manipulation in the view. You'll have to change your view a bit to make sure that the organization is auto selected for assigning items.重写 ModelForm 的
save
方法。这样,如果您需要在多个地方使用该表单,则无需重复操作。有关更多详细信息,请参阅此答案:
https://stackoverflow.com/a/40822731/2863603
Override the
save
method of the ModelForm. This way you won't have to repeat yourself if you need to use the form in multiple places.See this answer for more details:
https://stackoverflow.com/a/40822731/2863603