今天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
检查html发现
测试管理
增加
修改
现象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))