djangodjango-generic-views

Django UpdateView - get initial data from many-to-many field and add them when saving form


I'm using Django class based generic view. In my models.py I have a model called MyModel with many-to-many field called m2m. I have multiple groups of users they can edit the m2m field. Each group of users can only see and add their portion to the field - using get_form to set what they can see in the m2m field. The problem I'm having is that when one user enter his record it will delete the initial records in the m2m field. I need to somehow get the initial values from the m2m field save them and then add them to the new ones when the form is submitted. Here is my 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):
        ...

Solution

  • after few days of searching and coding I've found a solution.

    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)