Jjkivai
Jjkivai

Reputation: 157

Form save is not adding user to model

I have a django Model and ModelForm, but when I make a new body, everything works, except the User is not created. All post.user attributes return none. I am using the contrib.auth to login user, which works as in my html user.is_authenticated works

I tried using:

form.user=request.user
form.save()

to no avail.

Any help would be appreciated

Models.py

from django.db import models
from datetime import datetime
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.

class Post(models.Model):
    body = models.TextField(max_length=140)
    timestamp = models.DateField(db_index=True, default=datetime.utcnow)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)

    class Meta:
        ordering = ['-timestamp']

    def __repr__(self):
        return '<Post {}>'.format(self.body)
    
    def get_absolute_url(self):
        return reverse('post', args=[str(self.id)])

Forms.py

from django.forms import ModelForm
from .models import Post
from django.core.exceptions import ValidationError

class PostForm(ModelForm):
    def clean_body(self):
        data = self.cleaned_data['body']
        if len(data) > 140:
            raise ValidationError('More than 140 characters')
        return data
    class Meta:
        model = Post
        fields = ['body']

views.py

from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.core.paginator import Paginator
from django.shortcuts import redirect, render
from .models import Post
from .forms import PostForm
from django.contrib.auth.models import User
# Create your views here.

@login_required
def index(request):
    '''deal with post method first'''
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect(reverse('index'))
    
    else:
        form = PostForm
    
    posts = Post.objects.all()
    paginator = Paginator(posts, 3)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    context = {
        'form':form,
        'page_obj':page_obj
    }
    return render(request, 'index.html', context=context)

Upvotes: 3

Views: 65

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476493

A form has no user, you should patch the .instance wrapped in the form, so:

@login_required
def index(request):
    '''deal with post method first'''
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            return redirect('index')
    # …

You might want to use the auto_now_add=True parameter for the timestamp:

class Post(models.Model):
    body = models.TextField(max_length=140)
    timestamp = models.DateField(db_index=True, auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)

    # …

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.

Upvotes: 2

Related Questions