TAGS :Viewed: 6 - Published at: a few seconds ago

[ Django using a form with an ImageField and a User ]

In Django, the user can upload a comment with the image.

from sorl.thumbnail import ImageField

class Comment(models.Model):
  count_votes = models.Integer(default=0)
  user = models.ForeignKey(User)
  thumb = ImageField(upload_to="thumbnails")
  # ...

This is what I am trying to do :

# views.py
def add_comment(request):
  if request.method == 'POST' and request.user.is_authenticated():
    comment = Comment(user=request.user) 
    form = CommentForm(request.POST, request.FILES, instance=comment)
    if form.is_valid():
  # ...

# forms.py
class CommentForm(forms.ModelForm):
  class Meta:
    model = Comment

But there are some errors :

  • none of the fields are filled
  • the count_votes is not defaulted to 0 as I would like to
  • the user is not taken into account either
  • the image is said to be empty too

How can I achieve that ? I have read many questions on SO and tried various other things, like fill in things in the __init__ of the form, use initial instead of instance, ...

Answer 1

First, make sure in your template you have enctype="multipart/form-data" in your <form> tag, otherwise the image file will not get uploaded and your form will not validate (and thus, nothing will be added to the database).

In addition, you need to fix your views. Start by using the login_required decorator so that your view is restricted to logged-in users, and then fix your form logic:

from django.shortcuts import redirect, render
from django.contrib.auth.decorators import login_required

def add_comment(request):
    form = CommentForm(request.POST or None, request.FILES or None)
    if form.is_valid():
       obj = form.save(commit=False) # create the record, but don't save it
       obj.user = request.user # add the user from the request
       obj.save() # now save the record
       return redirect('/')
    return render(request, 'template.html', {'form': form})

Finally, in your form exclude the user because you will be adding it later. In fact, your form should just have the comment and image field. You don't need to include the count_votes field because it already has a default value; unless you want the user to modify this field.

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('thumb', 'comment',)