Django覆盖模型的get()方法不适用于外键 [英] Django override model get() method won't work on foreign keys

查看:63
本文介绍了Django覆盖模型的get()方法不适用于外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个定义如下的自定义模型,其中 get()方法覆盖

I have a custom model defined as following, with get() method override

class CustomQuerySetManager(models.QuerySet):
    def get(self, *args, **kwargs):
        print('Using custom manager')
        # some other logics here...
        return super(CustomQuerySetManager, self).get(*args, **kwargs)


class CustomModel(models.Model):
    objects = CustomQuerySetManager.as_manager()

    class Meta:
        abstract = True

然后我将两个模型定义为

Then I have two models defined as

class Company(CustomModel):
    name = models.CharField(max_length=40)

class People(CustomModel):
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)

如果我像 People.objects.get(pk = 1)之类直接使用 get(),则它可以正常工作,使用自定义管理器"被打印,但是如果我尝试获取外键信息,django仍然会使用默认管理器中的 get()方法,则不会打印任何内容,并且所定义的其余逻辑将不会执行,因为例子

If I use get() directly like People.objects.get(pk=1) then it works, "Using custom manager" gets printed, but if I try to get the foreign key info, django still uses the get() method from the default manager, nothing gets printed and the rest of logic defined won't get executed, for example

someone = People.objects.get(id=1)  # prints Using custom manager, custom logic executed
company_name = someone.company.name  # nothing gets printed, custom logic does not execute

即使外键模型也使用我的自定义模型类,模型中的外键字段是否使用其他管理器?有没有办法让我的自定义 get()方法对所有字段都起作用?

Is the foreign key field in a model using a different manager even though the foreign key model is also using my custom model class? Is there a way to make my custom get() method work for all fields?

推荐答案

Django文档所说的

As django doc says

默认情况下,Django使用Model._base_manager管理器的实例访问相关对象(即choice.question)时的类,而不是_default_manager在相关对象上

By default, Django uses an instance of the Model._base_manager manager class when accessing related objects (i.e. choice.question), not the _default_manager on the related object

查看更多这里.

因此,您必须告诉django模型将哪个管理器用作基本管理器,像这样:

So you have to tell django model which manager to use as base manager, like this:

class CustomModel(models.Model):
    objects = CustomQuerySetManager.as_manager()

    class Meta:
        #django will use your custom "objects" manager as base_manager
        #or you may have different managers for base and default managers
        #if you define two managers with different names
        base_manager_name = 'objects' 
        abstract = True

但是,请注意,不要从基本管理器中过滤掉任何结果.Django文档说:

But, please, pay attention that you do not filter away any results from base manager. Django doc says:

此管理器用于访问与某些对象相关的对象其他型号.在这种情况下,Django必须能够看到所有它正在获取模型的对象,因此任何可以检索到.

This manager is used to access objects that are related to from some other model. In those situations, Django has to be able to see all the objects for the model it is fetching, so that anything which is referred to can be retrieved.

因此,请勿覆盖此类管理器的 get_queryset().查看更多此处.

Therefore, do not override get_queryset() for this kind of managers. See more here.

这篇关于Django覆盖模型的get()方法不适用于外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆