Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#26248 closed New feature (wontfix)

Make current WSGI request instance available in forms.ModelForm instances.

Reported by: Dmitriy Sintsov Owned by: nobody
Component: Forms Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

It is so much tiresome to add custom form classes everywhere to access current request from form instances, especially in django.admin. Why request instance is not available as ModelForm member instance by default? ModelForm's may be instantiated in many different parts of application and it's very useful to have self.request instance in forms.ModelForm.clean() method.

Why it is not like that already? Aren't forms tied to requests and are pretty much useless without requests? Anyway, if there is usage of forms.ModelForm without WSGI request (I haven't seen such usage yet, it seems untypical), one may have self.request = None in such case.

Change History (5)

comment:1 Changed 3 years ago by Aymeric Augustin

Why it is not like that already?

Because of loose coupling -- see the first paragraph of https://docs.djangoproject.com/en/1.9/misc/design-philosophies/


You can write a middleware that stores the current request in a global (thread-local) variable and access it from anywhere in your application. Django doesn't provide this by default because committers don't think it's a good design. But it takes less than 10 lines of code and nothing stops you from doing it for your own use.

comment:2 Changed 3 years ago by Claude Paroz

Resolution: wontfix
Status: newclosed

comment:3 Changed 3 years ago by Dmitriy Sintsov

Having request instance available everywhere (including model instances) is a bad design, encouraging misuse of models which might live in management commands without request at all. Having request in ModelForm instances and maybe in field widgets instance is a very useful thing and is a much less bad design.

But as you wish.

comment:4 Changed 3 years ago by Aymeric Augustin

You could certainly use a modelform without a request, for example to validate data pulled from a CSV file before inserting it into the database.

It's unclear to me why you need to pass a request to a modelform so often. For me the frontier is materialized by form = MyModelForm(request.POST).

While it's true that (model)forms are usually closer to request handling than models, I'm not convinced coupling (model)forms to HTTP requests is justified.

comment:5 Changed 3 years ago by Dmitriy Sintsov

I have "orthogonal" kwargs in urls.py request to views mapping throughout the code with the same url regex key names: 'project_id', 'profile_id' . Then I implemented my own context middleware which process_view() checks for 'project_id' / 'profile_id' of current view kwargs. It also has the whole "business logic" context class, which tries to load Project / Profile models from DB by these PK's, then checks current user access permissions to these model instances, performs additional steps when necessary.

That saves a lot of repetitive boilerplate code in views where I get ready loaded and already checked self.request.context with appropriate project and /or user profile models, instead of loading them over and over. The trouble is, that sometimes I need to access that self.request.context instance from ModelForm.clean() method and these forms are used not only in views and CBV's where it's easy to add self.request to instance of ModelForm, but also in django.admin, including third-party nested inline admin.

I will probably have to implement per thread request context storage as you've suggested. Because anyway I use stable 1.8 LTS, not current working master (nested inline admin module has some troubles with newer Django versions).

Note: See TracTickets for help on using tickets.
Back to Top