【问题标题】:How does django's ORM get one to one fields without having to call a functiondjango的ORM如何在不调用函数的情况下得到一对一的字段
【发布时间】:2021-01-17 23:19:49
【问题描述】:

假设我有一个像这样的 django 模型:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

创建此一对一字段后,可以通过user_instance.profile访问配置文件对象

我为 ORM 启用了日志记录,以便在我的 settings.py 文件中查看发送到数据库的查询:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'),
            'propagate': False,
        },
    },
}

然后我使用python3 manage.py shell 打开外壳并执行以下操作:

firstuser = User.objects.first()

这导致以下查询被注销:

SELECT "users_user"."id", "users_user"."password", "users_user"."last_login", "users_user"."is_superuser", "users_user"."username", "users_user"."is_staff", "users_user"."is_active", "users_user"."date_joined", "users_user"."name", "users_user"."email", "users_user"."join_date", "users_user"."date_of_birth" FROM "users_user" ORDER BY "users_user"."id" ASC LIMIT 1; args=()

我还做了:

firstuser.profile

并已注销此查询:

SELECT "users_profile"."id", "users_profile"."user_id", "users_profile"."status", "users_profile"."institute" FROM "users_profile" WHERE "users_profile"."user_id" = 1 LIMIT 21; args=(1,)

那么,当我请求相关对象时,django 如何执行查询无需在我自己的代码中调用任何函数

是否有 python 方法来覆盖如何读取类中的属性的行为?

提前致谢!

【问题讨论】:

  • 我想知道 django 是如何在不调用我的代码中的任何函数的情况下进行这些惰性求值的
  • “django 如何进行这些惰性求值”和“在我的代码中不调用任何函数”是什么意思?你的问题是什么?你想知道 django 是如何做这些事情的吗?不调用任何函数是什么意思?
  • python中的底层机制称为Descriptor Protocol
  • @NavidZarepak 在我上面提到的代码中,我读取了属性user.profile,当我访问它时,我会延迟加载配置文件对象。在我的代码中,我不调用任何类似 get_profile
  • @Wombatz 正是我想知道的,非常感谢 Wombatz!

标签: python python-3.x django django-orm


【解决方案1】:

在 python 中Descriptors 让对象自定义属性查找、存储和删除。

底层机制称为Descriptor Protocol(感谢 Wombatz 指出这一点)

property 类允许动态计算属性

例子:

import random

class MyClass:
    @property
    def random(self):
        return random.random()

my_object = MyClass()

for _ in range(3):
    print(my_object.random)

输出:

0.23871118861024354
0.877585489346098
0.9753110448271668

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 2012-05-06
    • 2017-08-17
    • 2016-01-15
    • 2016-08-06
    • 2019-05-21
    • 2011-12-13
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多