pizzarob
pizzarob

Reputation: 12029

Django Model Form post to current user

I am trying to make a form where the current logged in user can post a new status. I am using a model form. I don't get any errors when I load the page, however it seems that no data is being posted. So my question is how to I get this to post a new status for the current user? Here is my current code:

My View:

@login_required
def post(request, username):
    logged_user = request.user
    newpostform = PostForm(instance=request.user.get_profile(), data=request.POST)
    if newpostform.is_valid():
        newpostform.save()
    newpostform = PostForm()
    context = {'newpostform': newpostform,}
    return render(request, 'twitterclone/newpost.html', context)

My Form:

class PostForm(ModelForm):
    class Meta:
        model = Post

My Models:

class Profile(models.Model):
    user = models.ForeignKey(User)
    bio = models.TextField()
    image = models.ImageField(upload_to='images/%Y/%m/%d')
    following = models.ManyToManyField('self', blank = True, null = True)

    def __unicode__(self):
        return unicode(self.user)

class Post(models.Model):
    profile = models.ForeignKey(Profile)
    body = models.CharField(max_length=140)
    pub_date = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return unicode(self.body[:50])

My Template:

<form action="" method="POST">
{% csrf_token %}
{{newpostform.body}}
<button>Tweet It</button>
</form>

Upvotes: 0

Views: 1120

Answers (1)

Peter DeGlopper
Peter DeGlopper

Reputation: 37319

Your template does not include the profile field, which is mandatory, so your form is never valid. Because you're creating a new form every time, you're not seeing the error message - not that your template would display it anyway.

Specify in your form definition that you only want the body:

class PostForm(ModelForm):
    class Meta:
        model = Post
        fields = ['body']

That will let the form validate. You will also have to set the profile field explicitly:

if newpostform.is_valid():
    newpost = newpostform.save(commit=False)
    newpost.profile = request.user.get_profile()
    newpost.save()

And your instance argument to the form constructor is not doing what you think it is - that's for passing in an existing instance of the model the form represents for editing.

I would rewrite the view thus:

@login_required
def post(request, username):
    newpostform = PostForm(data=request.POST)
    if newpostform.is_valid():
        newpost = newpostform.save(commit=False)
        newpost.profile = request.user.get_profile()
        newpost.save()            
        newpostform = PostForm()
    context = {'newpostform': newpostform,}
    return render(request, 'twitterclone/newpost.html', context)

Here, I'm not reassigning the form to a new empty one unless the one that was just submitted was valid. That will allow the template to show error messages.

Upvotes: 1

Related Questions