Python Django:使用延迟查询时获取模型类型

Python Django:使用延迟查询时获取模型类型,python,django,django-models,Python,Django,Django Models,使用defer(…)query命令时,Django返回的类与原始模型不同。使用“延迟”字段时,如何动态获取模型的名称 代码: obj_nodefer = model_class.objects.filter(title="foo")[0] model_name = str(type(obj_nodefer)) # Works just fine obj_defer = model_class.objects.filter(title="foo").defer("content")[0] mod

使用
defer(…)
query命令时,Django返回的类与原始模型不同。使用“延迟”字段时,如何动态获取模型的名称

代码:

obj_nodefer = model_class.objects.filter(title="foo")[0]
model_name = str(type(obj_nodefer)) # Works just fine

obj_defer = model_class.objects.filter(title="foo").defer("content")[0]
model_name = str(type(obj_defer)) # Does't return the right name because of defer above.

如何从
obj\u defer
获取模型名称?

您可以访问
obj.\uu class\uuu

  >>> print obj.__class__
  <class 'product.models.Product_Deferred_name'>
  >>> print obj.__class__.__name__
  Product_Deferred_name
  >>> print obj.__class__.__name__.split("_")[0]
  Product

在django 1.4中,延迟类的构造如下:

def deferred_class_factory(model, attrs):
    """
    Returns a class object that is a copy of "model" with the specified "attrs"
    being replaced with DeferredAttribute objects. The "pk_value" ties the
    deferred attributes to a particular instance of the model.
    """
    class Meta:
        proxy = True
        app_label = model._meta.app_label

    # The app_cache wants a unique name for each model, otherwise the new class
    # won't be created (we get an old one back). Therefore, we generate the
    # name using the passed in attrs. It's OK to reuse an existing class
    # object if the attrs are identical.
    name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs))))
    name = util.truncate_name(name, 80, 32)

    overrides = dict([(attr, DeferredAttribute(attr, model))
            for attr in attrs])
    overrides["Meta"] = Meta
    overrides["__module__"] = model.__module__
    overrides["_deferred"] = True
    return type(name, (model,), overrides)
所以,理论上,你应该通过做

type(type(deferred))

要获取非延迟模型,请执行以下操作

t = type(obj)
if t._deferred:
  t = t.__base__

在延迟类上,您还可以使用以下命令获取原始类,而无需操作
\uuuuuu class\uuuu.\uuuuuu name\uuuuu
字符串:

obj._meta.concrete_model
'product.models.ProductModelName'

obj._meta.concrete_model._meta.app_label
'product'

obj._meta.concrete_model._meta.model_name
'productmodelname'

这不起作用,你最终会得到
试试看,obj.\uuuuu类\uuuu.\uuuu名称\uuu仍然不起作用。我想以
结束,而不是
来吧。。。像那样使用split似乎太麻烦了,不是吗?如果我在模型的名称中有一个下划线怎么办?然后,像这样尝试--打印p.\u class.\u.\u name.\u.replace(“\u Deferred\u name”,”)--:d
t.\u base.\u.\u
对我不起作用,但我运行的是django的旧版本(v1.3)。我运行的是1.6,但是
\uuuuu base\uuuu
是python的东西;或者你可以做
t.。\uuuu base\uuu0]
这对我现在来说确实有效。。。不知道我以前做错了什么。但我认为更安全、更好的方法是:
t=type(obj);如果hasattr(t,“'u deferred')和t.'u deferred:t=t.,'u model
的元代理\u也在常规模型上设置;但在任何情况下,都可以使用3-arg getattr:
getattr(t,'u deferred',False)
obj._meta.concrete_model
'product.models.ProductModelName'

obj._meta.concrete_model._meta.app_label
'product'

obj._meta.concrete_model._meta.model_name
'productmodelname'