Isha Jagadi
Isha Jagadi

Reputation: 95

Edited form not getting saved in django

I've fixed almost everything, the form opens and I can make the edits but as soon as I make the edits and click on save, this shows up:

enter image description here

I don't understand what's wrong. I did the same thing for my edit profile page and it worked perfectly there so I don't understand why it's not working here.

views.py:

class EditComplaint(UserPassesTestMixin, UpdateView):
   model = Complaint
   fields = ('reportnumber', 'eventdate', 'event_type', 'device_problem', 'manufacturer', 
  'product_code', 'brand_name', 'exemption', 'patient_problem', 'event_text', 'document')  
   template_name = 'newcomplaint.html'
   def form_valid(self, request):
       complaint = request.user.complaint
       form = ComplaintForm(instance=complaint)
       if request.method == 'POST':
          form = ComplaintForm(request.POST, request.FILES, instance=complaint)
          if form.is_valid():
             form.save()
       context = {'form': form}
       return render(request, 'newcomplaint.html', context)

   def test_func(self):
       complain = self.get_object()

       if self.request.user == complain.user:
           return True
       raise Http404(_('This complain does not exist'))

urls.py:

path('Complaint/<int:pk>/edit/', accounts.views.EditComplaint.as_view(), 
name='Complaint')

What seems to be wrong? I think I need to change something in my views because everything else seems to work well so I'm not including anything else. But i don't understand what needs to be changed

forms.py:

class DateInput(forms.DateInput):
input_type = 'date'

class ComplaintForm(ModelForm):
   class Meta:
       model = Complaint
       fields = '__all__'
       widgets = {
           'reportnumber': forms.TextInput(attrs={'placeholder': 'Report 
            number'}),
           'event_type': forms.TextInput(attrs={'placeholder': 'Event 
            type'}),
           'eventdate': DateInput(),
           'device_problem': forms.TextInput(attrs={'placeholder': 
           'Device Problem'}),
           'event_text': forms.Textarea(attrs={'style': 'height: 
            130px;width:760px'}),
            'manufacturer': forms.TextInput(attrs={'placeholder': 'Enter 
            Manufacturer Name'}),
           'product_code': forms.TextInput(attrs={'placeholder': 'Enter 
            Product Code'}),
           'brand_name': forms.TextInput(attrs={'placeholder': 'Enter 
            Brand Name'}),
           'exemption': forms.TextInput(attrs={'placeholder': 'Enter 
            Exemption'}),
           'patient_problem': forms.TextInput(attrs={'placeholder': 
           'Enter Patient Problem'}),
       }
    
   def clean(self):
       cleaned_data = super(ComplaintForm, self).clean()
       reportnumber = cleaned_data.get('reportnumber')
       event_text = cleaned_data.get('event_text')
       if not reportnumber and not event_text:
           raise forms.ValidationError('You have to write something!')
       return cleaned_data

models.py:

class Complaint(models.Model):
   user = models.ForeignKey(User, on_delete= models.CASCADE, null = 
   True, blank=True)
   id = models.AutoField(blank=False, primary_key=True)
   reportnumber = models.CharField(max_length=500 ,null = True, blank= 
   False)
   eventdate = models.DateField(null=True, blank=False)
   event_type = models.CharField(max_length=300, null=True, blank=True)
   device_problem = models.CharField(max_length=300, null=True, 
   blank=True)
   manufacturer = models.CharField(max_length=300, null=True, 
   blank=True)
   product_code = models.CharField(max_length=300, null=True, 
   blank=True)
   brand_name = models.CharField(max_length = 300, null=True, 
   blank=True)
   exemption = models.CharField(max_length=300, null=True, blank=True)
   patient_problem = models.CharField(max_length=500, null=True, 
   blank=True)
   event_text = models.TextField(null=True, blank= True)
   document = models.FileField(upload_to='static/documents', blank=True, 
   null=True)

   def __str__(self):
       return self.reportnumber

Upvotes: 1

Views: 47

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476534

form_valid has as second parameter the form that has been validated, not the request. You can access the request with self.request.

But you do not need to handle this yourself: the UpdateView logic has already logic in place to create and validate a POST request. It will run form_valid only if the form is valid, and by default save the form and redirect to the success url:

from django.contrib.auth.mixins import LoginRequiredMixin

class EditComplaint(LoginRequiredMixin, UpdateView):
    model = Complaint
    form_class = ComplaintForm
    success_url = 'url-to-redirect-to'

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            user=self.request.user
        )

I did the same thing for my edit profile page and it worked perfectly.

Class-based views normally implement most of the codeflow, so it is usually only a matter of specifying some items like the form_class, success_url, etc. Usually, if you need to write large blocks of logic it means you implement the logic that is already there in place, or the view is complicated and thus should be implemented by a function-based view, or another class-based view.

When the success url depends on the object, you can override get_success_url:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse

class EditComplaint(LoginRequiredMixin, UpdateView):
    model = Complaint
    form_class = ComplaintForm

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            user=self.request.user
        )

    def get_success_url(self):
        return reverse('Complaint', kwargs={'pk': self.object.pk})

You can automatically set the user by omitting the user field in the form, and set the user with:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse

class EditComplaint(LoginRequiredMixin, UpdateView):
    model = Complaint
    form_class = ComplaintForm

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            user=self.request.user
        )

    def get_success_url(self):
        return reverse('Complaint', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].

Upvotes: 1

Related Questions