django:从该模型的实例中获取模型的最佳实践方法

Ger*_*alt 59 django

my_instance是模型MyModel.
我正在寻找一个好方法:

my_model = get_model_for_instance(my_instance)
Run Code Online (Sandbox Code Playgroud)

我没有找到任何真正直接的方法来做到这一点.到目前为止,我已经想出了这个:

from django.db.models import get_model

my_model = get_model(my_instance._meta.app_label, my_instance.__class__.__name__)
Run Code Online (Sandbox Code Playgroud)

这可以接受吗?它甚至是一种可靠的,最佳实践方式吗?
_meta.object_name有似乎提供相同的__class__.__name__.可以?好还是坏?如果是这样,为什么?

另外,如果app标签在项目范围内多次出现,我怎么知道我得到了正确的模型,例如'django.contrib.auth'中的'auth',还有'myproject.auth'?
这种情况会get_model不可靠吗?

感谢任何提示/指示和经验分享!

Wil*_*rdy 95

my_model = type(my_instance)
Run Code Online (Sandbox Code Playgroud)

为了证明这一点,您可以创建另一个实例:

my_new_instance = type(my_instance)()
Run Code Online (Sandbox Code Playgroud)

这就是为什么没有直接的方法,因为python对象已经具有此功能.

更新...

我喜欢marcinn的响应使用type(x).这与原来的答案(x.__class__)相同,但我更喜欢使用函数来访问魔法属性.以这种方式,我更喜欢使用vars(x)to x.__dict__,len(x)to x.__len__等.

更新2 ...

对于延迟实例(@Cerin在评论中提到),您可以通过访问原始类instance._meta.proxy_for_model.

  • 这不适用于使用`only()`的查询中的延迟实例或实例. (3认同)

mar*_*inn 23

my_new_instance = type(my_instance)()
Run Code Online (Sandbox Code Playgroud)


Roc*_*ite 6

至少对于Django 1.11,这应该工作(也适用于延迟实例):

def get_model_for_instance(instance):
    return instance._meta.model
Run Code Online (Sandbox Code Playgroud)

来源于此.

  • 虽然这有效,而且我之前不幸使用过它,但就“最佳实践”而言,`_meta.model` 不在 `_meta` [API](https://docs.djangoproject.com/en/2.2 /ref/models/meta/),不应该使用,`type()` 更好,pythonic。 (2认同)