mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
[permission] Add F object support
This commit is contained in:
parent
2b49effebb
commit
982a5ae009
@ -5,7 +5,7 @@ import operator
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.db.models import F, Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@ -58,13 +58,20 @@ class Permission(models.Model):
|
||||
|
||||
# A json encoded Q object with the following grammar
|
||||
# query -> [] | {} (the empty query representing all objects)
|
||||
# query -> ['AND', query, …]
|
||||
# -> ['OR', query, …]
|
||||
# -> ['NOT', query]
|
||||
# query -> {key: value, …}
|
||||
# key -> string
|
||||
# value -> int | string | bool | null
|
||||
# -> [parameter]
|
||||
# query -> ['AND', query, …] AND multiple queries
|
||||
# | ['OR', query, …] OR multiple queries
|
||||
# | ['NOT', query] Opposite of query
|
||||
# query -> {key: value, …} A list of fields and values of a Q object
|
||||
# key -> string A field name
|
||||
# value -> int | string | bool | null Literal values
|
||||
# | [parameter] A parameter
|
||||
# | {'F': oper} An F object
|
||||
# oper -> [string] A parameter
|
||||
# | ['ADD', oper, …] Sum multiple F objects or literal
|
||||
# | ['SUB', oper, oper] Substract two F objects or literal
|
||||
# | ['MUL', oper, …] Multiply F objects or literals
|
||||
# | int | string | bool | null Literal values
|
||||
# | ['F', string] A field
|
||||
#
|
||||
# Examples:
|
||||
# Q(is_admin=True) := {'is_admin': ['TYPE', 'bool', 'True']}
|
||||
@ -88,6 +95,26 @@ class Permission(models.Model):
|
||||
self.full_clean()
|
||||
super().save()
|
||||
|
||||
@staticmethod
|
||||
def compute_f(_oper, **kwargs):
|
||||
oper = _oper
|
||||
if isinstance(oper, list):
|
||||
if len(oper) == 1:
|
||||
return kwargs[oper[0]].pk
|
||||
elif len(oper) >= 2:
|
||||
if oper[0] == 'ADD':
|
||||
return functools.reduce(operator.add, [compute_f(oper, **kwargs) for oper in oper[1:]])
|
||||
elif oper[0] == 'SUB':
|
||||
return compute_f(oper[1], **kwargs) - compute_f(oper[2], **kwargs)
|
||||
elif oper[0] == 'MUL':
|
||||
return functools.reduce(operator.mul, [compute_f(oper, **kwargs) for oper in oper[1:]])
|
||||
elif oper[0] == 'F':
|
||||
return F(oper[1])
|
||||
else:
|
||||
return oper
|
||||
# TODO: find a better way to crash here
|
||||
raise Exception("F is wrong")
|
||||
|
||||
def _about(_self, _query, **kwargs):
|
||||
self = _self
|
||||
query = _query
|
||||
@ -110,6 +137,9 @@ class Permission(models.Model):
|
||||
if isinstance(value, list):
|
||||
# It is a parameter we query its primary key
|
||||
q_kwargs[key] = kwargs[value[0]].pk
|
||||
elif isinstance(value, dict):
|
||||
# It is an F object
|
||||
q_kwargs[key] = compute_f(query['F'], **kwargs)
|
||||
else:
|
||||
q_kwargs[key] = value
|
||||
return Q(**q_kwargs)
|
||||
|
Loading…
Reference in New Issue
Block a user