问题描述
所以我有几个模特和这样的经理。
class Member(BaseModel):
objects = models.Manager()
permissions = api_managers.PermissionManager()
Box = models.ForeignKey('api_backend.Box',on_delete=models.CASCADE)
roles = models.ManyToManyField('api_backend.Role',through='api_backend.MemberRole')
required_FIELDS = [Box,user]
class Role(BaseModel):
objects = models.Manager()
positions = api_managers.PositionalManager()
name = models.CharField(default='new role',max_length=100,validators=[MinLengthValidator(2)])
permissions = BitField(flags=permission_flags,default=default_perm_flags,db_index=True)
is_default = models.BooleanField(default=False,db_index=True)
position = models.PositiveSmallIntegerField(db_index=True,default=0)
Box = models.ForeignKey('api_backend.Box',on_delete=models.CASCADE)
required_FIELDS = [name,Box]
class MemberRole(BaseModel):
objects = models.Manager()
member = models.ForeignKey('api_backend.Member',on_delete=models.CASCADE)
role = models.ForeignKey('api_backend.Role',on_delete=models.CASCADE)
required_FIELDS = [member,role]
class Overwrite(BaseModel):
objects = models.Manager()
allow = BitField(flags=permission_flags,null=True,blank=True,db_index=True)
deny = BitField(flags=permission_flags,db_index=True)
channel = models.ForeignKey('api_backend.Channel',on_delete=models.CASCADE,editable=False)
Box = models.ForeignKey('api_backend.Box',editable=False)
role = models.OnetoOneField('api_backend.Role',db_index=True)
required_FIELDS = [role,channel,Box]
from memoize import memoize
class PermissionManager(models.Manager):
def __init__(self):
super().__init__()
@transaction.atomic
@memoize(timeout=3600)
def get_overwrites(self,channel):
assert channel.Box == self.model.Box,'invalid channel given'
permissions = self.get_base_permissions
if channel.Box.owner == self.model.user:
return permissions
try:
# get the default everyone role's overwrite
default_role = self.model.Box.roles.get(is_default=True)
default_overwrite = default_role.overwrite_set.get(channel=channel)
except ObjectDoesNotExist:
pass
else:
permissions &= set(~default_overwrite.deny)
permissions |= set(default_overwrite.allow)
member_role_ids = [role.id for role in self.model.roles.all()]
overwrite_roles = channel.overwrites.filter(role__id__in=member_role_ids)
deny,allow = None,None
for overwrite in overwrite_roles:
deny |= set(overwrite.deny)
allow |= set(overwrite.allow)
permissions &= ~deny
permissions |= allow
return permissions
如您所见,我的经理上的 get_overwrites
方法是一个执行起来非常昂贵的过程。因此,我想缓存特定参数的值以提高性能。
为此,我目前正在使用 django-memoize。 每当模型发生任何更新时,我都会像这样使缓存无效。
@receiver(post_delete,sender=api_models.Overwrite)
def on_overwrite_delete(instance=None,**kwargs):
delete_memoized(api_models.Member.permissions.get_overwrites,instance.channel)
@receiver(post_save,sender=api_models.Overwrite)
def on_overwrite_save(instance=None,instance.channel)
@receiver(post_delete,sender=api_models.MemberRole)
def on_member_role_delete(instance=None,**kwargs):
for overwrite in instance.role.overwrite_set.all():
delete_memoized(instance.member.permissions.get_overwrites,overwrite.channel)
@receiver(post_save,sender=api_models.MemberRole)
def on_member_role_create(instance=None,overwrite.channel)
@receiver(post_delete,sender=api_models.Role)
def on_role_delete(instance=None,**kwargs):
for overwrite in instance.overwrite_set.all():
delete_memoized(api_models.Member.permissions.get_overwrites,sender=api_models.Role)
def on_role_save(instance=None,overwrite.channel)
但是,这种方法是否值得推荐?有没有更好的方法来做同样的事情? 现在,我觉得我必须坚持这一点,因为 django 在 3.0 版本中放弃了对 LRU-cache 的支持
此外,我认为 memoize-deletion 过程非常无效 (因为在这种情况下我也必须遵循反向关系)
有人可以帮我吗? 非常感谢!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)