关键字参数如何与模型交互? Django的

时间:2018-01-31 08:44:40

标签: python django

我对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如何确保它们连接到我编写的属性?有点似乎我在模型中定义了一个属性,然后在实例化时尝试重新定义相同的属性?

谢谢!

2 个答案:

答案 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描述符和元类功能的一个很好的例子。