Аннотации, возвращающие чистое значение PK вместо Django HashIDPython

Программы на Python
Ответить Пред. темаСлед. тема
Гость
 Аннотации, возвращающие чистое значение PK вместо Django HashID

Сообщение Гость »


В моем приложении пользователь может взять на себя одну из трех разных ролей.
Этих пользователей можно назначить программам, и им можно назначить три разных поля, каждое из которых предназначено исключительно для роль.
В своем API я пытаюсь опросить всех своих пользователей и аннотировать программы, в которых они работают:

Код: Выделить всё

def get_queryset(self):
queryset = (
User.objects
.select_related('profile')
.prefetch_related('managed_programs', 'supervised_programs', 'case_managed_programs')
.annotate(
programs=Case(
When(
role=RoleChoices.PROGRAM_MANAGER,
then=ArraySubquery(
Program.objects.filter(program_managers=OuterRef('pk'), is_active=True)
.values('id', 'name')
.annotate(
data=Func(
Value('{"id": '),
F('id'),
Value(', "name": "'),
F('name'),
Value('"}'),
function='concat',
output_field=CharField(),
)
)
.values('data')
),
),
When(
role=RoleChoices.SUPERVISOR,
then=ArraySubquery(
Program.objects.filter(supervisors=OuterRef('pk'), is_active=True)
.values('id', 'name')
.annotate(
data=Func(
Value('{"id": '),
F('id'),
Value(', "name": "'),
F('name'),
Value('"}'),
function='concat',
output_field=CharField(),
)
)
.values('data')
),
),
When(
role=RoleChoices.CASE_MANAGER,
then=ArraySubquery(
Program.objects.filter(case_managers=OuterRef('pk'), is_active=True)
.values('id', 'name')
.annotate(
data=Func(
Value('{"id": '),
F('id'),
Value(', "name": "'),
F('name'),
Value('"}'),
function='concat',
output_field=CharField(),
)
)
.values('data')
),
),
default=Value(list()),
output_field=ArrayField(base_field=JSONField()),
)
)
.order_by('id')
)
return queryset

This works (almost) flawlessly and gives me only 5 DB hits, perfect, or not...
The problem is that I'm using Django HashID fields for the Program PK, and this query returns the pure integer value for each Program.
I've tried a more "normal" approach, by getting the data using a

Код: Выделить всё

SerializerMethodField
:

Код: Выделить всё

@staticmethod
def get_programs(obj):
role_attr = {
RoleChoices.PROGRAM_MANAGER: 'managed_programs',
RoleChoices.SUPERVISOR: 'supervised_programs',
RoleChoices.CASE_MANAGER: 'case_managed_programs',
}
try:
programs =  getattr(obj, role_attr[obj.role], None).values_list('id', 'name')
return [{'id': str(id), 'name': name} for id, name in programs]
except (AttributeError, KeyError):
return []

This gives me the result I need, but the query quantity skyrockets. Кажется, что он не использует преимущества

Код: Выделить всё

prefetch_related
, but I don't understand how is this possible, considering I'm using the same queryset.
So, I have two options here:
  • Use the annotations but having the HashID returning, instead of integer PK
  • Have the SerializerMethodField reuse the prefetched data, instead of requerying
Is there a way to accomplish any of those?
EDIT:
A small heads-up, I've decided to use the first approach and Hash the ID manually inside the serializer

Код: Выделить всё

programs = serializers.SerializerMethodField()

@staticmethod
def get_programs(obj):
return [
{"id": str(Hashid(value=program['id'], salt=settings.SECRET_KEY, min_length=13)), "name": program['name']} for program in obj.programs
]

For now it works, but I'd be more satisfied if there's a more direct way to accomplish this.


Источник: https://stackoverflow.com/questions/781 ... ngo-hashid
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Тип возвращаемого значения задачи дает не все пути кода, возвращающие значение
    Anonymous » » в форуме C#
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Tesseract не распознает чистое изображение из обрезанного (считыватель разрешений на автомобиль)
    Anonymous » » в форуме Python
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous
  • Интерфейс как тип возвращаемого значения в Asp. Чистое ядро
    Anonymous » » в форуме C#
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Ищу чистое решение для JavaScript с активным состоянием Navbar
    Anonymous » » в форуме Html
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Ищу чистое решение для JavaScript с активным состоянием Navbar
    Anonymous » » в форуме CSS
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»