问题
I would like to accomplish two goals on this project. First, I would like to save the logged-in user as the reviewer. Second, I want to pass the lawyer value from the foreignkey into the review form. (This way, the user can review click on a review link on the lawyer's detail page and review that lawyer and no one else.)
I keep getting on the first goal, with this error.
error
IntegrityError at /lawyers/karlyn-rosemarie-hylton/review/
NOT NULL constraint failed: lawyers_review.reviewer_id
Can someone please explain what I am doing wrong and how to fix it?
The second goal seems to be very related to the first goal. I am not getting any errors for it. But I want to make sure that I am doing it right. However, I won't be able to tell until I get passed the first error.
Any help getting unstuck is much appreciated.
models.py
from django.db import models
from django.urls import reverse
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Lawyer(models.Model):
name = models.CharField(max_length=55,
default='')
picture = models.ImageField(upload_to='media/lawyers/pictures',
default='')
slug = models.SlugField()
def average_rating(self):
all_ratings = map(lambda x: x.rating, self.review_set.all())
return np.mean(all_ratings)
def save(self, *args, **kwargs):
self.slug = (slugify(self.name))
super(Lawyer, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('lawyers:detail', kwargs={'slug': self.slug})
def __str__(self):
return self.name
class Review(models.Model):
RATING_CHOICES = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5'),
)
lawyer = models.ForeignKey(Lawyer,
null=True)
created = models.DateTimeField(auto_now_add=True)
reviewer = models.ForeignKey(User)
title = models.CharField(max_length=55,
default='')
comment = models.TextField()
rating = models.IntegerField(choices=RATING_CHOICES)
def __str__(self):
return self.lawyer.name
views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import (CreateView,
DetailView,
ListView)
from django.contrib.auth.models import User
from .models import Lawyer, Review
class AddLawyerView(CreateView):
model = Lawyer
fields = ['name', 'picture']
def post_valid(self, form):
lawyer = form.save(Commit=False)
lawyer.picture = form.cleaned_data['picture']
return super(AddLawyerView, self).form_valid(form)
class LawyerDetail(DetailView):
model = Lawyer
class LawyerList(ListView):
model = Lawyer
class AddReviewView(CreateView):
model = Review
fields = ['rating', 'title', 'comment']
def post_valid(self, form):
review = form.save(Commit=False)
review.lawyer = get_object_or_404(Lawyer,
slug=self.kwargs.get('slug'))
review.reviewer = User.objects.get(user=self.request.user)
return super(AddReview, self).form_valid(form)
urls.py
from django.conf.urls import url
from .views import (AddLawyerView,
LawyerDetail,
LawyerList,
AddReviewView)
urlpatterns = [
url(r'^add-lawyer',
AddLawyerView.as_view(),
name = 'add-lawyer'),
url(r'^(?P<slug>[\w-]+)/$',
LawyerDetail.as_view(),
name = 'detail'),
url(r'^$',
LawyerList.as_view(),
name = 'list'),
url(r'^(?P<slug>[\w-]+)/review/$',
AddReviewView.as_view(),
name = 'add-review'),
]
Using the feedback from @Alasdair and @Sachin Kukreja , I went back and made some correction. I changed "Commit" to "commit" and "post_valid" to "form_valid". I also made one minor tweak to simplify the view. The corrected and working AddReviewView is below. The one with mistakes is above.
Thank you all!
Working View:
class AddReviewView(CreateView):
model = Review
fields = ['rating', 'title', 'comment']
def form_valid(self, form):
review = form.save(commit=False)
review.lawyer = get_object_or_404(Lawyer,
slug=self.kwargs.get('slug'))
review.reviewer = self.request.user
return super(AddReviewView, self).form_valid(form)
回答1:
You have a typo there, you are overriding form_valid
but you have written post_valid
.
def form_valid(self, form):
review = form.save(Commit=False)
review.lawyer = get_object_or_404(Lawyer,
slug=self.kwargs.get('slug'))
review.reviewer = User.objects.get(user=self.request.user)
# save and return HttpResponse
review.save()
return HttpResponseRedirect(self.get_success_url())
But, the super
call will still call the parent class' form_valid
which will still raise the error. I think you can save the review in this overriden method and return what the base class returns i.e. return HttpResponseRedirect(self.get_success_url())
Ref: form_valid in FormMixin class, form_valid in ModelFormMixin class
来源:https://stackoverflow.com/questions/45654433/not-null-constraint-failed-django-createview