Функция взять объект Django и вернуть его, завернутый в QuerySet? - PullRequest
2 голосов
/ 09 ноября 2019

Как мне взять объект Django и обернуть его, чтобы он стал QuerySet с одним элементом?

m: SomeModel = SomeModel.objects.get(pk=8)

Однако в более поздних функциях ожидается, что m будет QuerySet (даже с длиной 1).

Ответ ниже работает, если вам нужно только обернуть определенные модели, но есть ли способ сделать что-то вроде приведенного ниже псевдокода?

def generic_model2qs(m: Model) -> "QuerySet[Model]":
    return m.get_model().objects.filter(pk=m.pk)

Есть ли у Django что-то вроде .get_model()функция

1 Ответ

2 голосов
/ 09 ноября 2019

Один из способов сделать это - что-то вроде приведенной ниже функции

def wrap_some_model(m: SomeModel) -> "QuerySet[SomeModel]":
    return SomeModel.objects.filter(pk=m.pk)

Однако это не общий случай, и его необходимо будет повторно реализовать для каждой отдельной модели.


Более общий ответ с подсказками из этого ответа для получения имени модели от неизвестного объекта , который я реализовал для своего собственного проекта:

def self_as_qs(s, model: Optional[models.Model] = None) -> "QuerySet[models.Model]":
    """
    Takes the input and returns it wrapped in a QuerySet
    :param s: the thing you want to transform
    :param model: optional specification to stop errors when using potentially-heterogeneous (nested) Iterables
    :return: A QuerySet representation of the input
    """

    # since you can't create a generic empty QuerySet
    generic_empty: QuerySet = model.objects.none() if model else SomeModel.objects.none()

    if isinstance(s, QuerySet) and not model:  # check inner QS if a model is specified
        return s  # it's already a QuerySet

    if isinstance(s, Iterable):
        # only works if all items are of the same model
        n = generic_empty
        for item in s:
            n = n | self_as_qs(item, model)  # handle nested lists
        return n

    if not s:
        return generic_empty
    if model and not isinstance(s, type(model.objects.all()[0])):
        return generic_empty

    # for future extensibility
    m = type(s)
    n = [s.pk]
    return m.objects.filter(pk__in=n)

Примечания:

...