Django - 使用表单集在不通过表的情况下建立 2 个模型之间的多对多关系
Posted
技术标签:
【中文标题】Django - 使用表单集在不通过表的情况下建立 2 个模型之间的多对多关系【英文标题】:Django - Establishing Many To Many Relationship Between 2 Models Without Through Table Using Formsets 【发布时间】:2012-11-26 08:23:59 【问题描述】:我有一个模型属性和产品,声明如下:
class Attribute(models.Model):
value = models.TextField()
owner = models.ForeignKey(User)
type = models.ForeignKey(AttributeType)
image = ImageField(upload_to='attributes', null=True, blank=True)
related_attribute = models.ManyToManyField('self', blank = True, null = True)
class BaseWorkspace(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(User)
attributes = models.ManyToManyField('Attribute', blank = True, null = True)
created = CreationDateTimeField()
modified = ModificationDateTimeField()
comments = models.ManyToManyField('Comment', blank = True, null = True )
sort_order = models.IntegerField(blank = True)
class Product(BaseWorkspace):
project = models.ForeignKey('Project', related_name='products')
如何使用表单集建立 m-m 关系?我尝试过这样的模型表单集工厂:
AttributeFormset = modelformset_factory(Attribute, form=AttributeForm)
在通用视图中使用此功能:
def form_valid(self, form):
f = form.instance
f.sort_order = Product.default_sort_order()
f.owner = self.request.user
f.project = get_object_or_404(Project, pk=self.kwargs['pk'])
context = self.get_context_data()
attribute_form = context['attribute_form']
if attribute_form.is_valid():
self.object = form.save()
attribute_form.instance = self.object
attribute_form.save()
return HttpResponseRedirect(reverse(self.get_success_url()))
else:
return self.render_to_response(self.get_context_data(form=form))
但我无法让它工作。有什么想法吗?
【问题讨论】:
你知道它在哪一行失败了吗?你能提供一个堆栈跟踪吗?可能是调用通用视图方法的顺序 - 在调用form_valid()
时实际上是否有一个 context['attribute_form']
变量?
所以您只想显示一个属性列表来分配产品?类似于 User 表单在 django admin 中显示 Groups 的方式?
我想在一个表单中创建附加到产品的属性。
所以您希望能够创建新属性,或添加现有属性?
你有没有得到这个工作?
【参考方案1】:
通过使用f = form.instance
,您可以访问原始实例。如果attribute_form 有效,则调用form
上的save 方法,而不是f
。您对f
所做的所有更改都将丢失。
查看saving-objects-in-the-formset 如何在保存表单集实例之前对其进行更新。
【讨论】:
【参考方案2】:试试这样的:
from django.forms.models import modelformset_factory
def my_view_function(request) :
# not sure where the product whose formset we are working on comes from
product = <whatever>
AttributeFormSet = modelformset_factory(Attribute)
if request.method == "POST" :
# POST bound formset
formset = AttributeFormSet(request.POST, queryset=Attribute.objects.filter(product=product))
# If the entire formset is valid
if formset.is_valid() :
for form in formset:
# Save each form in the set
b = form.save()
else :
#There was an error (add a message using the messages framework?)
pass
else :
# initial formset w/o post
formset = AttributeFormSet(queryset=Attribute.objects.filter(product=product))
...
很难给你更具体的答案,我认为如果你使用基于类的视图,我们将需要整个视图函数或视图类。
在您的模板中,像这样简单的事情(来自文档)应该可以做到。
<form method="post" action="">
formset.management_form
<table>
% for form in formset %
form
% endfor %
</table>
</form>
如果您需要能够在运行时使用 javascript 将表单添加到表单集,请查看:http://code.google.com/p/django-dynamic-formset/。我从未使用过它,但至少它看起来像是朝着正确方向迈出的一步。
编辑
首先从表单集中排除产品
AttributeFormSet = modelformset_factory(Attribute, exclude=('product',))
然后将表单处理块更改为在保存时不提交,并手动附加产品。
if formset.is_valid() :
for form in formset:
# get this form's instance
b = form.save(commit=False)
# attach product
b.product = product
# save the instance
b.save()
【讨论】:
如何将属性链接到产品? 我还回答了另一个类似的问题:***.com/a/13686524/884453以上是关于Django - 使用表单集在不通过表的情况下建立 2 个模型之间的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章
如何在不通过视图在所有页面中发送表单的情况下从 django 布局(如“base.html”)获取表单数据?
如何使用 Django、Ajax、jQuery 在不刷新页面的情况下提交表单?