NOT NULL constraint failed Django CreateView

不打扰是莪最后的温柔 提交于 2019-12-23 23:51:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!