I'm interested in subclassing django's ImageFileField to allow access to the image IPTC metadata, something like:
>>> from myapp.models import SomeModel
>>> obj = SomeModel.objects.all()[0] # or what have you
>>> obj.image.iptc['keywords']
('keyword','anotherkeyword','etc')
... the docs say to read over django's internal code, which I did; I've tried to produce a working implementation and I am not sure what I'm doing -- I've defined custom fields before, but I can't come up with boilerplate setup for a file-based field.
I know I need to define an attr_class and a descriptor_class to make it work. Does anyone have a straightforward example or suggestion, with which I could get started?
It's not clear from your question: have you tried something like this?
class ImageMetadataMixin(object):
"""Mixin can be added to any image file"""
#property
def iptc(self):
"""Or something like this"""
class ImageWithMetadataFieldFile(ImageMetadataMixin, ImageFieldFile):
pass
class ImageWithMetadataField(ImageField):
attr_class = ImageWithMetadataFieldFile
I think it's all what necessary. Why do you think you need to redefine descriptor_class?
UPDATE: I have figured this one out -- thanks in part to the answer #valya provided. An example of a successful implementation can be found in my fork of django-imagekit:
https://github.com/fish2000/django-imagekit/blob/icc-develop/imagekit/modelfields.py
Related
i'm having a hard time changing the default _get_for_dict() Method.
This is what my code looks at the moment:
class ImageProperty(ndb.BlobKeyProperty):
def _get_for_dict(self, entity):
value = super(ImageProperty, self)._get_for_dict(entity)
if value:
return images.get_serving_url(value)
else:
return None
I'm not that much into the concepts for overriding methods, and having trouble with ndb iself...
Basically what I want to do: Store my Datastore Key as a BlobKeyProperty, but when retrieving it as a dict I want to get the image serving url.
Thanks a lot
I haven't tried this, but I think that this would be better as a _from_base_type hook:
class ImageProperty(ndb.BlobKeyProperty):
def _from_base_type(self, value):
return images.get_serving_url(value)
If I understand the documentation correctly, this API "stacks" so you don't need to call the _from_base_type on the super class (BlobKeyProperty). I guess ndb handles that for you. Personally, I think this is a bit weird for an API when super seems like it would work just fine ... But ... that's how it is I guess.
I want to have a base class called MBUser that has some predefined properties, ones that I don't want to be changed. If the client wants to add properties to MBUser, it is advised that MBUser be subclassed, and any additional properties be put in there.
The API code won't know if the client actually subclasses MBUser or not, but it shouldn't matter. The thinking went that we could just get MBUser by id. So I expected this to work:
def test_CreateNSUser_FetchMBUser(self):
from nsuser import NSUser
id = create_unique_id()
user = NSUser(id = id)
user.put()
# changing MBUser.get.. to NSUser.get makes this test succeed
get_user = MBUser.get_by_id(id)
self.assertIsNotNone(get_user)
Here NSUser is a subclass of MBUser. The test fails.
Why can't I do this?
What's a work around?
Models are defined by their "kind", and a subclass is a different kind, even if it seems the same.
The point of subclassing is not to share values, but to share the "schema" you've created for a given "kind".
A kind map is created on base class ndb.Model (it seems like you're using ndb since you mentioned get_by_id) and each kind is looked up when you do queries like this.
For subclasses, the kind is just defined as the class name:
#classmethod
def _get_kind(cls):
return cls.__name__
I just discovered GAE has a solution for this. It's called the PolyModel:
https://developers.google.com/appengine/docs/python/ndb/polymodelclass
Maybe easy question but I don't know how to summarize it that I would find my answer.
Is it possible to print out all available fields of model?
For example in iPython I can import model and just write model name and tab will show all available fields the models have.
Is it possible to do this in code without using some sort of shell?
I would like to use some sort of command (e.a. print_fields(self)) and get what's inside the model.
To check fields on a model I usually use ?:
>>> Person?
Type: ModelBase
Base Class: <class 'django.db.models.base.ModelBase'>
String Form: <class 'foo.bar.models.Person'>
Namespace: Interactive
File: /home/zk/ve/django/foo/bar/models.py
Docstring:
Person(id, first_name, last_name)
You can also use help(). If you have an instance of the model you can look at __dict__:
>>> [x for x in Person().__dict__.keys() if not x.startswith('_')]
<<< ['first_name', 'last_name', 'id']
If you have the model instance(s) you can simply call:
model_queryset.all().values()
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values
For just the list of fields using the model class itself see Django: Get list of model fields?
or directly the documentation - for Django 1.10 there is a dedicated section on how to work with fields: https://docs.djangoproject.com/en/1.10/ref/models/meta/#retrieving-all-field-instances-of-a-model
I think you just want to use __dict__ on an instance of a model. (It won't give methods like tab completion in ipython though). Also using __doc__ is quite helpful usually.
Also look into inspect http://docs.python.org/library/inspect.html
Maybe try something suggested here:
data = serializers.serialize("json", models.MyModel.objects.all(), indent=4)
JSON format is easy to print and read ;)
Inspired by #zeekay's answer, use the following to see the fields and corresponding values for an instance of a model:
[x for x in Cheese.objects.all()[0].__dict__.items() if not x[0].startswith('_')]
Why don't you implement __unicode__ :
def __unicode__(self):
return self.whatever_field + self.another_field
I have a model that has a pickled set of strings. (It has to be pickled, because Django has no built in set field, right?)
class Foo(models.Model):
__bar = models.TextField(default=lambda: cPickle.dumps(set()), primary_key=True)
def get_bar(self):
return cPickle.loads(str(self.__bar))
def set_bar(self, values):
self.__bar = cPickle.dumps(values)
bar = property(get_bar, set_bar)
I would like the set to be editable in the admin interface. Obviously the user won't be working with the pickled string directly. Also, the interface would need a widget for adding/removing strings from a set.
What is the best way to go about doing this? I'm not super familiar with Django's admin system. Do I need to build a custom admin widget or something?
Update: If I do need a custom widget, this looks helpful: http://www.fictitiousnonsense.com/archives/22
Update 2: Now I'm looking through different relational models to see if that will work. One idea I'm toying with:
class FooMember(models.Model):
name = models.CharField(max_length=120)
foo = models.ForeignKey('Foo')
class Foo(models.Model):
def get_names(self):
return FooMember.objects.filter(foo__exact=self)
Disadvantages of this include:
It feels excessive to make an entire model for one data field (name).
I would like the admin interface for Foo to allow the user to enter a list of strings. I'm not sure how to do that with this setup; making a custom form widget seems like less work.
Uhm. Django usually stores it's data in an SQL database. Storing a set as a pickled string is definietly not the best way to use an SQL database. It's not immediately obvious which is the right solution in your case, that depends what is in that set, but this is the wrong solution in any case.
You might want a new table for that set, or at least save it as comma separated values or something.
I'm setting up a data model in django using multiple-table inheritance (MTI) like this:
class Metric(models.Model):
account = models.ForeignKey(Account)
date = models.DateField()
value = models.FloatField()
calculation_in_progress = models.BooleanField()
type = models.CharField( max_length=20, choices= METRIC_TYPES ) # Appropriate?
def calculate(self):
# default calculation...
class WebMetric(Metric):
url = models.URLField()
def calculate(self):
# web-specific calculation...
class TextMetric(Metric):
text = models.TextField()
def calculate(self):
# text-specific calculation...
My instinct is to put a 'type' field in the base class as shown here, so I can tell which sub-class any Metric object belongs to. It would be a bit of a hassle to keep this up to date all the time, but possible. But do I need to do this? Is there some way that django handles this automatically?
When I call Metric.objects.all() every objects returned is an instance of Metric never the subclasses. So if I call .calculate() I never get the sub-class's behavior.
I could write a function on the base class that tests to see if I can cast it to any of the sub-types like:
def determine_subtype(self):
try:
self.webmetric
return WebMetric
except WebMetric.DoesNotExist:
pass
# Repeat for every sub-class
but this seems like a bunch of repetitious code. And it's also not something that can be included in a SELECT filter -- only works in python-space.
What's the best way to handle this?
While it might offend some people's sensibilities, the only practical way to solve this problem is to put either a field or a method in the base class which says what kind of object each record really is. The problem with the method you describe is that it requires a separate database query for every type of subclass, for each object you're dealing with. This could get extremely slow when working with large querysets. A better way is to use a ForeignKey to the django Content Type class.
#Carl Meyer wrote a good solution here: How do I access the child classes of an object in django without knowing the name of the child class?
Single Table Inheritance could help alleviate this issue, depending on how it gets implemented. But for now Django does not support it: Single Table Inheritance in Django so it's not a helpful suggestion.
But do I need to do this?
Never. Never. Never.
Is there some way that django handles this automatically?
Yes. It's called "polymorphism".
You never need to know the subclass. Never.
"What about my WebMetric.url and my TextMetric.text attributes?"
What will you do with these attributes? Define a method function that does something. Implement different versions in WebMetric (that uses url) and TextMetric (that uses text).
That's proper polymorphism.
Please read this: http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes
Please make your superclass abstract.
Do NOT do this: http://docs.djangoproject.com/en/1.2/topics/db/models/#multi-table-inheritance
You want "single-table inheritance".