我对Django中的模型有一个疑问,特别是关于如何指定属性,例如:“author = models.CharField ...”,连接到创建这些相同模型的实例时传递的关键字参数
我正在阅读的典型模型如下:
from django.db import models class MyModel(models.Model): Attribute = models.CharField(max_length=100)
然后,当实例化它并创建和对象时,我看到的经常是这样的:
Instance = MyModel(Attribute='some text')
这些如何连接?我知道我的'MyModel'的父类中的__init__
需要kwargs - 但我不确定它是如何处理它们的。 Django如何确保它们连接到我编写的属性?有点似乎我在模型中定义了一个属性,然后在实例化时尝试重新定义相同的属性?
谢谢!
答案 0 :(得分:1)
请注意,模型字段是 class-level 属性。在实例化时,它们实际上与关键字参数没有多大关系; Django只是迭代字段名称列表来分配kwargs的相关值。您当然可以随时为实例分配任何属性,无论它是否与类级字段定义同名。
只有当您保存模型或从数据库加载模型时,才会直接使用这些字段; Django使用它们来确定如何为每个字段保存或加载数据。
答案 1 :(得分:1)
Django模型字段成为python描述符。让我解释一下它是如何工作的。如果你打开你的django shell,你可以写这样的东西
>>> from yourapp.models import MyModel
>>> MyModel.attribute
<django.db.models.query_utils.DeferredAttribute object at 0x7f67cf3449e8>
初看起来,你可能希望看到CharField而不是DeferredAttribute。当执行ModelBase元类__ new __方法(运行时)时,使用Monkey修补,其中包含用于注册其所有模型字段并基于它们创建描述符的代码。
如果你探索DeferredAttribute类,你很容易发现这实际上是一个非数据描述符类,因为它有__ get __方法,没有__ set __方法。缺乏__ set __方法意味着 - 当您尝试设置属性时:
instance.attrubute = 'some text'
它被实例属性溢出,现在它实际上只是一个常见的实例属性。并且DeferredAttribute类也有__ init __方法,如下所示:
def __init__(self, field_name, model):
self.field_name = field_name
如您所见,它具有field_name属性。
>>> MyModel.attribute.field_name
'attribute'
此名称在__ get __方法中用于从MyModel实例获取值(如果未直接设置它)
这是一个相当复杂的系统,但我相信Django使用字段的方式是python描述符和元类功能的一个很好的例子。