djangodjango-viewscreate-view

CreateView doesn't save object , throws 'this field is required ' error


models.py is :

class Todo(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE,null=True,blank=True)
    title = models.CharField(max_length=200)
    desc = models.TextField(null=True,blank=True)
    complete = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title
    
    class Meta:
        ordering = ['created']

views.py is:

class TaskCreate(generic.CreateView):
    model = Todo
    fields = '__all__'
    template_name = 'create.html'
    success_url = reverse_lazy('home')

create.html is:

<body>
    <a href="{% url 'home' %}">go back</a>
    {{ form.as_p }}
    <form method="post">
    {% csrf_token %}
    <input type="submit" value="submit">
    </form>
</body>

Whenever I submit data from create.html form it doesn't save it to the database and throws this field is required on 'user' field. How do I resolve this?


Solution

  • You probably want to exclude the user field, since it is determined by the logged in user, so:

    from django.conf import settings
    
    
    class Todo(models.Model):
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL, on_delete=models.CASCADE, editable=False
        )
        # …
    
        def __str__(self):
            return self.title
    
        class Meta:
            ordering = ['created']

    Then we inject the logged in user in the instance of the form:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    
    class TaskCreateView(LoginRequiredMixin, generic.CreateView):
        model = Todo
        fields = '__all__'
        template_name = 'create.html'
        success_url = reverse_lazy('home')
    
        def form_valid(self, form):
            form.instance.user = request.user
            return super().form_valid(form)

    Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


    Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].


    Note: In Django, class-based views (CBV) often have a …View suffix, to avoid a clash with the model names. Therefore you might consider renaming the view class to TaskCreateView, instead of TaskCreate.