2

I have 10 model classes and I wanted to check whether the passed data is available in table or not. I've a plan in mind that I can create a function which will take arguments of modelclass name, attribute to check and value of that field. from data import models

def IsAvailable(model, attr, val):
  # Here I wanted to create object of given model class and validate whether the attr has the give value.
  obj = getattr(models, model)
  res = obj.objects.get(attr=val)
  return res

This will not work because attr is not a field in the given model. Can somebody help me here ?

Jan Eglinger
  • 3,995
  • 1
  • 25
  • 51
YSK
  • 539
  • 1
  • 5
  • 9

1 Answers1

3

You probably want ** keyword pass-through:

def IsAvailable(model, attr, val):
    obj = getattr(models, model)        
    res = obj.objects.get(**{attr: val})
    return res

This passes the dictionary {attr: val} as keyword arguments to get(), i.e. {'foo': 'bar'} calls get(foo='bar'}.

Bonus points for making this generic:

def IsAvailable(model, **kwargs):
    obj = getattr(models, model)        
    res = obj.objects.get(**kwargs)
    return res

This lets you call IsAvailable(model, attr1=val1, attr2=val2), testing the availabilty of all attributes which might even be more convenient.

In Django 1.7 you can also resolve the model by name for the whole project across applications (also possible in django < 1.7, but using a different method).

from django.apps import apps

def get_model_dotted(dotted_model_name):
    app_label, model_name = dotted_model_name.split(".", 1)
    return apps.get_model(app_label, model_name)

def IsAvailable(model, **kwargs):
    model = get_model_dotted(model_name)
    res = model.objects.get(**kwargs)
    return res;

Use as IsAvailable('app1.model1', attr1=value1).

Remember that get() raises MultipleObjectsReturned when more than one object matches the filter, so you might actually want

res = model.objects.filter(**kwargs)

or even only

return model.objects.filter(**kwargs).exists()
Community
  • 1
  • 1
dhke
  • 15,008
  • 2
  • 39
  • 56