#django #django-rest-framework #annotate #django-annotate
#django #django-rest-framework #аннотировать #django-аннотировать
Вопрос:
У меня есть такая таблица:
class SystemPushLog(models.Model):
...
user_id = models.IntegerField(null=True)
Как вы можете видеть в приведенной выше модели, user_id
это a IntegerField
, а не внешний ключ. Потому что информация о пользователях в системе извлекается из вызовов gRPC. Теперь я хочу упорядочить набор last_login
запросов, который является полем в информации о пользователе.
Я пробовал с annotate
подобным в get_queryset
:
def get_queryset(self):
queryset = super().get_queryset().annotate(
last_login=self.__class__.get_user_last_login(F('user_id'))
)
И ниже get_user_last_login
:
@staticmethod
def get_user_last_login(user_id):
print('user_id', user_id) # <<< user_id F(user_id)
print('type of user_id', type(user_id)) # <<< type of user_id <class 'django.db.models.expressions.F'>
# retrieving user info from rpc call.
user = do_user_actions({'id': user_id})
return user.last_login
Как вы можете видеть, F('user_id')
переданный функции, является типом django.db.models.expressions.F
вместо фактического user_id
.
Может annotate
быть, можно просто взять несколько простых выражений, таких как annotate(off_price=F('original_price') - F('discount_price'))
.
Итак, как я должен реализовать этот удаленный порядок полей?
Ответ №1:
Если вы не возражаете против добавления поля last_login в SystemPushLog, сделав поле last_login обнуляемым, вы можете заполнить last_login, переопределив django @classmethod def create()
, тогда вы можете легко заказать свою модель, поскольку в ней есть поле last_login
Я не пробовал этого, но что-то вроде этого должно сработать
def create(self, *args, **kwargs):
if 'user_id' in kwargs and isinstance(kwargs['type'], int):
# retrieving user info from rpc call.
user = do_user_actions({'id': user_id})
kwargs['last_login'] = user.last_login
return super(SystemPushLog, self).create(*args, **kwargs)
Комментарии:
1. Но
last_login
это поле, которое будет меняться при повторном входе пользователя в систему, поэтому я должен получить его динамически. В противном случае я бы сделал так, как вы сказали.2. @Gorgine Это правда, но даже если вы сможете каким-то образом передать F(‘id’), user.last_login вернет не выражения в QuerySet.annotate() . может быть, вы можете заполнять данные каждый раз, когда запрашиваете get_queryset(self) ?