django 1.7+ default_permissions
由于做Caption要做权限设计。在核心类的设计的时候需要做好权限的基础设计。django 1.7+以后 django.db.modes新增特性 default_permissions,官方文档语焉不详。
决定自己探索下,不想一一分析代码,遂引入bug,直接观察核心线路。
引入bug方法:
class baseModel(models.Model):
#....
class Meta:
default_permissions='add'#should be ('add','change',...)
错误如下:
Traceback (most recent call last):
File "C:\Users\tommy.yu\Desktop\Captain\Captain-master\codes\Captain\manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\__init__.py", line 385, in execute_from_command_line
utility.execute()
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\base.py", line 338, in execute
output = self.handle(*args, **options)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\commands\migrate.py", line 165, in handle
emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\core\management\sql.py", line 268, in emit_post_migrate_signal
using=db)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\dispatch\dispatcher.py", line 198, in send
response = receiver(signal=self, sender=sender, **named)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\contrib\auth\management\__init__.py", line 114, in create_permissions
Permission.objects.using(using).bulk_create(perms)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\models\query.py", line 409, in bulk_create
self._batched_insert(objs_without_pk, fields, batch_size)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\models\query.py", line 938, in _batched_insert
using=self.db)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\models\manager.py", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\models\query.py", line 921, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\models\sql\compiler.py", line 920, in execute_sql
cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\backends\utils.py", line 81, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\backends\utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\backends\utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\backends\sqlite3\base.py", line 486, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: columns content_type_id, codename are not unique
直接在最终的文件C:\Python27\lib\site-packages\django-1.7.2-py2.7.egg\django\db\backends\sqlite3\base.py里面加入print xxx之类的语句。如下:
def execute(self, query, params=None):
if params is None:
return Database.Cursor.execute(self, query)
query = self.convert_query(query)
print query,params#在这里添加了print
return Database.Cursor.execute(self, query, params)
再次migrate,并观察sql:
由于sql过多,只抓出insert的sql,如下:
INSERT INTO "auth_permission" ("name", "content_type_id", "codename")
SELECT ? AS "name", ? AS "content_type_id", ? AS "codename"
UNION ALL SELECT ?, ?, ?
UNION ALL SELECT ?, ?, ?
...
(
u'Can add tag', 7, u'add_tag',
u'Can change tag', 7, u'change_tag',
u'Can delete tag', 7, u'delete_tag',
...
)
即写表auth_permission ,django的权限表,可以参考这里。
经过反复的try发现,default_permissions只是取出 default_permissions[0],default_permissions[1],default_permissions[2]然后将其插入到数据表auth_permission里面。而且版本1.7.2的还有bug:
case 1. str类型赋值
default_permissions='abcde'
sql如下,以上代码为抽象基类中的meta类,对于子类(Tag,ContentType,Menu,Page)来说,只有最后一个Page起到作用了(id为10)
INSERT INTO "auth_permission" ("name", "content_type_id", "codename")
SELECT ? AS "name", ? AS "content_type_id", ? AS "codename" UNION ALL SELECT ?, ?, ? UNION A
LL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ?
UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?,
?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ?
UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ?
(u'Can add tag', 7, u'add_tag',
u'Can change tag', 7, u'change_tag',
u'Can delete tag', 7, u'delete_tag',
u'Can add content type', 8, u'add_contenttype',
u'Can change content type', 8, u'change_contenttype',
u'Can delete content type', 8, u'delete_contenttype',
u'Can add menu', 9, u'add_menu',
u'Can change menu', 9, u'change_menu',
u'Can delete menu', 9, u'delete_menu',
u'Can a page', 10, 'a_page',
u'Can b page', 10, 'b_page',
u'Can c page', 10, 'c_page',
u'Can d page', 10, 'd_page',
u'Can e page', 10, 'e_page')
case 2. tuple/list ,长度小于3
抽象基类default_permissions属性
default_permissions=('add', 'change')
生成的sql代码:
INSERT INTO "auth_permission" ("name", "content_type_id", "codename") SELECT ? AS "name", ? AS "content_type_id", ? AS "codename" UNION ALL SELECT ?, ?, ? UNION A
LL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?,
?, ? UNION ALL SELECT ?, ?, ? UNION ALL SELECT ?, ?, ?
(u'Can add tag', 7, u'add_tag',
u'Can change tag', 7, u'change_tag',
u'Can delete tag', 7, u'delete_tag',
u'Can add content type', 8, u'add_contenttype',
u'Can change content type', 8, u'change_contenttype',
u'Can delete content type', 8, u'delete_contenttype',
u'Can add menu', 9, u'add_menu',
u'Can change menu', 9, u'change_menu',
u'Can delete menu', 9, u'delete_menu',
u'Can add page', 10, 'add_page',
u'Can change page', 10,'change_page')
跟case 1 差不多,有作用,有bug。
结论:
往表auth_permissions里面插入记录而已。
鉴于只对子类中的最后一个模型起作用(包括permissions属性),因此不能作为公共属性。
django 1.7+ default_permissions的更多相关文章
- Django模型类Meta元数据详解
转自:https://my.oschina.net/liuyuantao/blog/751337 简介 使用内部的class Meta 定义模型的元数据,例如: from django.db impo ...
- django _meta方法
models.Book._meta.'concrete_model': <class 'books.models.Book'> models.Book._meta.'related_fke ...
- Django的Model上都有些什么
Django的Model上都有些什么 modelinfo= ['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__' ...
- Django 模型和数据库 总结
模型和数据库 模型 首先我们在创建一个model的时候,这个类都是继承自 django.db.models.Model, 各种Model Field类型 AutoField,自动增长的IntegerF ...
- 模型的元数据Meta -- Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- 【Django】模型层说明
[Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...
- Django 模型层
基本操作 1.meta类属性汇总 属性名 用法 举例代码 abstract 如果设置abstract=True则这个模式是一个抽象基类 db_table 定义model在数据库中的表名称,如果不定 ...
- 三 Django模型层之Meta
模型的Meta选项 本文阐述所有可用的元数据选项,你可以在模型的Meta类中设置他们 Meta选项 abstract 如果为True,就表示抽象基类 app_label 如果模型在INSTALLED_ ...
- django之ModelBase类及mezzanine的page link类
class ModelBase(type): """ Metaclass for all models. """ def __new__(c ...
随机推荐
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【二】——使用Repository模式构建数据库访问层
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在数据访问层应用Repository模式来隔离对领域对象的细节操作是很有意义的.它位于映射层 ...
- Nvidia Nsight + .NET
https://devtalk.nvidia.com/default/topic/804306/nsight-4-5-can-t-debug-net-applications/ http://comm ...
- GLSL Debugger的姿势
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGLShaderBuilder ...
- mono中显示debug信息(filename/lineno)
一直发现 mono 的 traceback 没有 fliename.lineno,很奇怪.研究了下,原来编译和运行时要加参数的. dmcs -debug /r:xunit.dll /t:library ...
- Autofac.Integration.Web分析
using System; using System.Web; using Autofac.Core.Lifetime; namespace Autofac.Integration.Web { /// ...
- Winform打包工具SetupFactory 9 的使用
写了个WinForm的小程序..以前没打过包..只是直接把Bin里的东西复制出来使用..自己使用是足够.但是发给别人毕竟不太好看(不牛逼)..所以就想着打包.. Vs2012自带的有打包的功能..相信 ...
- JavaScript 五种(构造方式)继承
一.对象冒充 function Parent(username){ this.username = username; this.hello = function(){ alert(this.user ...
- 用jquery写循环播放div -2
前面所说的class html元素标签的写法也要有层次性, 这个层次性其实也就是常说的 css类写法要有一个"命名空间, 名字空间" "namespace" 在 ...
- TTFB-首字节时间简介
百度站长工具里看到有一个"首字节时间"的建议,第一次听说,还真不知道是什么东东.百度站长工具里面的解释是:"浏览器开始收到服务器响应数据的时间=后台处理时间+重定向时间, ...
- C#中的抽象方法和虚方法有什么区别?
抽象方法是只有定义.没有实际方法体的函数,它只能在抽象函数中出现,并且在子类中必须重写:虚方法则有自己的函数体,已经提供了函数实现,但是允许在子类中重写或覆盖.重写的子类虚函数就是被覆盖了.