This is the solution I came up, in my 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
And use it like:
Post.field_exists('title') # > True or False
The problem comes with foreign keys, my Post model belongs to a Category, this check works:
Post.field_exists('category') # > True
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?
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
You can use getattr to return a default value if the field does not exist.. like below
getattr(table, field, False)
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With