Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django form set current login user

Tags:

forms

django

@login_required
def post_review(request):
    if request.method == 'POST':
        formset = ReviewForm(request.POST)
        if formset.is_valid():
            formset.save(commit=False)
            #formset.author = User.objects.get(pk=int(request.user.id))
            formset.pub_date = datetime.datetime.now
            formset.save()
            return HttpResponseRedirect(reverse(review_index))
    else:
        formset = ReviewForm()
    return render_to_response("review/post_review.html",
        {"formset": formset}, context_instance=RequestContext(request),
    )

I have this view, I want to auto set the current logged-in user in my review form author field. But I dont know how. Any ideas/hint pls? Below is my form:

class ReviewForm(ModelForm):
    class Meta:
        model = Review
        fields = ('title','category', 'body', )
        widgets = {
            'body': Textarea(attrs={'cols': 60, 'rows': 20}),
        }
like image 288
Ronnie Beltran Avatar asked Nov 28 '22 11:11

Ronnie Beltran


2 Answers

I've always done this by accepting a new kwarg in my form's __init__, and saving the value until save-time.

class ReviewForm(ModelForm):
    class Meta:
        model = Review
        fields = ('title','category', 'body', )
        widgets = {
            'body': Textarea(attrs={'cols': 60, 'rows': 20}),
        }

    def __init__(self, *args, **kwargs):
        self._user = kwargs.pop('user')
        super(ReviewForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        inst = super(ReviewForm, self).save(commit=False)
        inst.author = self._user
        if commit:
            inst.save()
            self.save_m2m()
        return inst

And then in my view:

def post_review(request):
    # ... snip ...
    if request.method == 'POST'
      form = ReviewForm(request.POST, user=request.user)
      if form.is_valid():
         form.save()
         return HttpResponseRedirect('/thanks/') #or whatever the url
      else:
         # Don't forget to add user argument
         form = ReviewForm(user=request.user)
    # ... snip ...

If Review.author isn't a required field, you can add a second value to the kwargs.pop call to set a default, like None. Otherwise, if the user kwarg isn't provided, it'll raise an error, effectively making it a required argument.

like image 102
eternicode Avatar answered Dec 06 '22 23:12

eternicode


As an alternative solution, in Django 2+ using a form view - such as a CreateView or FormView, I can simply pass the self.request.user to my pre-saved form model:

class AppCreateView(CreateView):
    model = models.App
    fields = ['name']
    success_url = '/thanks/'

    def form_valid(self, form):
        app_model = form.save(commit=False)
        app_model.author = self.request.user
        # app_model.user = User.objects.get(user=self.request.user) # Or explicit model 
        app_model.save()
        return super().form_valid(form)

I agree the class based view is not important here. The important line is app_model.author = self.request.user.

The model is not special:

from django.db import models
from django.contrib.auth.models import User


class App(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=255, help_text="Arbitrary name")
    created = models.DateTimeField(auto_now_add=True, max_length=255)
like image 34
Glycerine Avatar answered Dec 07 '22 00:12

Glycerine