0

I have 3 models.

class Picture(models.Model)
  name = models.CharField(max_length=255)
  image_field = models.ImageField(upload_to="foo/")
  slug = models.SlugField()
  [...]


class Size(models.Model):
  name = models.CharField(max_length=255)
  width = models.IntegerField()
  height = models.IntegerField()
  crop = models.BooleanField(default=True)
  upscale = models.BooleanField(default=False)

  def __unicode__(self):
    return self.name

class Cache(models.Model):
  size = models.ForeignKey('Size')
  picture = models.ForeignKey('Picture')
  image_field = models.ImageField(upload_to="picture/resize/")

I want to use them as follows: First generate Picture objects. Then create Size objects. For every Size and Picture a Cache object should be generated when needed.

My problem is that I don't know where to put the code. It should be something like (pseudocode):

def get_cached_picture(Picture,Size):
  try:
    cacheObj = Cache.objects.get(picture=Picture, size=Size):
    [.. use cacheObj  ..]
  except Cache.DoesNotExist:
    [.. resize Picture according to Size, insert into cache, use it ..]

So where can I plug this code ? I know I could do this within a view, but is there a way to embed it into the models ? Cache should never be filled in the admin, instead it should be generated whenever a certain combination between Cache and Picture is needed.

It is probably easy to do, but I'm lacking of the right keyword for google.

JasonTS
  • 2,479
  • 4
  • 32
  • 48
  • A couple questions... Why do you need a separate model to associate a size with your picture when the picture.imagefield will store the width and height for you on the model? What is the purpose of the cache model? It seems to just duplicate image data? Can you post your model snippets and also explain a bit better what you are trying to accomplish as opposed to the exact code you are trying to find? – jdi Apr 22 '12 at 21:12
  • The purpose of this is to have multiple sizes of the picture. The Picture module will hold the original image, while the Cache module will hold multiple resized versions. Thank you for your reply, I will try to improve my Question. – JasonTS Apr 22 '12 at 21:21
  • 1
    Ah yes. That information is definitely helpful. Your Cache model is really more of a Versions. I began to think you were heading down the wrong path by trying to manually do caching. Please do update the question to show your models and also examples of what this usage will be. – jdi Apr 22 '12 at 21:23
  • Ok, I updated the question, is it better now ? I think I have an idea how to do it within a view, but is there a way to do this directly as a method of the picture model ? – JasonTS Apr 22 '12 at 21:33

1 Answers1

2

Assumptions:

  1. You want to be able to load a "Representation" of an image at a certain size on the fly.
  2. Size model will store a predefined set of sizes that a Representation can have.

I am going to refer to your Cache model as Representation because I think it makes more sense in context here.

The entry-point of this process would obviously be a view. A request comes in and you determine you need to search "Image1.jpg" @ 800x600. The simplest approach is just to put your queries right into the view. But for reusability, it might be better to do any of the following:

  • A utility function which is then called from the view to retrieve a Representation object
  • A classmethod of your Representation model, since you are already referencing Picture and Size as foreign keys.
  • Using a custom manager on the Representation model to do something similar to the above

Any of these will make it reusable as an app if someone else were to have their own views and needed to simply retrieve a Rep instance directly.

While your pseudocode refers to this process being on the Picture mode, I maintain that it should probably be on the Representation model, since it contains both foreign keys and you can easily see if you have a proper rep. If not, create it.

The view should only have to call something simple as opposed to having all of the logic:

# as classmethod
rep = Representation.get_cached_picture(picture, size)
# or with a manager
rep = Representation.objects.get_cached_picture(picture, size)
jdi
  • 90,542
  • 19
  • 167
  • 203
  • @JasonTS: Anytime! Thanks for updating your question. It was a lot easier to visualize once I saw model code and could tell exactly how you wanted to use it. – jdi Apr 22 '12 at 21:45