【问题标题】:Get verbose name of foreign key from objects _meta dynamically in Django在Django中动态地从对象_meta中获取外键的详细名称
【发布时间】:2018-09-19 16:30:02
【问题描述】:

为简单起见,使用如下模型:

 class Plan(models.Model)
     name = models.CharField(max_length=255, verbose_name="Phone Plan Name")
     monthly_charge = models.FloatField()
 class Company(models.Model):
     name = models.CharField(max_length=255, verbose_name="Company Full Name")
     phone_plan = models.ForeignKey(Plan)
 class Client(models.Model):
     name = models.CharField(max_length=255, verbose_name="Client Full Name")
     company = models.ForeignKey(Company)

给定一个字符串,我想知道是否有一种简单的方法可以检索模型属性的详细名称,即使该字符串遍历外键。

我知道我可以通过

获得Client 属性的详细名称
Client._meta.get_field("name").verbose_name 

这将导致“客户全名”。

但是如果我有字符串“company__phone_plan__name”,我不能简单地使用

Client._meta.get_field("company__phone_plan__name").verbose_name

到达“电话计划名称”,因为它会产生错误。

这些字符串将是动态的,所以我想知道获得属性正确详细名称的最简单方法是什么,即使它遍历模型也是如此?

这个特例使用的是 Django 1.11

【问题讨论】:

    标签: django django-models meta


    【解决方案1】:

    这不是很好的答案,但如果你需要你想要的,你可以使用这个功能:

    def get_verbose_name(model, string):
        fields = string.split('__')
    
        for field_name in fields[:-1]:
            field = model._meta.get_field(field_name)
    
            if field.many_to_one:
                model = field.foreign_related_fields[0].model
            elif field.many_to_many or field.one_to_one or field.one_to_many:
                model = field.related_model
            else:
                raise ValueError('incorrect string')
    
        return model._meta.get_field(fields[-1]).verbose_name
    

    此函数获取模型名称和字符串并返回详细名称

    你可以这样使用它:

    get_verbose_name(Client, 'company__phone_plan__name')
    

    【讨论】:

    • 这似乎比我的建议实用得多;这很好用(我在Django 1.11 测试过)
    • 这个答案行得通!谢谢你。我希望 Django 有一个内置的班轮来处理这个问题,但这绝对足够了。
    【解决方案2】:

    如果您正在使用模型的实例,那么您可以试试这个:

    c = Client.objects.first()
    
    # c._meta.get_field('company').verbose_name
    # c.company._meta.get_field('phone_plan').verbose_name
    c.company.phone_plan._meta.get_field('name').verbose_name
    

    如果您只使用类,那么它会更复杂:

    field_company = Client._meta.get_field('company')
    field_phone_plan = field_company.rel.to._meta.get_field('phone_plan')
    field_name = field_phone_plan.rel.to._meta.get_field('name')
    field_name.verbose_name
    
    # or one long line
    s = Client._meta.get_field('company') \
        .rel.to._meta.get_field('phone_plan') \
        .rel.to._meta.get_field('name') \
        .verbose_name
    

    编辑: 用户@AndreyBerenda 指出Django 2.1 中的第二个选项对他不起作用;我只在问题中指定的1.11 进行了测试。

    【讨论】:

    • 你想对 db 做几个查询只是为了得到详细的名字,这不是很好。第二选择不起作用(django 2.1)(AttributeError:'ForeignKey'对象没有属性'rel')
    • @AndreyBerenda 是的,第一个选项会命中很多数据库。第二个选项在django 1.11 中对我有用,并且该版本在问题中指定。
    猜你喜欢
    • 2018-09-13
    • 2020-06-26
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 2016-09-29
    • 2012-12-24
    • 1970-01-01
    • 2017-10-03
    相关资源
    最近更新 更多