【问题标题】:Django UpdateView - get initial data from many-to-many field and add them when saving formDjango UpdateView - 从多对多字段获取初始数据并在保存表单时添加它们
【发布时间】:2018-03-27 07:22:03
【问题描述】:

我正在使用基于 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):
        ...

【问题讨论】:

    标签: django django-generic-views


    【解决方案1】:

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

    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)
    

    【讨论】:

      【解决方案2】:

      我添加这个答案是为了提供对此类问题的简化解释,并且还因为 OP 在他的解决方案中从 UpdateView 切换到基于函数的视图,这可能不是某些用户想要的。

      如果您将 UpdateView 用于具有 ManyToMany 字段的模型,但您没有将其显示给用户,因为您只想保留这些数据,在保存表单后,所有 m2m 值都将被删除。

      这显然是因为 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']
      

      【讨论】:

        猜你喜欢
        • 2021-09-25
        • 2018-09-30
        • 1970-01-01
        • 2015-11-08
        • 1970-01-01
        • 1970-01-01
        • 2014-02-01
        • 1970-01-01
        • 2014-02-26
        相关资源
        最近更新 更多