解决Django Dynamic models 的 admin_url 为空的问题

今天Django项目的一个需求:

通过前端的操作创建一个model,并通过管理平台对其进行管理,也就是说这个model不是通过通过代码写好的类,而是动态创建出来的。

参考 https://code.djangoproject.com/wiki/DynamicModels 实现该功能,并且在管理平台能够找到该model,

def create_model_class(name, cname, fields=None, app_label='', module='', options=None, admin_opts=None):
    '''
    Create dynamic model
    '''
    class Meta:
        verbose_name = cname
        verbose_name_plural = "%s%s"%(cname,u"管理")

    app_label = "dict"
    if app_label:
        setattr(Meta,'app_label',app_label)
    if options is not None:
        for key,value in options.iteritems():
            setattr(Meta, key, value)
    attrs = {'__module__': name,'Meta':Meta}

    for n,t in fields.items():
        cn_name = t[0]
        t = dict(FIELD_TYPE)[t[1]]
        if t == 'VarChar':
            f = models.CharField(cn_name, max_length = 255, blank = True)
        elif t == 'Int':
            f = models.IntegerField()
        elif t == 'DATE':
            f = models.DateTimeField()
        else:
            assert False
        attrs[n] = f
    #default field
    attrs['create_time'] = models.DateTimeField(u'创建时间',auto_now=False, auto_now_add=True)
    attrs['change_time'] = models.DateTimeField(u'修改时间',auto_now=True, auto_now_add=False)
    attrs['last_user'] = models.CharField(u'修改人', default='',max_length=50,blank=True)
        
    model = type(name, (models.Model,), attrs)
    
    class Admin(admin.ModelAdmin):
        def save_model(self, request, obj, form, change):
            obj.last_user = request.user.username
            obj.save()
    if admin_opts:
        for key, value in admin_opts:
            setattr(Admin, key, value)
    admin.site.register(model, Admin)
    return model


不过问题来了,当点击model的时候,没有进入该model的管理界面,点击加号的时候直接报404

检查html发现


    测试管理
    增加
    修改

现象1  很明显超链接的地址不对

现象2  当Django重启后先加载这个Dynamic models,一切正常


找到对应的模板,C:\Python27\Lib\site-packages\Django-1.7-py2.7.egg\django\contrib\admin\templates\admin\index.html


            {% if model.admin_url %}
                {{ model.name }}
            {% else %}
                {{ model.name }}
            {% endif %}

            {% if model.add_url %}
                {% trans 'Add' %}
            {% else %}
                 
            {% endif %}

            {% if model.admin_url %}
                {% trans 'Change' %}
            {% else %}
                 
            {% endif %}
 
由此可知,渲染时,model.admin_url为空字符。

查看django源码,找到admin_url的赋值是由django/contrib/admin/sites.py 第447行处理,不过,这里没有对异常进行处理

try:
    model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
except NoReverseMatch:
    pass

reverse方法来自django\core\urlresolvers.py

该模块的介绍为:

"""
This module converts requested URLs to callback view functions.
RegexURLResolver is the main class here. Its resolve() method takes a URL (as
a string) and returns a tuple in this format:
    (view_function, function_args, function_kwargs)
"""

结合现象2 判断与缓存有关

urlresolvers.py 模块定义了下面的方法

def clear_url_caches():
    get_callable.cache_clear()
    get_resolver.cache_clear()
    get_ns_resolver.cache_clear()

没有方法介绍,而且django源码中只有测试用例调用过该方法,不过看到出是在清理缓存


最终通过实践找到解决方法:

在创建完Dynamic models后,加入


clear_url_caches()
reload(import_module(settings.ROOT_URLCONF))

博文仅供参考


你可能感兴趣的:(Django)