Django :: Reference foreign key

Dan

I want to create a page where I can display properties by their pictures on a webpage.

Currently, My Property model looks like this (some codes are taken out):

class Property(models.Model):
    PROPERTY_TYPE = (('Room', 'Room'), ('House', 'House'))
    type = models.CharField(max_length=100, choices=PROPERTY_TYPE)
    title = models.CharField(max_length=100, db_index=True)
    beds = models.IntegerField(null=True, blank=True)
    price = models.IntegerField()
    payment_term = models.CharField(choices=PAYMENT_TERM_CHOICES, max_length=50)

and Picture model

class Picture(models.Model):
    location = models.CharField(max_length=255)
    owner = models.ForeignKey(User)
    active = models.BooleanField(default=True)
    alt = models.CharField(max_length=100)
    parent_property = models.ForeignKey(Property, null=True)
    timestamp = models.DateTimeField(default=timezone.now)

In my view, I get the list of objects like this:

room_list = Property.objects.all().filter(type='Room').order_by('timestamp')[6]

When running a for loop through the passed room_list list, I want to reference it like

Room's list of picture's first image

I tried going through Django's official documentation on One to Many relationships but I cannot seem to follow it.

How would I go about achieving this?

Bruce

Although you can use something like this:

{% for room in room_list %}
   <img src="{{ room.picture_set.first }}"/>
{% endfor %}

I don't recommend it. The reason is, that for every room_list item, you go to the database for Picture item. So when you have 30 items for example, you will bombard database with 31 queries.

The easiest thing you can do, is to add another field for you Property model, say default_picture, that will be FK to the Picture with None as default. After you save Picture, you fill the ID of that Picture (which Picture you use and how do you handle records without Picture is on your business logic). Then you get the records this way:

room_list = Property.objects.filter(
    type='Room'
).select_related(
    'default_picture'
).order_by('timestamp')[6]

This will result in a single query. Sure there are another methods to achieve the same but these are more complicated.

TIP: you don't need to order by timestamp field (unless you modify its value), but you can use ID as it is created in sequence. This is cheaper operation (at least in Postgres).

Update: As @JamesLin suggested, you could use something like this:

room_list = Property.objects.filter(
    type='Room'
).prefetch_related(
    'picture_set'
)

This will be translated into two queries, one for the Property list and the second one for all Picture records related to pulled Property items (Django will connect them programmatically). This is quite a lazy for the programmer but consider that you are loading all Picture records per Property. But this is certainly a better solution than the picture_set and easier to implement than my first suggestion (it doesn't automatically mean that better solution).

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related