获取 Django 对象并将其 return 包裹在 QuerySet 中的函数?

Function to take a Django object and return it wrapped in a QuerySet?

如何获取 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() 的功能吗?

执行此操作的一种方法类似于以下函数

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

但是,这不是一般情况,需要针对每个不同的模型重新实施。


我为自己的项目实施的 this answer for getting the model name from an unknown object 提示的更通用的答案:

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)

备注:

  • 由于使用了 | 运算符,当 运行 在 Iterable(查询集、列表、元组等)上时,顺序和嵌套结构不会被保留
  • 关于 generic_empty: QuerySet = model.objects.none() if model else SomeModel.objects.none() 的行是为了确保如果程序需要这样做,您有一个空的 QuerySet 到 return。你需要 to specify some model that you actually have here (doesn't have to be relevant to anywhere else, though), as there doesn't seem to be any generic empty QuerySet generator.