Как фильтровать с помощью перечисления или строки и получить тот же результат?

#python #django #enums

#python #django #перечисления

Вопрос:

Мне трудно использовать перечисления в Django.

Это моя модель запроса:

 class RequestStatuses(Enum):
    new = 'new'
    sent = 'sent'
    done = 'done'


class Request(BaseModel):


    request_number =    models.PositiveIntegerField(default=0)
    type =              models.CharField(max_length=31, blank=True, null=True)

    status =            models.CharField(
        max_length=31,
        choices=[(a.name, a.value) for a in RequestStatuses],
        default=RequestStatuses.new
    )

    sensor =            models.ForeignKey(Sensor, on_delete=models.SET_NULL, blank=True, null=True)
    device =            models.ForeignKey(Device, on_delete=models.SET_NULL, blank=True, null=True)
    user =              models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
    payload =           models.TextField(blank=True, null=True)
  

Есть разница, когда я создаю запись с использованием string или типа enum, что действительно раздражает…

Это работает просто отлично:

     device = Device.objects.create(serial_number=1)
    request = Request(
        device=self.device,
        status=RequestStatuses.sent
    )
    request.save()
    try:
        request = device.request_set.filter(
            status=RequestStatuses.sent
        )[0]
    except IndexError:
        print(device.request_set.all()[0].status)
        pass
  

Но это вызывает исключение

     device = Device.objects.create(serial_number=1)
    request = Request(
        device=device,
        status='sent'
    )
    request.save()
    try:
        request = device.request_set.filter(
            status=RequestStatuses.sent
        )[0]
    except IndexError:
        print(device.request_set.all()[0].status)
        pass
  

Когда я пытаюсь фильтровать с помощью status=RequestStatuses.sent.value или просто с помощью sent string, первый пример выдает исключение, а второй работает.

В чем смысл перечислений, когда вы не можете фильтровать их по строке или наоборот? Как я могу заставить это работать с api, который будет передавать строку в фильтр? Или это просто какая-то проблема с кэшем?

Ответ №1:

В модели запроса вам нужно изменить определение «статуса»

 status = models.CharField(
        max_length=31,
        choices= RequestStatuses.choices(),
        default=RequestStatuses.new.value
    )

  

Затем вы можете фильтровать следующим образом.

 request = Request.objects.filter(status=RequestStatuses.new.name)

  

Ответ №2:

Я, честно говоря, не знаю причину, почему и правильно ли это делать, но добавление функций __repr__ и __str__ в перечисление решило проблему.

 class RequestStatuses(Enum):
    new = 'new'
    sent = 'sent'
    done = 'done'

    def __repr__(self):
        return self.name

    def __str__(self):
        return self.name