开发者

How can I introspect properties and model fields in Django?

开发者 https://www.devze.com 2023-02-09 08:39 出处:网络
I am trying to get a list of all existing model fields and properties for a given object. Is there a clean way to instrospect an object so that I can get a dict of fields and properties开发者_JAVA技巧

I am trying to get a list of all existing model fields and properties for a given object. Is there a clean way to instrospect an object so that I can get a dict of fields and properties开发者_JAVA技巧.

class MyModel(Model)
    url = models.TextField()

    def _get_location(self):
        return "%s/jobs/%d"%(url, self.id)

    location = property(_get_location)

What I want is something that returns a dict that looks like this:

{
  'id' : 1,
  'url':'http://foo',
  'location' : 'http://foo/jobs/1'
}   

I can use model._meta.fields to get the model fields, but this doesn't give me things that are properties but not real DB fields.


If you strictly want just the model fields and properties (those declared using property) then:

def get_fields_and_properties(model, instance):
    field_names = [f.name for f in model._meta.fields]
    property_names = [name for name in dir(model) if isinstance(getattr(model, name), property)]
    return dict((name, getattr(instance, name)) for name in field_names + property_names)

instance = MyModel()
print get_fields_and_properties(MyModel, instance)

The only bit that's extra here is running through the class to find the fields that correspond to property descriptors. Accessing them via the class gives the descriptor, whereas via the instance it gives you the values.


The trouble is you say you only want fields, but then complicate things by throwing properties into the mix. There isn't really any easy way in Python of distinguishing between a property and any other random method. This isn't anything to do with Django: it's simply that a property is just a method that is accessed via a descriptor. Because any number of things in the class will also be descriptors, you'll have trouble distinguishing between them.

Is there any reason why you can't define a list at the class level that contains all the properties you want, then just call getattr on each of the elements?


You should use the dir() function on your instance. Skipping whatever starts with '__' and than use getattr to get the value from your instance.

properties = [prop for prop in dir(SomeClass) if not prop.startswith("__")]

obj = {}
for prop in properties:
    obj[prop] = getattr(myinstance, prop)


class Awesome(models.Model):
 foo = models.TextField()
 bar = models.CharField(max_length = 200)

awe = Awesome()
for property in awe.__dict__.copy():
 # pass private properties.
 if not property.startswith('_'):
  print property,getattr(awe,property)

This is how they do it in Django.

0

精彩评论

暂无评论...
验证码 换一张
取 消