您的位置:首页 > 编程语言 > Go语言

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

2014-12-18 15:20 483 查看
今天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
= 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</span>


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

<tr>
<th scope="row"><a href="">测试管理</a></th>
<td><a href="add/" class="addlink">增加</a></td>
<td><a href="" class="changelink">修改</a></td>
</tr></span>


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

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

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

<tr class="model-{{ model.object_name|lower }}">
{% if model.admin_url %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}

{% if model.add_url %}

4000
<td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td> </td>
{% endif %}

{% if model.admin_url %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td> </td>
{% endif %}
</tr></span>
由此可知,渲染时,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</span>


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()</span>


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

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

在创建完Dynamic models后,加入

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


博文仅供参考
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息