Django: an ordered list of model instances from different models?

Users can upload three different types of content to our website: image, video, audio. Here are the models for each type:

class ImageItem(models.Model): user = models.ForeignKey(User) upload_date = models.DateTimeField(auto_now_add=True) image = models.ImageField(upload_to=img_get_file_path) title = models.CharFiled(max_length=1000, blank=True) class VideoItem(models.Model): user = models.ForeignKey(User) upload_date = models.DateTimeField(auto_now_add=True) video = models.FileField(upload_to=vid_get_file_path) title = models.CharFiled(max_length=1000, blank=True) class AudioItem(models.Model): user = models.ForeignKey(User) upload_date = models.DateTimeField(auto_now_add=True) audio = models.FileField(upload_to=aud_get_file_path) title = models.CharFiled(max_length=1000, blank=True) 

I have a page called library.html that displays all the elements that the user has loaded, in order to download the latest downloaded version (it displays the title and upload_date each instance and places a small icon on the left, symbolizing which element it is).

Assuming this requires three separate queries, how can I combine the three queries? How can I make sure they are in order from the most recent download?

+4
source share
3 answers

Referring to the question, this is the exact solution I used. Under the influence of monkut's answer and the top answer from the Franzdy link in his comment (thanks guys).

 from itertools import chain from operator import attrgetter images = ImageItem.objects.filter(user=user) video = VideoItem.objects.filter(user=user) audio = AudioItem.objects.filter(user=user) result_list = sorted(chain(images, video, audio), key=attrgetter('upload_date'), reverse=True) 
0
source

Alternatively, you can use multiple table inheritance and include common attributes in the superclass model. Then you simply order_by load the date into the superclass model. The third-party application django-model-utils provides a custom manager called Inheritance manager that allows you to automatically disable subclass models in your request.

 from model_utils.managers import InheritanceManager class MediaItem(models.Model): objects = InheritanceManager() user = models.ForeignKey(User) upload_date = models.DateTimeField(auto_now_add=True) title = models.CharFiled(max_length=1000, blank=True) class ImageItem(MediaItem): image = models.ImageField(upload_to=img_get_file_path) class VideoItem(MediaItem): video = models.FileField(upload_to=vid_get_file_path) class AudioItem(MediaItem): audio = models.FileField(upload_to=aud_get_file_path) 

Then your query looks simple:

 MediaItem.objects.all().order_by('upload_date').select_subclasses() 

This way you get what you want with one query (with three joins). In addition, your data is better normalized, and it is quite simple to support all kinds of more complex queries, as well as pagination.

Even if you do not, I would still use the abstract inheritance of the base class to conceptually normalize your data model, although you do not get the benefits of a database and ORM.

+4
source

attrgetter can be used to pull out the attributes of objects that you might want to sort.

 from operator import attrgetter results = [] results.extend(list(AudioItem.objects.filter(...))) results.extend(list(VideoItem.objects.filter(...))) results.extend(list(ImageItem.objects.filter(...)) results.sort(key=attrgetter("upload_date") 
0
source

All Articles