检查Django中是否存在模型字段

时间:2015-03-13 14:24:23

标签: python django

这是我提出的解决方案,在我的models.py中:

from django.db import models

@classmethod
def model_field_exists(cls, field):
    try:
        cls._meta.get_field(field)
        return True
    except models.FieldDoesNotExist:
        return False

models.Model.field_exists = model_field_exists

并使用它:

Post.field_exists('title') # > True or False

问题来自外键,我的Post模型属于一个类别,此检查有效:

Post.field_exists('category') # > True

但是这个没有:

Post.field_exists('category_id') # > False

这是db中的实际字段名称,我需要像这样检查它。我怎么能在django中做到这一点?

5 个答案:

答案 0 :(得分:9)

hasattr(cls,field)在所有情况下都不起作用,例如使用mixins的情况。安全测试是:

            try:
                model._meta.get_field(field)
                .. do stuff here
            except FieldDoesNotExist:
                pass

            field = None
            try:
                field = model._meta.get_field(field)
            except FieldDoesNotExist:
                pass

            if field:
              .. do stuff here

答案 1 :(得分:4)

如果该字段不存在,您可以使用getattr返回默认值。如下所示

getattr(table, field, False)

答案 2 :(得分:4)

您的'category_id'字段是https://docs.djangoproject.com/en/1.10/ref/models/meta/术语中的隐藏字段。它不能被get_field检索。

可能遍历所有字段并检查其名称; get_fields可以返回隐藏字段:

for field in cls._meta.get_fields(include_hidden=True):
    if field.name == field:
        return True
return False

如果您需要关心db_column已更改为默认值的字段,您也可以测试field.db_column(但如果没有明确设置则未设置)。

答案 3 :(得分:2)

  

但是这个没有:

     

Post.field_exists('category_id')#>假

     

这是db中的实际字段名称,我需要像这样检查它。我怎么能在django中做到这一点?

the other answer中,_id部分以外的所有内容都得到了充分的回答。为了处理_id案例,你基本上需要一个特殊的条件以及,它可以回答这些案例。类似的东西:

if field_name.endswith('_id'):
    try:
        field = model._meta.get_field(field_name.strip('_id'))
    except FieldDoesNotExist:
        return False
    if not f.is_relation:
        return False
    return True

需要进行额外检查以确保字段减去_id返回ForeignKey,而不是恰好具有相同名称的其他类型的字段,这意味着name_id字段在模型上无效。

答案 4 :(得分:1)

你为什么需要这个?对象关系映射器的概念是用于描述/定义数据库的类。因此,如果您想测试模型的类型,您应该使用isinstance,如下所示:

if isinstance(model, Post):
    # model is a Post, Post has a publish()
    model.publish()
elif isinstance(model, Comment):
    # model is a Comment, Comment has a foo()
    model.foo()

您的模型定义定义您的架构。没有理由必须测试场的存在。如果有,您可能不会通过使用setattr分配字段来遵循最佳做法吗?