I agree that setting self.exclude will set the instance attribute, thus hiding 
the class attribute of the same name. However, it appears that a given 
AdminSite instantiates each registered ModelAdmin once at registration time.[1] 
The default AdminSite itself is a module global. Thus, any long-running, 
multi-threaded Django application server (e.g. a threaded uWSGI process) might 
be relying on a given ModelAdmin instance to serve multiple requests 
concurrently. Neither AdminSite nor ModelAdmin appear to have any 
thread-locality, suggesting that modifying self.exclude (or anything else) for 
an individual request is a race condition waiting to happen.

I believe this is essentially a subtle documentation bug, although it's worth 
asking whether there are any deeper assumptions about ModelAdmin or AdminSite 
having any kind of request isolation. 

Thanks,
Peter


[1] 
https://github.com/django/django/blob/master/django/contrib/admin/sites.py#L104


> On Nov 12, 2014, at 1:36 PM, Collin Anderson <cmawebs...@gmail.com> wrote:
> 
> On Tuesday, November 11, 2014 3:24:48 PM UTC-5, Peter Sagerson wrote:
> The documentation of ModelAdmin.get_form()[1] demonstrates modifying 
> self.exclude in order to modify the add/change form on a per-request basis. 
> However, looking at django.contrib.admin, it seems clear that ModelAdmin is 
> instantiated when it's installed, not for every request. It also doesn't 
> appear to be a subclass of threading.local. Is there some reason this isn't a 
> terrible idea or is the example just in error?
> 
> Thanks,
> Peter
> 
> 
> [1] 
> https://docs.djangoproject.com/en/1.7/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_form
> 
> Hi Peter,
> 
> I've never thought that way about admin classes before, but it should work 
> correctly.
> 
> In Python, setting self.exclude = ['something'] will set a _new_ attribute on 
> on the object, the instance of the admin class, not the admin class itself, 
> even if there's a matching attribute on the class with that name. You'll end 
> up with two different exclude lists. One in self.__class__.__dict__ (aka 
> vars(type(self))) (which is now pretty hidden) and one in self.__dict__ (aka 
> vars(self)).
> 
> Though, if you _mutate_ the original attribute, like 
> self.exclude.append('something'), it will mutate the exclude list on the 
> class.
> 
> Collin
> 
> 
> -- 
> You received this message because you are subscribed to a topic in the Google 
> Groups "Django users" group.
> To unsubscribe from this topic, visit 
> https://groups.google.com/d/topic/django-users/AmoUDtEefyA/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to 
> django-users+unsubscr...@googlegroups.com.
> To post to this group, send email to django-users@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/be985862-c203-4358-bc78-8988a295f733%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/2D8BB5C1-879F-4D10-9A79-98ECD26C682A%40ignorare.net.
For more options, visit https://groups.google.com/d/optout.

Reply via email to