1

假设我有以下模型 -

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)

通常,当items被“分配”给一个时,它们将具有与相关对象organization中最初记录的相同的值。Item但在某些情况下,分配给组织的项目可能会被覆盖value(因此是中间模型)。由于覆盖原始值很少发生(但确实会发生),我希望允许用户items从实例列表中简单地选择所需的值Item以将它们分配给组织实例。然后,用户可以选择在批量分配完成后覆盖单个值。

所以我有以下简单的 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) 保存Customizable与用户选择的项目相对应的实例,以及 (ii) 确保持久化的Customizable实例正确地取自由foreignkey 相关的实例所取value的对应实例。valueitem

我试图在一个视图中处理它(但我的思想被阻塞了) -

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))
4

3 回答 3

1

您将不得不使用save_m2m方法:

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)

            current_organization.save()

            form.save_m2m()

            return HttpResponseRedirect(reverse('redirect-someplace-else'))
    else:
        form = AssignItemsForm(instance=organization,)
    return render_to_response("assign_items.html", {"form": form,}, context_instance=RequestContext(request))

在这里查看更多信息:

http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

于 2010-10-05T10:24:54.130 回答
0

我会以不同的方式处理这个问题。您的 m2m 有一个中间模型。因此,我认为AssignItemsForm应该得到这种中介模型的支持。因此,我将其更改如下:

# forms.py
class AssignItemsForm(forms.ModelForm):
    value = forms.DecimalField(max_digits=12, decimal_places=2, required = False)

    class Meta:
        model = Customizable

接下来是允许用户选择不同值的问题。为了做到这一点,我value将模型的字段设为可选(required = False)。然后我检查用户是否提供了明确的值。如果不是,我假设将使用Item的默认值。为此,我将覆盖clean表单的方法:

    def clean(self):
        super(AssignItemsForm, self).clean()
        value, item = self.cleaned_data.get('value'), self.cleaned_data.get('item')
        if not value:
            value = item.value
        self.cleaned_data['value'] = value
        return self.cleaned_data

最后我在管理员中测试了这个。

# admin.py
from app.forms import AssignItemsForm

class CAdmin(admin.ModelAdmin):
    form = AssignItemsForm

admin.site.register(Item)
admin.site.register(Organization)
admin.site.register(Customizable, CAdmin)

这样您就可以继续使用,form.save()从而避免在视图中进行自定义操作。您必须稍微更改您的视图,以确保自动选择组织来分配项目。

# views.py
def assign_items(request, oid):
    organization = Organization.objects.get(id=oid)
    if request.method == 'POST':
        form = AssignItemsForm(data=request.POST.copy())
        form.save()
    else:
        form = AssignItemsForm(initial = {'organization': organization})
    ...
于 2010-10-05T10:16:34.633 回答
0

覆盖saveModelForm 的方法。这样,如果您需要在多个地方使用该表单,您就不必重复自己。

有关更多详细信息,请参阅此答案:

https://stackoverflow.com/a/40822731/2863603

于 2016-11-26T20:30:58.873 回答