2

Please have a look at my models.

class BackgroundImage(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=get_upload_file_name)
    caption = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

class ProfilePicture(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=get_upload_file_name)
    caption = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

class Album(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

    class Meta:
        ordering = ['-pub_date']
        verbose_name_plural = ('Albums')

    def __unicode__(self):
        return self.name

class Photo(models.Model):
    user = models.ForeignKey(User)
    album = models.ForeignKey(Album, default=3)
    image = models.ImageField(upload_to=get_upload_file_name)
    caption = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

How do I get all the images of Photo, ProfilePicture and BackgroundImage from their image field in one set. And then filter them by -pub_date to display in the template? Please help me out. Will be much much appreciated! Thank you.

Edit

N.B: I need ProfilePicture and BackgroundImage to work with the UserProfile like this:

from django.db import models
from django.contrib.auth.models import User
from profile_picture.models import ProfilePicture
from background_image.models import BackgroundImage

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    permanent_address = models.TextField()
    temporary_address = models.TextField()
    profile_pic = models.ForeignKey(ProfilePicture)
    background_pic = models.ForeignKey(BackgroundImage)

    def __unicode__(self):
        return self.user.username

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
Aamu
  • 3,431
  • 7
  • 39
  • 61
  • 1
    Is it apropriate to create base model class? Say `BaseImage(models.Model)` with `user`, `image`, `caption`, `pub_date` fields and then create other models like `BackgroundImage(BaseImage)`. – twil Nov 10 '13 at 00:41
  • Yes, I tried that way. But I don't remember why, for some reason there were too many errors. Can I do for loop and get the list of images from each set, and then add them together? – Aamu Nov 10 '13 at 11:46

1 Answers1

4

There is an InheritanceManager provided as part of django-model-utils which allows you to do this, see docs.

To install in Linux / Mac:

sudo pip install django-model-utils

Annoyingly, installing using easy_install or pip on windows is not quite as straight forward, see: How do I install Python packages on Windows?. A quick and dirty method is to download the django-model-util/ directory from here into the top directory of your django project, this is handy if you intend to copy the entire project across for deployment to a production webserver.

In order to use the InheritanceManager, the models need to be refactored slightly:

from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
from model_utils.managers import InheritanceManager

get_upload_file_name = 'images/' # I added this to debug models

class BaseImage(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=get_upload_file_name)
    caption = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

    objects = InheritanceManager()

class BackgroundImage(BaseImage):
    pass

class ProfilePicture(BaseImage):
    pass

class Album(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=200)
    pub_date = models.DateTimeField(default=datetime.now)

    class Meta:
        ordering = ['-pub_date']
        verbose_name_plural = ('Albums')

    def __unicode__(self):
        return self.name

class Photo(BaseImage):
    album = models.ForeignKey(Album, default=3)

All the Image models now inherit from a common super class which creates an instance of the InheritanceManager. I've also moved up all the duplicated attributes into the superclass, but this isn't strictly necessary, using InheritanceManager means that any attributes which are not present in BaseImage can still be accessed in the template.

To retrieve a list ordered by -pubdate:

BaseImage.objects.select_subclasses().order_by("-pub_date")

To use in a view:

def recentImages(request):
    r = BaseImage.objects.select_subclasses().order_by("-pub_date")[:20]
    return  render_to_response("recentImages.html", { "imageList" : r })

To use in a template:

{% for photo in imageList %}
  <img src="{{ photo.image.url }}" />
{% endfor %}

Is this something like what you are looking for?

Edit

The following code will still work fine, with the new models:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    permanent_address = models.TextField()
    temporary_address = models.TextField()
    profile_pic = models.ForeignKey(ProfilePicture)
    background_pic = models.ForeignKey(BackgroundImage)

Just make sure the names of the last two models in the ForeignKey relationship are correct!

Community
  • 1
  • 1
Henry Florence
  • 2,848
  • 19
  • 16
  • Thank you so much for the answer. This is what I was looking for. But just two more question though. Does django-model-utils work in windows, because I tried `pip install django-model-utils` but couldn't find it. And second, can I still use `ProfilePicture` and `BackgroundImage` in my `UserProfile` model (I have added in the edit the `UserProfile` model)? – Aamu Nov 10 '13 at 13:48
  • @Aamu the ProfilePicture and BackgroundImage will behave exactly as before. I ve added a quick and dirty windows install method to the answer, there is also an alternative answer if this doesn't work. – Henry Florence Nov 10 '13 at 14:02
  • I am sorry. At first I did was`django-models-utils` instead of django-model-utils`. Now its installed. And would you please be kind enough to answer me my second question, please. – Aamu Nov 10 '13 at 14:06
  • 2
    The `ProfilePicture` and `BackgroundImage` will behave exactly the same as before, they can be imported and used into other sections of code without importing `BaseImage` and queries such as `ProfilePicture.objects.all().orderby("-pubdate")` will work exactly as before. This should not effect your existing `UserProfile` code at all - the beauty of good refactoring, ;). Does this answer your second question? If you want to post the `UserProfile` code, I would be happy to look through it. – Henry Florence Nov 10 '13 at 14:18
  • Thank you so much for your answers and support!!! I have added it in the **Edit** section. Could please have a look at it and correct me whether it will work or not. I am really sorry, if I am asking too many question. Being a newbie I am lost with new concept! – Aamu Nov 10 '13 at 14:28
  • @Aamu I've added a corresponding edit, it's no problem, thanks for the accepting my answer! – Henry Florence Nov 10 '13 at 14:34
  • Thank you so much! And it was really my pleasure to accept it as the answer! – Aamu Nov 10 '13 at 14:40