Setup UpdateView in Django with a form that has the __init__ method configured

When I use UpdateView in Django with a form that has the init method configured to customize the ModelMultipleChoiceField querysets do not load the initial values of the instance?

Some context first, I find myself making an application that manages documents associated to subportals, for that each subportal has associated Service Groups and Dependencies.

I need that when a document is loaded, it can be categorized by Service Groups and Dependencies that are only associated to the subportal. I achieved this by using the init method in the forms.

The problem is when I need to update the document data, the initial values of the model do not appear.

I show the codes

Models.py

class ServiceGroup(models.Model):
    subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
    title = models.CharField(max_length=150, null=False, blank=False)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

class Dependence(models.Model):
    subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
    title = models.CharField(max_length=150, null=False, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title 

class SubportalDocument(models.Model):

    def get_upload_to(instance, filename):
        return '{}/documents/{}'.format(instance.subportal.title, filename)

    subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
    showcategory = models.OneToOneField(ShowCategory, null=True, blank=True, on_delete=models.CASCADE)
    title = models.CharField(max_length=150, null=False, blank=False)
    file = models.FileField(upload_to=get_upload_to, null=False, blank=False)
    review_date = models.DateField(null=False, blank=True)
    review_nro = models.IntegerField(null=False, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    dependences = models.ManyToManyField(Dependence, related_name='dependencesdoc', blank=True)
    servicegroups = models.ManyToManyField(ServiceGroup, related_name='servicegroupsdoc', blank=True)

    def __str__(self):
        return self.title

Forms.py

class SubportalDocumentForm(forms.ModelForm):
    class Meta:
        model = SubportalDocument
        exclude = ['subportal', 'created_at', 'status']
        labels = {
            'showcategory':'Categoría de Despliegue:',
            'title':'Nombre del Documento:',
            'file':'Cargar el archivo:',
            'review_nro':'Número de Revisión:',
            'review_date':'Fecha de Revisión:',
        }
        
        widgets = {
            'showcategory':forms.Select(attrs={'class':'form-select'}),
            'title':forms.TextInput(attrs={'class':'form-control'}),
            'file':forms.FileInput(attrs={'class':'form-control'}), 
            'review_nro': forms.NumberInput(attrs={'class':'form-control'}),
            'review_date': forms.DateInput(format=('%d/%m/%Y'),
                            attrs={'class':'form-control', 
                            'type':'date'}),                          
        }
    
    servicegroups = forms.ModelMultipleChoiceField(
        label='Grupos de Servicios:',
        queryset=None,
        widget=forms.CheckboxSelectMultiple,
    )
    
    dependences = forms.ModelMultipleChoiceField(
        label='Dependencias:',
        queryset=None,
        widget=forms.CheckboxSelectMultiple,
    )

    def __init__(self, *args, **kwargs):
        self.subportal = kwargs.pop('subportal')
        super(SubportalDocumentForm, self).__init__(*args, **kwargs)
        
        self.fields['servicegroups'].queryset = ServiceGroup.objects.filter(
            subportal=self.subportal)

        self.fields['dependences'].queryset = Dependence.objects.filter(
            subportal=self.subportal)

        self.fields['showcategory'].queryset = ShowCategory.objects.filter(
            subportal=self.subportal)


        self.fields['servicegroups'].widget.attrs.update({
            'class': 'form-check-input',
        })

        self.fields['dependences'].widget.attrs.update({
            'class': 'form-check-input',
        })

Views.py

class SubportalDocumentUpdateView(UpdateView):
    model = SubportalDocument
    form_class = SubportalDocumentForm
    template_name = 'portal_manager/create_document.html'

    def get_form_kwargs(self, *args, **kwargs):
        subportal_id = self.get_object().subportal_id
        subportal = get_object_or_404(Subportal, id=subportal_id)
        kwargs = {
            "subportal": subportal,
        }
        
        return kwargs

    def dispatch(self, request, *args, **kwargs):
        id = self.get_object().subportal_id
        self.get_form().fields['servicegroups'].queryset = ServiceGroup.objects.filter(subportal_id=id)
        self.get_form().fields['dependences'].queryset = Dependence.objects.filter(subportal_id=id)

            
        return super(SubportalDocumentUpdateView, self).dispatch(request, *args, **kwargs)

    def get_success_url(self):
        id = self.get_object().subportal_id
        return reverse_lazy('portal_manager:admin_subportal', kwargs={'id': id})

Urls.py

path('modificar-documento/<int:pk>', views.SubportalDocumentUpdateView.as_view(), name='update_document'),

The result I get is this image of the form without the initial values

Now, if I don't use the init method in the forms to filter the Service Groups and Dependencies by subportal, I get the initial values.

forms.py not init

class SubportalDocumentForm(forms.ModelForm):
    class Meta:
        model = SubportalDocument
        exclude = ['subportal', 'created_at', 'status']
        labels = {
            'showcategory':'Categoría de Despliegue:',
            'title':'Nombre del Documento:',
            'file':'Cargar el archivo:',
            'review_nro':'Número de Revisión:',
            'review_date':'Fecha de Revisión:',
        }
        
        widgets = {
            'showcategory':forms.Select(attrs={'class':'form-select'}),
            'title':forms.TextInput(attrs={'class':'form-control'}),
            'file':forms.FileInput(attrs={'class':'form-control'}), 
            'review_nro': forms.NumberInput(attrs={'class':'form-control'}),
            'review_date': forms.DateInput(format=('%d/%m/%Y'),
                            attrs={'class':'form-control', 
                            'type':'date'}),                          
        }
    
    servicegroups = forms.ModelMultipleChoiceField(
        label='Grupos de Servicios:',
        queryset=ServiceGroup.objects.all(),
        widget=forms.CheckboxSelectMultiple,
    )
    
    dependences = forms.ModelMultipleChoiceField(
        label='Dependencias:',
        queryset=Dependence.objects.all(),
        widget=forms.CheckboxSelectMultiple,
    )

Ajust Views.py

class SubportalDocumentUpdateView(UpdateView):
    model = SubportalDocument
    form_class = SubportalDocumentForm
    template_name = 'portal_manager/create_document.html'

    def dispatch(self, request, *args, **kwargs):
        id = self.get_object().subportal_id
        self.get_form().fields['servicegroups'].queryset = ServiceGroup.objects.filter(subportal_id=id)
        self.get_form().fields['dependences'].queryset = Dependence.objects.filter(subportal_id=id)

            
        return super(SubportalDocumentUpdateView, self).dispatch(request, *args, **kwargs)

    def get_success_url(self):
        id = self.get_object().subportal_id
        return reverse_lazy('portal_manager:admin_subportal', kwargs={'id': id})

Image with the expected result but filtering the Service Groups and Dependencies

If someone could help me or give me a clue of what is happening, I would appreciate it very much, I have been investigating for a long time and I can't get an answer.

Back to Top