Django UpdateView - 从多对多字段获取初始数据,并在保存表单时添加它们

时间:2017-10-15 19:16:04

标签: django

我使用基于Django类的通用视图。在我的models.py中,我有一个名为MyModel的模型,其中包含多对多字段m2m。我有多组用户可以编辑m2m字段。每组用户只能看到并将其部分添加到字段中 - 使用get_form设置他们在m2m字段中可以看到的内容。我遇到的问题是,当一个用户输入他的记录时,它将删除m2m字段中的初始记录。我需要以某种方式从m2m字段获取初始值保存它们,然后在提交表单时将它们添加到新的值。这是我的views.py:

class MyModelUpdate(UpdateView):
model = MyModel
fields = ['m2m']

def get_initial(self):
    return initials

def get_form(self, form_class=None):    
    form = super(MyModelUpdate, self).get_form(form_class)
    form.fields["m2m"].queryset = DiffModel.objects.filter(user = self.request.user)
    return form 

def form_valid(self, form):
    form.instance.m2m.add( ??? add the initial values) 
    return super(MyModelUpdate, self).form_valid(form)

def get_success_url(self):
    ...

2 个答案:

答案 0 :(得分:0)

经过几天的搜索和编码后,我找到了解决方案。

views.py:

from itertools import chain
from .forms import MyForm,

def MyModelUpdate(request, pk):
template_name = 'mytemplate.html'
instance = MyModel.objects.get(pk = pk)

instance_m2m = instance.m2m.exclude(user=request.user) 

if request.method == "GET":
    form = MyForm(instance=instance, user=request.user)
    return render(request, template_name, {'form':form})
else:
    form = MyForm(request.POST or None, instance=instance, user=request.user)
    if form.is_valid():
        post = form.save(commit=False)
        post.m2m = chain(form.cleaned_data['m2m'], instance_m2m)
        post.save()
        return redirect(...)

forms.py:

from django import forms
from .models import MyModel

class MyForm(forms.ModelForm):
class Meta:
    model = MyModel
    fields = ['m2m']

def __init__(self, *args, **kwargs):
    current_user = kwargs.pop('user')
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['m2m'].queryset = self.fields['m2m'].queryset.filter(user=current_user)

答案 1 :(得分:0)

我添加此答案是为了简化此类问题的解释,也是因为OP在他的解决方案中从UpdateView切换到基于函数的视图,这可能不是某些用户正在寻找的。< / p>

如果将UpdateView用于具有ManyToMany字段的模型,但由于只希望将此数据保留下来而没有向用户显示,则在保存表单后,所有m2m值都将被删除。 / p>

这显然是因为Django希望将此字段包含在表单中,并且不包含此字段与将其发送为空相同,因此,它告诉Django删除所有ManyToMany关系。

在这种简单情况下,您无需定义form_valid然后再检索原始值,依此类推,您只需要告诉Django不要使用此字段即可。

因此,如果您查看的话:

class ProjectFormView(generic.UpdateView):
    model = Project
    form_class = ProjectForm
    template_name = 'project.html'

在您的表单中,排除m2m字段:

class ProjectForm(forms.ModelForm):
    class Meta:
        model = Project
        fields = '__all__'
        exclude = ['many_to_many_field']