-
-
Save gengue/3dd99a57b084377169b6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
''' | |
Tricky admin -> xadmin merger. | |
Alex Moiseenko aka IMDagger. | |
''' | |
import logging | |
import types | |
from functools import wraps, update_wrapper | |
from django.http import HttpRequest | |
from django.contrib.admin import ModelAdmin | |
class IgnoredAdminModel(Exception): | |
pass | |
def translate(klass, model_obj): | |
''' | |
Very tricky function to merge Django admin's model descriptors | |
into the XAdmin registry, because it doesn't work from the | |
box due to the huge difference and some copied xadmin's | |
functionality (this one has own incompatible metaclass, incompatible | |
methods with same goal as Django's admin does). | |
This function tries to fill this gap. | |
''' | |
if issubclass(klass, ModelAdmin): | |
attrs = {} | |
slices = reversed((klass,) + klass.__bases__) | |
# all bases after ModelAdmin | |
is_nested = lambda s: issubclass(s, ModelAdmin) and s != ModelAdmin | |
custom_slices = filter(is_nested, slices) | |
for admin_slice in custom_slices: | |
# copy just only custom methods and fields | |
for k, v in admin_slice.__dict__.iteritems(): | |
if k.startswith('__'): | |
continue | |
if isinstance(v, types.FunctionType): | |
def method_for(k, v): | |
@wraps(v) | |
def inner(self, *args, **kwargs): | |
real_handler = getattr(model_obj, k) | |
if args and isinstance(args[0], HttpRequest): | |
# args list already contains request | |
return real_handler(*args, **kwargs) | |
# request should be first argument after self | |
elif 'request' in real_handler.im_func.func_code.co_varnames[:2]: | |
return real_handler(self.request, *args, **kwargs) | |
else: | |
return real_handler(*args, **kwargs) | |
return inner | |
attrs[k] = method_for(k, v) | |
elif not isinstance(v, property): | |
attrs[k] = v | |
# xadmin doesn't work with func-obj specified columns | |
if 'list_display' in attrs: | |
str_list = [] | |
for idx, column in enumerate(attrs['list_display']): | |
if callable(column): | |
internal_name = '_list_{name}_{unique}'.format(name=column.__name__, unique=idx) | |
column_handler = staticmethod(column) | |
attrs[internal_name] = column_handler | |
# patch __func__, because column_handler | |
# is a static method object yet | |
update_wrapper(column_handler.__func__, column) | |
str_list.append(internal_name) | |
else: | |
str_list.append(column) | |
display_type = type(attrs['list_display']) | |
attrs['list_display'] = display_type(str_list) | |
essential = type('{0}Wrapper'.format(klass.__name__), (object,), attrs) | |
return essential | |
else: | |
raise IgnoredAdminModel('This function doesn\'t support {0} yet'.format(klass)) | |
def sew(admin, to, RegistryError): | |
xadmin = to | |
for model, admin_obj in admin.site._registry.iteritems(): | |
try: | |
x = xadmin.site.register(model, translate(admin_obj.__class__, admin_obj)) | |
admin_obj.admin_site = x | |
except (RegistryError, IgnoredAdminModel), e: | |
logger = logging.getLogger(__name__) | |
logger.debug('Admin sewing notice', exc_info=True, extra={'descriptor': e}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# how to use merger: | |
... | |
from django.contrib import admin | |
admin.autodiscover() | |
from xadmin import sites | |
import xadmin | |
xadmin.autodiscover() | |
seamless_admin.sew(admin, to=xadmin, RegistryError=sites.AlreadyRegistered) | |
urlpatterns = patterns('', | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment