pythondjangodjango-class-based-viewscreate-view

Django IntegrityError at /create_post/


When trying to create a create class-based view I get the IntegrityError listed above the full error is

IntegrityError at /create_post/
null value in column "author_id" of relation "blog_post" violates not-null constraint
DETAIL:  Failing row contains (6, First, 2021-02-27 15:36:47.072327+00, Cosndfadfa, 2021-02-27 15:36:47.072447+00, null).

I am not sure what I am doing wrong. Any help on this is greatly appreciated.

Below are my views.py

class CreateView(CreateView):
    model = Post
    template_name = "blog/post_form.html"
    fields = ["title", "content"]

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("about/", views.about, name="about"),
    path("blog/", views.BlogList.as_view(), name="blog-list"),
    path("create_post/", views.CreateView.as_view(), name="create"),
]

my post model in models.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User


class Post(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    updated_on = models.DateTimeField(auto_now=True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_on"]

    def __str__(self):
        return self.title

and my post_form.py

{%extends "blog/base.html"%}
{% load crispy_forms_tags %}

{%block content%}

<div class="container">
    <main class="form-signin">
        <form method="POST">
            {%csrf_token%}
          <h1 class="h3 mb-3 fw-normal">Create New Post </h1>
            {{form|crispy}}
          <button class="w-15 btn btn-lg btn-primary" type="submit">Create </button>
        </form>
      </main>
    </div>

{%endblock content%}

Any help on this is greatly appreciated.


Solution

  • You need to specify a value for the author, since this is a non-NULLable field and there is no default. You can do this by overriding the form_valid method:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class CreateView(LoginRequiredMixin, CreateView):
        model = Post
        template_name = 'blog/post_form.html'
        fields = ['title', 'content']
    
        def form_valid(self, form):
            form.instance.author = 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].