Django

Code

Ticket #6776: 6776_modeladmin_fix.1.diff

File 6776_modeladmin_fix.1.diff, 4.1 kB (added by brosner, 9 months ago)

initial cut for patching this. needs alot more work, but this is a proof of concept for the final patch.

  • /dev/null

    old new  
     1 
     2class ModelAdminCache(object): 
     3     
     4    __shared_state = dict( 
     5        modeladmin_store = {}, 
     6    ) 
     7     
     8    def __init__(self): 
     9        self.__dict__ = self.__shared_state 
     10         
     11    def get(self, key): 
     12        return self.modeladmin_store[key] 
     13     
     14    def register(self, *admin_classes): 
     15        for admin_class in admin_classes: 
     16            key = ".".join(admin_class.__module__.split(".")[-2:] + [admin_class.__name__]) 
     17            # print "ModelAdminCache registering %s (%s)" % (key, id(admin_class)) 
     18            if key in self.modeladmin_store: 
     19                continue 
     20            self.modeladmin_store[key] = admin_class 
     21 
     22admin_class_cache = ModelAdminCache() 
  • a/django/contrib/admin/options.py

    old new  
    44from django.newforms.models import _modelform_factory, _inlineformset_factory 
    55from django.contrib.contenttypes.models import ContentType 
    66from django.contrib.admin import widgets 
     7from django.contrib.admin.loading import admin_class_cache 
    78from django.contrib.admin.util import get_deleted_objects 
    89from django.core.exceptions import ImproperlyConfigured, PermissionDenied 
    910from django.db import models, transaction 
     
    124125        attrs = classes and {'class': u' '.join(classes)} or {} 
    125126        return self.field.label_tag(contents=contents, attrs=attrs) 
    126127 
     128class ModelAdminMetaclass(type): 
     129    def __new__(cls, name, bases, attrs): 
     130        new_class = forms.MediaDefiningClass.__new__(cls, name, bases, attrs) 
     131        try: 
     132            parents = [b for b in bases if issubclass(b, ModelAdmin)] 
     133            if not parents: 
     134                return new_class 
     135        except NameError: 
     136            return new_class 
     137        # new_class = type.__new__(cls, name, bases, attrs) 
     138        # put this in some sort of registry 
     139        # print "ModelAdminMetaclass called (name=%s, module=%s, new_class=%s)" % (name, new_class.__module__, id(new_class)) 
     140        admin_class_cache.register(new_class) 
     141        # due to the way imports happening only use the admin class that is 
     142        # already registered. 
     143        return admin_class_cache.get(".".join(new_class.__module__.split(".")[-2:] + [new_class.__name__])) 
     144 
    127145class BaseModelAdmin(object): 
    128146    """Functionality common to both ModelAdmin and InlineAdmin.""" 
    129147    raw_id_fields = () 
     
    200218 
    201219class ModelAdmin(BaseModelAdmin): 
    202220    "Encapsulates all admin options and functionality for a given model." 
    203     __metaclass__ = forms.MediaDefiningClass 
     221    __metaclass__ = ModelAdminMetaclass 
    204222 
    205223    list_display = ('__str__',) 
    206224    list_display_links = () 
  • a/django/contrib/admin/sites.py

    old new  
    7676        if isinstance(model_or_iterable, ModelBase): 
    7777            model_or_iterable = [model_or_iterable] 
    7878        for model in model_or_iterable: 
    79             if model in self._registry: 
    80                 raise AlreadyRegistered('The model %s is already registered' % model.__name__) 
     79            # print "registering %r (model=%s, admin_class=%s, in_registry=%s, self=%s)" % (model, id(model), id(admin_class), model in self._registry, id(self)) 
     80            if model in self._registry and self._registry[model].__class__ is not admin_class: 
     81                # print "MAYDAY!! (%s is not %s)" % (id(self._registry[model].__class__), id(admin_class)) 
     82                raise AlreadyRegistered('The model %s is already registered to %s' % (model.__name__, self._registry[model].__class__.__name__)) 
    8183            self._registry[model] = admin_class(model, self) 
    8284 
    8385    def unregister(self, model_or_iterable):