Accessing request.user in class based generic view CreateView in order to set FK field in Django

后端 未结 3 2065
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-29 23:14

So I have a model that includes:

class Place(models.Model):
    ....
    created_by = models.ForeignKey(User)

My view is like so:



        
相关标签:
3条回答
  • 2020-11-29 23:53

    How about overriding form_valid which does the form saving? Save it yourself, do whatever you want to it, then do the redirect.

    class PlaceFormView(CreateView):
        form_class = PlaceForm
    
        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(PlaceFormView, self).dispatch(*args, **kwargs)
    
        def form_valid(self, form):
            obj = form.save(commit=False)
            obj.created_by = self.request.user
            obj.save()        
            return http.HttpResponseRedirect(self.get_success_url())
    
    0 讨论(0)
  • 2020-11-29 23:54

    I know that this is old, but for other people with this problem:

    There is an even simpler way - since saving a form multiple times will always use the same model instance, you can also do:

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.created_by = self.request.user
        return super(PlaceFormView, self).form_valid(form)
    

    That way, you get all the benefits of the super call - it's trivial to see that you're really only adding those two lines of code, and you don't have to repeat yourself by replicating the redirect logic.

    0 讨论(0)
  • 2020-11-29 23:56

    An alternate way to do this is to pass the user through overwriting the get_initial() method in the CreateView, and modify save method in the PlaceForm class to save the user:

    class PlaceForm(forms.ModelForm):
        ...
        ...
        ...
    
        def __init__(self, *args, **kwargs):
            self.created_by = kwargs['initial']['created_by']
            super(PlaceForm, self).__init__(*args, **kwargs)
    
        def save(self, commit=True):
            obj = super(PlaceForm, self).save(False)
            obj.created_by = self.created_by
            commit and obj.save()
            return obj
    
    class PlaceFormView(CreateView):
        ...
        ...
        form_class = PlaceForm
    
        def get_initial(self):
            self.initial.update({ 'created_by': self.request.user })
            return self.initial
    

    This way the saving logic is still encapsulated within the form class.

    0 讨论(0)
提交回复
热议问题