Reputation: 95
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:
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
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