【问题标题】:How to change the output of the models.ForeignKey in Django?如何在 Django 中更改 models.ForeignKey 的输出?
【发布时间】:2021-07-01 22:10:52
【问题描述】:

如何在下面的自定义字段中更改models.ForeignKey 字段的输出?

自定义字段:

class BetterForeignKey(models.ForeignKey):

    def to_python(self, value):
        print('to_python', value)
        return {
            'id': value.id,
            'name_fa': value.name_fa,
            'name_en': value.name_en,
        }

    def get_db_prep_value(self, value, connection, prepared=False):
        print('get_db_prep_value')
        return super().get_db_prep_value(value, connection, prepared)

    def get_prep_value(self, value):
        print('get_prep_value')
        return super().get_prep_value(value)

并用于以下模型:

class A(models.Model):
    ...
    job_title = BetterForeignKey(JobTitle, on_delete=models.CASCADE)

我想更改以下print(a.job_title) 语句的输出:

>>> a = A.objects.filter(job_title__isnull=False).last()
get_db_prep_value
get_prep_value

>>> print(a.job_title)
Developer

【问题讨论】:

    标签: python django django-models django-rest-framework django-orm


    【解决方案1】:

    按照Django documentation 中的建议在您的模型上定义__str__() 方法:

    class BetterForeignKey(models.ForeignKey):
    
        def __str__():
            return 'my nicely printable string representation of the object'
    

    【讨论】:

    • 感谢您的回复,我之前尝试过__str__的方法,但它不起作用:(
    • 鉴于此回复和其他答案,我不确定您想要实现什么。你到底想用这个做什么?
    • 我覆盖了models.ForeignKey 以将字段的输出从str 修改为dict。例如,print(a.job_title) 返回了一个字符串,我想将其更改为 dict
    • 换句话说,我正在处理一个在所有模型中都使用models.ForeignKey 的项目。此外,所有 API 都将 ForeignKeys 的 __str__ 返回给用户。我想在不更改所有 API 的情况下序列化所有 ForeignKey。
    • 我仍然不确定我是否了解您的用例。在什么情况下您需要dict,在什么情况下您需要str?问题是您不能同时获得两者,您需要切换字段的类型。即使您使用__repr__,您也只能获得值的字符串表示形式,而不是您的dict。另外我很确定当你改变它时你会破坏一些东西。 我想在不更改所有 API 的情况下序列化所有 ForeignKey。 是什么意思?你不能用模型函数来支持你的业务逻辑吗?
    【解决方案2】:

    为什么不在这里使用带注释的字段?

    from django.db.models import F
    a = A.objects.annotate(job_title_name=F("job_title__name")).filter(job_title__isnull=False).last()
    
    print(a.job_title_name)
    

    如果您更改 models.py 中字段的实现,以后可能会导致未知错误。

    【讨论】:

    • 我在许多 API 中使用了 A 模型,我不想更改所有 API 中的查询。所以,我开发了一个自定义字段来修改models.ForeignKey的一些行为
    • 我认为您将不得不修改查询。如果您不这样做,那么由于 job_title 是 ForeignKey,您将对数据库进行 n+1 查询。您也可以在序列化程序级别处理此问题。
    • 您能解释一下吗?我认为这个解决方案和你的解决方案在数据库查询方面没有区别。
    猜你喜欢
    • 2021-10-06
    • 2011-05-16
    • 2013-10-02
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 2022-12-17
    • 2013-10-31
    相关资源
    最近更新 更多