简体   繁体   中英

Django queryset dict in dict across ForeignKey

I'm a bit of a Django/Python Noob and am struggling with something that I imagine is relatively simple.

I have two models:

class Place(models.Model):
    place_name = models.CharField(max_length=200)
    place_summary = models.TextField(max_length=1500, blank=True, null=True)
    ...

    def __unicode__(self):
        return self.place_name

class Place_Image(models.Model):
    place_name = models.ForeignKey(Place)
    place_image = models.CharField(max_length=100, null=True, blank=True)
    ...

    def __unicode__(self):
        return self.place_image_title

I want to query the db and returns rows that looks something like:

place_name_A, place_summary_A,  place_image {place_image_A1}
place_name_B, place_summary_B,  place_image {place_image_B1, place_image_B2}

I played around with a few things: prefetch_related, select_related, I fiddled with my model that didn't seem to work. I'm sure the answer is fairly straight forward, but I can't see it at the moment. Some help would be great!

Should I be handling this is the model (with some sort of method) or in the view (with prefetch or something else)?

Thanks

UPDATE: I'm going to use the data in a template, roughly like this:

{% for place in places %}
    <ul>
        {{ place.place_name }}
        {{ place.place_summary }}
        # I then have an image carousel that displays images eg. '/static/images/{{ place.place_image_title}
    </ul>
{% endfor %}

If you are looking to do this at the view level there is no need to create an object which is exactly like a table. The great thing about the ORM is you can 'navigate' through it to get the data you want and need. So in your case you only need to query the Place model pulling out the data you need. You can do something like this:

view.py

def my_view(request):
    object_list = Place.objects.all()
    return render(request, 'template.html', {'object_list':object_list})

template.html

<table>
{% for item in object_list %}
    <tr>
        <td>{{ item.place_name }}</td>
        <td>{{ item.place_summary }}</td>
        <td>
            <ul>
            {% for pic in item.place_image %}
                <li>{{ pic.place_name }}</li>
            {% endfor %}
            </ul>
        </td>
    </tr>
{% endfor %}
</table>

Whilst you can improve this code just worry about getting to grips with the basics first.


Just some side notes to help improve your code and working with querysets.

In your models you do not need to prefix attributes with the model name. Just doing the following is fine:

class Place(models.Model):
    name = models.CharField(max_length=200)
    summary = models.TextField(max_length=1500, blank=True, null=True)
    ...

    def __unicode__(self):
        return self.name

As per the understanding I think this is the way to go:

Place.objects.all().values('place_name','place_summary','place_image')

and see it solves your purpose?

I guess you can access the Place_Image queryset from a Place instance like this:

place.place_image_set.all() # to retrieve all 

since django adds '_set' to the field name for reverse relationship. You can change it by specifiying a different field name with related_name like this:

place_name = models.ForeignKey(Place, related_name='place_images') 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM