Skip to main content
 首页 » 编程设计

python之NOT NULL 约束失败 Django CreateView

2024年10月01日32kerrycode

我想在这个项目上完成两个目标。首先,我想将登录用户保存为审阅者。其次,我想将外键中的律师值传递到审核表中。 (通过这种方式,用户可以点击律师详细信息页面上的评论链接来评论该律师,而不是其他人。)

我一直朝着第一个目标前进,但出现了这个错误。

错误

IntegrityError at /lawyers/karlyn-rosemarie-hylton/review/ 
NOT NULL constraint failed: lawyers_review.reviewer_id 

有人可以解释一下我做错了什么以及如何解决吗?

第二个目标似乎与第一个目标非常相关。我没有收到任何错误。但我想确保我做对了。但是,在我通过第一个错误之前我无法判断。

非常感谢任何帮助摆脱困境。

模型.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 

View .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) 

网址.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'), 
] 

根据@Alasdair 和@Sachin Kukreja 的反馈,我回去做了一些更正。我将“提交”更改为“提交”,将“post_valid”更改为“form_valid”。我还做了一个小调整来简化 View 。更正且有效的 AddReviewView 如下所示。有错误的在上面。

谢谢大家!

工作 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) 

请您参考如下方法:

你有一个错字,你覆盖了 form_valid 但你写了 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()) 

但是,super 调用仍会调用父类的 form_valid,这仍会引发错误。我认为您可以在这个覆盖方法中保存评论并返回基类返回的内容,即 return HttpResponseRedirect(self.get_success_url())

引用:form_valid in FormMixin class , form_valid in ModelFormMixin class