Accessing request from form

15 views
Skip to first unread message

James Schneider

unread,
May 30, 2019, 3:36:26 AM5/30/19
to django...@googlegroups.com
Does anyone know a philosophical reason (or I suppose a technical one, although I don't think that's the case) why the request is not made available by default in ModelForms when using CBV's? 

Almost all of the models I use have "audit" fields (created_by, updated_by, etc.) that reference the current logged in user. A ModelForm has no access to the current request, and as such can't update these fields without a User object. I have other use cases as well, but this one is probably the most prevalent among other developers.

At any rate, I'm currently stuck having to create relatively empty ModelForm shell classes for the simple reason of including a form mixin that grabs the request before __init__() (because the ModelForm complains if I don't), and overrides save() to save the fields with the user object, in addition to specifying the form_class in the CBV along with a view mixin for sending the request over via get_form_kwargs(). It's quite a process, especially when dealing with multiple models. I could drop a significant amount of code if I could flag the CBV to include the request with the form initialization. Heck, there could even be some magic to have the form associate the user with specific fields on save from the view as form_kwargs.

Or am I making things hard on myself? Thanks.

-James

James Schneider

unread,
May 30, 2019, 5:26:57 AM5/30/19
to django...@googlegroups.com
I always dread being the guy that responds to his own thread with "Hey guys, I fixed it."

At any rate, I'm currently stuck having to create relatively empty ModelForm shell classes for the simple reason of including a form mixin that grabs the request before __init__() (because the ModelForm complains if I don't), and overrides save() to save the fields with the user object, in addition to specifying the form_class in the CBV along with a view mixin for sending the request over via get_form_kwargs(). It's quite a process, especially when dealing with multiple models. I could drop a significant amount of code if I could flag the CBV to include the request with the form initialization. Heck, there could even be some magic to have the form associate the user with specific fields on save from the view as form_kwargs.

Or am I making things hard on myself? Thanks.

For the use case above, I had an epiphany did some more experimenting and figured out how to update the audit fields without needing to mangle a Form/ModelForm, entirely from the CBV:

     def form_valid(self, form):
        form.instance.updated_by = self.request.user
        return super().form_valid(form)

Fully compatible with an implicit ModelForm, and only 3 lines of code!

This is an easy drop in a view mixin, which I already have for other overrides anyway. However, this feels really gross, and I feel like I'm violating some prime directive by attaching data to an instance that was not validated by the form. I think I can forgive myself since the data I'm attaching is coming from Django and not some other source, and I have to assume Django handles these things properly.

Of course while writing this message, I then stumbled on this exact solution buried in the Django docs:


So, feel free to ignore me. I will grant myself a point for coming up with the same solution already blessed by the Django devs. I'm also deducting a point from myself for not RTFM properly, so I break even.

-James

Mike Dewhirst

unread,
May 30, 2019, 8:27:43 PM5/30/19
to Django users


On Thursday, May 30, 2019 at 7:26:57 PM UTC+10, James Schneider wrote:
I always dread being the guy that responds to his own thread with "Hey guys, I fixed it."

Don't beat yourself up :)

No-one stops looking and just waits for the answer. You have to assume your own motivation to find it is stronger than everyone else's. It is just good manners to report back so others can stop looking. And it would be bad manners to say you fixed it without revealing the fix.

Actually, no-one else even looks unless they are particularly interested or they encountered the same problem within recent memory.

Except you. You have helped me more than once in the past and I appreciate it. Thank you. Ten extra points!

Cheers

Mike

James Schneider

unread,
May 31, 2019, 2:59:27 PM5/31/19
to django...@googlegroups.com


Don't beat yourself up :)

It's actually slightly cathartic and humbling to do that every once in a great while. ;-)


No-one stops looking and just waits for the answer. You have to assume your own motivation to find it is stronger than everyone else's. It is just good manners to report back so others can stop looking. And it would be bad manners to say you fixed it without revealing the fix.

Yeah, that's a pet peeve of mine so I made sure to include the answer.


Actually, no-one else even looks unless they are particularly interested or they encountered the same problem within recent memory.

Can't say I'm not guilty of doing that as well. I'm a college lecturer in one of my many positions, so I do like the academic challenge that some of these questions pose, even if I haven't needed it myself. However, on more than one occasion I have run into one of the landmines that I've helped out on in the past, and it's saved me a fair amount of time.


Except you. You have helped me more than once in the past and I appreciate it. Thank you. Ten extra points!

Haha, thanks. I'll take the points. I wish I had the time to be more active on this list, but the wife says I have to pay attention to her and the kids, and I'm only allowed to have 2 jobs and 1 hobby. Luckily my current hobby overlaps with Django so here I am.

-James
Reply all
Reply to author
Forward
0 new messages