[Django]-Check if model field exists in Django

22👍

hasattr(cls,field) will not work in all cases, for example where mixins are used. A safe test is:

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

or

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

            if field:
              .. do stuff here

17👍

You can use getattr to return a default value if the field does not exist.. like below

getattr(table, field, False)

7👍

Your ‘category_id’ field is a hidden field in the terminology of https://docs.djangoproject.com/en/1.10/ref/models/meta/ . It can’t be retrieved by get_field.

Maybe loop over all the fields and check their names; get_fields can return hidden fields:

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

If you need to care about fields that have their db_column changed from their default, you can test field.db_column too (but it is unset if it wasn’t set explicitly).

7👍

But this one doesn’t:

Post.field_exists(‘category_id’) # > False

This is the actual field name in db and I need to check for it like this. How can I do it in django?

The case for everything aside from the _id part is sufficiently answered in the other answer. For handling the _id cases, you would basically need a special conditional in addition to that answer to appropriately deal with these cases. Something resembling this:

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

The additional check is needed to assure that the field minus _id returns a ForeignKey, as opposed to some other type of field that just happens to have the same name, which would mean the name_id field on the model is invalid.

👤AlanSE

2👍

Why do you need this? The idea of Object Relational Mappers is for the classes to describe/define the database. So if you want to test the type of a Model you should use isinstance like so:

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()

Your model definitions define your schema. There should not be a reason to have to test for the existence of a field. If there is, you might not be following best practice by assigning fields with setattr?

-1👍

YourModelName.objects.filter(YourModelField=TheFieldToCheck).exists()

Leave a comment