ghiotion
ghiotion

Reputation: 285

Django Design Pattern - request.user in Model

I run into this pattern all the time and I'm wondering if there's a better way to handle it. Lots of my models contemplate the idea of 'creator' - in other words, I want to make sure the user who created the object is saved as the creator. As such, my models almost always include

creator = models.ForeignKey(User)

There doesn't seem to be a way of defaulting this user to the user who created it (request.user). As such I find myself building model forms and adding creator as a HiddenInput()

class MyModelForm(ModelForm):
    class Meta:
        model = MyModelForm
        fields = ['name', 'creator']
        widgets = {
            'creator': HiddenInput()
        }        

and then binding the form in the view with initial

form = MyModelForm(initial={'creator': request.user})

and checking on POST to make sure no one dickered with the form (full view):

def create(request):
    form = MyModelForm(initial={'creator': request.user})
    if request.method ==  'POST':
        if int(request.POST['creator']) != int(request.user.id):
            return render(request,'500.html', {'message':'form tampering detected'})
        form = FeedGroupForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('index'))
    return render(request, 'mymodelformpage.html',{'form':form})

I'm fine with this but it seems like an anti-pattern. It strikes me that there ought to be a way to default the creator in the model.

creator = models.ForeignKey(User, default=request.user)

Or do it in a post_save perhaps?

Upvotes: 1

Views: 810

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599956

No, this is not the right way. The correct way is to exclude the creator field from the form, then set it on save:

if form.is_valid:
    obj = form.save(commit=False)
    obj.creator = request.user
    obj.save()
    ... redirect ...

Upvotes: 3

Related Questions