Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting object owner with generic create_object view in django

Tags:

python

django

Is it possible to use create_object view to create a new object and automatically assign request.user as foreign key?

P.E:

class Post(models.Model):
    text = models.TextField()
    author = models.ForeignKey(User)

What I want is to use create_object and fill author with request.user.

like image 997
Gonzalo Quero Avatar asked Mar 12 '09 18:03

Gonzalo Quero


3 Answers

In many ways, all the solutions to this will be more trouble than they are worth. This one qualifies as a hack. It is possible for a django update to leave you high and dry if they change the way create_update is implemented. For simplicity sake, I'll assume that you are trying to set a default user, not silently force the user to be the logged in user.

Write a context processor:

from django.views.generic.create_update import get_model_and_form_class
def form_user_default(request):
    if request.method == 'GET':
        model, custom_form = get_model_and_form_class(Post,None)
        custom_form.author = request.user
        return {'form':custom_form}
    else: return {}

What this will do is override the form object that create_update passes to the template. What it's technically doing is re-creating the form after the default view has done it.

Then in your url conf:

url(r'pattern_to_match', 'django.views.generic.create_update.create_object', kwargs={'context_processors':form_user_default})

Again, I had to delve into the source code to figure out how to do this. It might really be best to try writing your own view (but incorporate as many Django custom objects as possible). There's no "simple default" way to do this, because in the django paradigm forms are more closely tied to the model layer than to views, and only views have knowledge of the request object.

like image 78
David Berger Avatar answered Nov 12 '22 12:11

David Berger


You may want to consider a closure.

from django.forms import ModelForm
from django.views.generic.create_update import create_object, update_object

def make_foo_form(request):
    class FooForm(ModelForm):
        class Meta:
            model = Foo
            fields = ['foo', 'bar']

        def save(self, commit=True):
            f = super(FooForm, self).save(commit=False)
            if not f.pk: f.user = request.user
            if commit: f.save()
            return f

    return FooForm

def create_foo(request):
    FooForm = make_foo_form(request)
    return create_object(form_class=FooForm)

There is some inefficiency here, since you need to create the ModelForm object on each request, but it does allow you to inject functionality into the generic view.

You need to decide whether the added complexity for the form creation is worth maintaining simplicity on the view side.

A benefit here, though, is that this also works with the update case with practically no extra effort:

def update_foo(request, object_id):
    FooForm = make_foo_form(request)
    return update_object(form_class=FooForm, object_id=object_id)

Obviously, you can use this approach for more complex cases as well.

like image 23
B. Slavin Avatar answered Nov 12 '22 11:11

B. Slavin


If a user is authenticated, their user object is the request.user object.

I'm not familiar with create_object... I'm still a beginner to django and have only just started my first real project with it.

Note that you should check to make sure a user is logged in before using this. This can be done with request.user.is_authenticated().

like image 1
Powerlord Avatar answered Nov 12 '22 11:11

Powerlord