如何在Django模型Meta类中自动添加CRUD权限并复用权限生成器
嘿,这问题我熟!咱们分两部分来解决,一步步把这个可复用的CRUD权限生成器搞定~
1. 如何在Django模型Meta类中自动添加CRUD权限
首先得说,Django默认会给每个模型自动生成add_<model>、change_<model>、delete_<model>、view_<model>这四个权限,但如果你想要自定义命名规则(比如你要的create_post、read_post这种更直观的命名),就需要动态生成权限元组。
核心思路是:写一个可复用的函数,让它能自动识别当前模型的信息(比如模型名称),然后生成符合你要求的权限元组,最后在模型的Meta类里把permissions字段指向这个函数的返回值就行。这样不用每个模型都手动写一遍权限,复用性拉满。
2. 可复用的
permission_generator()具体实现 要让函数能自动识别调用它的模型,我们可以用Python的inspect模块来获取调用栈,从而拿到当前的模型类。话不多说,直接上代码:
import inspect from django.db import models def permission_generator(): # 从调用栈中找到当前的模型类 call_frame = inspect.currentframe().f_back # 取出模型类对象(因为Meta类是在模型类内部定义的,所以栈里的cls就是模型类) model_class = call_frame.f_locals.get('cls') # 做个校验,确保函数是在Django模型的Meta类里调用的 if not model_class or not issubclass(model_class, models.Model): raise ValueError("permission_generator 必须在Django模型的Meta类内部调用") # 获取模型的小写名称(比如Post模型会得到'post') model_name = model_class._meta.model_name.lower() # 定义CRUD操作对应的权限码和显示名称 crud_actions = [ ('create', f'create {model_name}'), ('read', f'read {model_name}'), ('update', f'update {model_name}'), ('delete', f'delete {model_name}'), ] # 生成最终的权限元组 return tuple((f'{action}_{model_name}', display_name) for action, display_name in crud_actions)
然后在你的Post模型里直接用就行:
class Post(models.Model): name = models.CharField(max_length=20) body = models.TextField() class Meta: permissions = permission_generator()
这样生成的权限就是你要的:
( ('create_post', 'create post'), ('read_post', 'read post'), ('update_post', 'update post'), ('delete_post', 'delete post'), )
额外优化点
如果你想让显示名称更友好(比如用模型的verbose_name而不是小写的模型名),可以把model_name换成:
model_verbose_name = model_class._meta.verbose_name.lower()
然后把crud_actions里的f'create {model_name}'改成f'create {model_verbose_name}'就行。
注意事项
- 这个函数可以在任何Django模型里复用,只要在模型的
Meta类里赋值permissions = permission_generator()就好,完全不用重复写权限元组。 inspect模块在Python和Django的常见版本里都能正常工作,兼容性没问题。- 如果你的模型是继承自其他抽象模型,这个函数依然能正确识别当前模型的元数据,不用担心继承问题。
内容的提问来源于stack exchange,提问作者sgaseretto
相关产品推荐
相关产品推荐

