Django ORM как использовать case when и использовать значение других объектов с фильтром?
Итак, у меня есть 2 модели:
- label, модели label используется для определения того, что является меткой кода "типа" пример купона тип кода 2, истек срок действия метки.
- модель купона используется для данных о купоне .
Итак, я хочу использовать случай, когда нужно отфильтровать данные и получить название статуса, например, если дата купона больше, чем сегодня, то он просрочен, иначе он активирован, и я хочу получить значение названия статуса из другой модели, называемой моделью label, вот моя текущая попытка
label_status = Labels.objects.filter(label_type='coupon_status').all()
data = Vouchers.objects.
annotate(
coupon_status_name=Case(
When(status=0, valid_dt__lte=date.today(), then=Value(system_used.filter(label_code="2").first().label_name)),
default=Value(label_status.filter(label_code=status).first().label_name),
output_field=CharField()
)
).all()
я могу фильтровать первую строку в функции When(), но я не могу фильтровать объекты label в параметре default функции case, которые ссылаются на купон динамически, так как я могу это сделать? Я пытался использовать OuterRef(), как
default=Value(label_status.filter(label_code=OuterRef(status)).first().label_name)
но это дает мне эту ошибку:
Этот кверисет содержит ссылку на внешний запрос и может использоваться только в подзапросе.
любая помощь будет принята с благодарностью, и пожалуйста не просите меня изменить структуру базы данных спасибо.
Вы пытаетесь использовать несвязанный объект в запросе, который запрашивает отношение, что и является причиной возникновения ошибки. Мне кажется немного не интуитивным использовать модель подобным образом, в то время как Django используется для запросов к реляционной базе данных.
Похоже, что Label и Coupon взаимодействуют друг с другом. Так как Label является разновидностью статуса Coupon
.
вы должны попытаться добавить внешний ключ между ними. Это будет намного проще.
Что-то вроде этого :
class Coupons(models.Model):
coupon_name = models.CharField(max_length=200, null=False)
coupon_desc= models.CharField(max_length=200, null=False)
valid_date = models.DateField(null=False)
status = models.IntegerField(null=False)
label_status = models.ForeignKey(Label)
Также не следует перезаписывать primary_key, Django не очень любит это, это может вызвать некоторые ошибки.
поэтому я нашел решение для этого, используя subquery()
и OuterRef()
label_status = Labels.objects.filter(label_type='coupon_status').all()
data = Coupons.objects.
annotate(
coupon_status_name=Case(
When(status=0, valid_date__lte=date.today(), then=Subquery(label_status.filter(label_code="2").values('label_name'))),
default=Subquery(label_status.filter(label_code=OuterRef('status').values('label_name')),
output_field=CharField()
)
).all()