Django inlineformset_factory в UpdateView данные набора форм не обновляются - PullRequest
0 голосов
/ 22 января 2020

Я использую представления на основе классов в моем проекте. В CreateView работает несколько форм (inlineformset_factory), и я успешно сохранил данные обеих форм.

Но когда я пытался редактировать свой набор форм, используя представления на основе классов (UpdateView), только первые данные формы успешно обновляются.

Но данные набора форм (inlineformset_factory) не обновляются. Пожалуйста, помогите выяснить проблему в моем (UpdateView).

views.py

class MaterialRequest_update(UpdateView):
    template_name = 'inventory/edit_files/material_request.html'
    form_class = MaterialRequestForm
    model = MaterialRequest
    success_url = reverse_lazy('inventory-material-request')

    def get_queryset(self):
        id = self.kwargs['pk']
        return MaterialRequest.objects.filter(pk=id)

    def get_context_data(self, **kwargs):
        context = super(MaterialRequest_update, self).get_context_data(**kwargs)
        if self.request.POST:
            context['form'] = MaterialRequestForm(self.request.POST, instance=self.object)
            context['formset'] = MaterialRequestFormset(
                self.request.POST, instance=self.object)
        else:
            context['form'] = MaterialRequestForm(instance=self.object)
            context['formset'] = MaterialRequestFormset(instance=self.object)

        return context


    def form_valid(self, form):
        context = self.get_context_data()
        formset = context['formset']

        if form.is_valid() and formset.is_valid():
            form.save()
            formset.save()

        return super().form_valid(form)

forms.py

# Main Form

    class MaterialRequestForm(forms.ModelForm):
        class Meta:
            model = MaterialRequest
            fields = [
                'location', 'job', 'task_num', 'supervisor', 'entry_serialno', 'date', 
                'department', 'ref', 'other_info', 'attachment'
            ]
            labels = {
                'location':'Location', 'job':'Job', 'task_num':'Estimate No', 
                'supervisor':'Supervisor', 'entry_serialno':'Entery No', 'date':'Date', 
                'department':'Department', 'ref':'Reference', 'other_info':'Other Info', 
                'attachment':'Attachment File'
            }
            widgets = {
                'location': forms.Select(attrs={'class':'form-control select-search'}), 
                'job': forms.Select(attrs={'class':'form-control select-search'}), 
                'task_num': forms.TextInput(attrs={'class':'form-control'}), 
                'supervisor': forms.TextInput(attrs={'class':'form-control'}), 
                'entry_serialno': forms.TextInput(attrs={'class':'form-control'}), 
                'date': forms.DateInput(attrs={'class':'form-control pickadate'}), 
                'department': forms.Select(attrs={'class':'form-control select-search'}), 
                'ref': forms.TextInput(attrs={'class':'form-control'}), 
                'other_info': forms.Textarea(attrs={'class':'form-control', 'rows':3}),
                'attachment': forms.ClearableFileInput(attrs={'class':'form-control'})
            }

            def clean(self):
                fields = self.cleaned_data


    # Formset start from here

    MaterialRequestFormset = inlineformset_factory(
        MaterialRequest, 
        MaterialRequestProducts,
        form = MaterialRequestForm,
        extra=1,
        can_delete=True,
        max_num=200,
        validate_max=200,
        fields=('product', 'quantity', 'unit', 'stock'),
        widgets={
            'product': forms.Select(attrs={'class':'form-control select-search'}), 
            'quantity': forms.NumberInput(attrs={'class':'form-control'}), 
            'unit': forms.Select(attrs={'class':'form-control select-search'}), 
            'stock': forms.NumberInput(attrs={'class':'form-control'}),
        }
    )

models.py

class MaterialRequest(models.Model):
        location = models.ForeignKey(to='administrator.Location', related_name='materialreq_location', on_delete=models.CASCADE)
        job = models.ForeignKey(to='master.Job', related_name='materialreq_job', on_delete=models.CASCADE)
        task_num = models.CharField(max_length=100, blank=True) 
        supervisor = models.CharField(max_length=100, blank=True) 
        entry_serialno = models.CharField(max_length=100, blank=True) 
        date = models.CharField(max_length=100, blank=True)
        department = models.ForeignKey('master.Department', related_name='department', on_delete=models.CASCADE, null=True)
        ref = models.CharField(max_length=100, blank=True)
        other_info = models.TextField(blank=True)
        attachment = models.FileField(upload_to='files/inventory/material_request/%Y/%m/%d/', null=True, blank=True)
        added_by = models.CharField(max_length=200, default='Azhar Saleem')
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)

         objects = models.Manager

         def __str__(self):
              return self.job

          class Meta:
              db_table = 'inventory_material_request'
              verbose_name = 'Material_Request'
              verbose_name_plural = 'Material_Requests'



    #Formset model start from here...

class MaterialRequestProducts(models.Model):
        material_request = models.ForeignKey(MaterialRequest, related_name='materialrequest', on_delete=models.CASCADE)
        product = models.ForeignKey(Products, related_name='products', on_delete=models.CASCADE)
        quantity = models.BigIntegerField()
        unit = models.ForeignKey('master.UnitOfMeasurements', related_name='unit', on_delete=models.CASCADE)
        stock = models.DecimalField(max_digits=999, decimal_places=2)
        add_by = models.CharField(max_length=100, default='Azhar Saleem')
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)

        objects = models.Manager

        def __str__(self):
           return self.product

        class Meta:
           db_table = 'inventory_material_request_products'
           verbose_name = 'Material_Request_Product'
           verbose_name_plural = 'Material_Request_Products'

1 Ответ

0 голосов
/ 22 января 2020

Попробуйте это.

class MaterialRequest_update(UpdateView):
    model = MaterialRequest
    form_class = MaterialRequestForm
    template_name = 'inventory/edit_files/material_request.html'
    slug_field = 'uid'
    slug_url_kwarg = 'uuid'
    success_message = 'Data saved successfully'

    def get_success_url(self):
        return reverse_lazy('inventory-material-request')

    def get_context_data(self, **kwargs):
        context = super(MaterialRequest_update, self).get_context_data(**kwargs)
        if self.request.POST:
            context['form'] = MaterialRequestForm(self.request.POST, instance=self.object)
            context['formset'] = MaterialRequestFormset(self.request.POST,
                                                        instance=self.object)
        else:
            context['form'] = MaterialRequestForm(instance=self.object)
            context['formset'] = MaterialRequestFormset(instance=self.object)
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        formset = MaterialRequestFormset(self.request.POST, instance=self.object)
        if (form.is_valid() and formset.is_valid()):
            return self.form_valid(form, formset)
        else:
            return self.form_invalid(form, formset)

    def form_valid(self, form, formset):
        self.object = form.save()
        formset.instance = self.object
        formset.save()
        return HttpResponseRedirect(self.get_success_url())

    def form_invalid(self, form, formset):
        return self.render_to_response(self.get_context_data(form=form, formset=formset))
...