Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using request.user with Django ModelForm

I'm having a problem with logged users and a Django ModelForm. I have a class named _Animal_ that has a ForeignKey to User and some data related to the animal like age, race, and so on.

A user can add Animals to the db and I have to track the author of each animal, so I need to add the request.user that is logged when the user creates an animal instance.

models.py

class Animal(models.Model):
    name = models.CharField(max_length=300)
    age = models.PositiveSmallIntegerField()
    race = models.ForeignKey(Race)
    ...
    publisher = models.ForeignKey(User)
    def __unicode__(self):
        return self.name

class AnimalForm(ModelForm):
    class Meta:
        model = Animal

The main goal is hide the publisher field in the form, and submit the logged user when hitting save button.

I can catch the current user in the view using initial, but what I also want is not display the field.

views.py

@login_required
def new_animal(request):
    if request.method == "POST":
        form = AnimalForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('/')
        else:
            variables = RequestContext(request, {'form': form})
            return render_to_response('web/animal_form.html', variables)
    else:
        form = AnimalForm(initial={'publisher': request.user})
    variables = RequestContext(request, {'form': form})
    return render_to_response('web/animal_form.html', variables)
like image 508
amb Avatar asked Dec 11 '11 19:12

amb


3 Answers

You just need to exclude it from the form, then set it in the view.

class AnimalForm(ModelForm):
    class Meta:
        model = Animal
        exclude = ('publisher',)

... and in the view:

    form = AnimalForm(request.POST)
    if form.is_valid():
        animal = form.save(commit=False)
        animal.publisher = request.user
        animal.save()

(Note also that the first else clause - the lines immediately following the redirect - is unnecessary. If you leave it out, execution will fall through to the two lines at the end of the view, which are identical.)

like image 110
Daniel Roseman Avatar answered Oct 15 '22 12:10

Daniel Roseman


Another way (slightly shorter):
You need to exclude the field as well:

class AnimalForm(ModelForm):
    class Meta:
        model = Animal
        exclude = ('publisher',)

then in the view:

animal = Animal(publisher=request.user)  
form = AnimalForm(request.POST, instance=animal)
if form.is_valid():
     animal.save()
like image 34
matino Avatar answered Oct 15 '22 12:10

matino


I would add it directly to the form:

class AnimalForm(ModelForm):
    class Meta:
        model = Animal
        exclude = ('publisher',)

    def save(self, commit=True):
        self.instance.publisher = self.request.user
        return super().save(commit=commit)

This is in my opinion the cleanest version and you may use the form in different views.

like image 29
melbic Avatar answered Oct 15 '22 11:10

melbic