mirror of https://gitlab.crans.org/bde/nk20
[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.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
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 _
|
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
|
# A json encoded Q object with the following grammar
|
||||||
# query -> [] | {} (the empty query representing all objects)
|
# query -> [] | {} (the empty query representing all objects)
|
||||||
# query -> ['AND', query, …]
|
# query -> ['AND', query, …] AND multiple queries
|
||||||
# -> ['OR', query, …]
|
# | ['OR', query, …] OR multiple queries
|
||||||
# -> ['NOT', query]
|
# | ['NOT', query] Opposite of query
|
||||||
# query -> {key: value, …}
|
# query -> {key: value, …} A list of fields and values of a Q object
|
||||||
# key -> string
|
# key -> string A field name
|
||||||
# value -> int | string | bool | null
|
# value -> int | string | bool | null Literal values
|
||||||
# -> [parameter]
|
# | [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:
|
# Examples:
|
||||||
# Q(is_admin=True) := {'is_admin': ['TYPE', 'bool', 'True']}
|
# Q(is_admin=True) := {'is_admin': ['TYPE', 'bool', 'True']}
|
||||||
|
@ -88,6 +95,26 @@ class Permission(models.Model):
|
||||||
self.full_clean()
|
self.full_clean()
|
||||||
super().save()
|
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):
|
def _about(_self, _query, **kwargs):
|
||||||
self = _self
|
self = _self
|
||||||
query = _query
|
query = _query
|
||||||
|
@ -110,6 +137,9 @@ class Permission(models.Model):
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
# It is a parameter we query its primary key
|
# It is a parameter we query its primary key
|
||||||
q_kwargs[key] = kwargs[value[0]].pk
|
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:
|
else:
|
||||||
q_kwargs[key] = value
|
q_kwargs[key] = value
|
||||||
return Q(**q_kwargs)
|
return Q(**q_kwargs)
|
||||||
|
|
Loading…
Reference in New Issue