curtisp
curtisp

Reputation: 2315

Django photo gallery - get single photo to show on gallery home page

Using Django 1.8. I am building app that has photo galleries with photos that belong to those galleries (my galleries are called 'fountains')

My photo model includes a 'gallery' field (boolean true or false) that designates a photo as the 'main fountain photo. Only one photo has this gallery field = True at any given time.

Trying to figure out how to get a query (queries) in a 'gallery home page' that will have list of all fountains with one photo for each fountain. My presentation will be a responsive grid of fountain name plus the single photo.

I am struggling with the view to send the fountain info plus the info about the single photo.

My models:

class Fountains(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    street_address = models.CharField(max_length = 100, blank=True, null=True)
    street_number = models.CharField(max_length = 20, blank=True, null=True)
    city = models.CharField(max_length=100, blank=True, null=True)
    lat = models.CharField(max_length=20, blank=True, null=True)
    lon = models.CharField(max_length=20, blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True)
    #slug = models.SlugField(prepopulate_from=("name",))
    modified = models.DateTimeField(auto_now=True)
    #tags = TaggableManager()
    #def __unicode__(self):
    #    return self.name.name

    class Meta:
        managed = True
        db_table = 'fountains'
        #verbose_name_plural = 'Fountains'

class Photos(models.Model):
    #filename = models.CharField(max_length=100)
    filename = models.ImageField(upload_to='.')
    ext = models.CharField(max_length=5, blank=True, null=True)
    desc = models.TextField(blank=True, null=True)
    #fountain_id = models.IntegerField(blank=True, null=True)
    fountain = models.ForeignKey(Fountains)
    user_id = models.IntegerField(blank=True, null=True)
    tag_count = models.IntegerField(blank=True, null=True)
    photos_tag_count = models.IntegerField(blank=True, null=True)
    comment_count = models.IntegerField(blank=True, null=True)
    gallery = models.NullBooleanField(blank=True)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    #def __unicode__(self):
    #    return self.filename.name

    class Meta:
        managed = True
        db_table = 'photos'
        #verbose_name_plural = 'Photos'

My view for the home page:

def home(request):
    """Renders the home page."""
    assert isinstance(request, HttpRequest)
    #fountain_list = Fountains.objects.order_by('name')
    fountain_list = Fountains.objects.filter(photos__gallery=True).order_by('name')

    context_dict = { 'fountain_list': fountain_list }
    return render(
        request,
        'app/index.html',
        context_dict,
        context_instance = RequestContext(request)
    )

My template for the home page view:

{% extends "app/layout.html" %}

{% block content %}

    <div class="col-sm-10">
    {% for fountain in fountain_list %}
        <div style="float:left; class="img-responsive">
            <a href="/photos/{{ fountain.id }}/"}>{{ fountain.name }}</a>
            {% for photo in fountain.photos_set.all %}
                <img src="{{ MEDIA_URL }}{{ photo.filename }}" alt="{{ photo.filename }}" class="thumbnail" width="100" height="100" style="border:none;"/>
                </a>
            {% endfor %}
        </div>
    {% endfor%}
    </div>

{% endblock %}

I have another similar view where i am getting the count of photos for each fountain using this:

fountain_list = Fountains.objects.annotate(photo_count=Count('photos')).order_by('name')

The fact that this notation can count photos for each fountain suggests that it can also get a specific photo as well. So i my view tries using 'aggregate' instead of 'annotate':

fountain_list = Fountains.objects.filter(photos__gallery=True).order_by('name')

However this just reduced the number of fountains in the object to those that had the gallery field = True.

Still, it seems that that the photo with gallery field = true might be contained in this object. But i couldn't retrieve it.

I have tried to get the 'gallery = true' photo in the template. I posited that as it was coming from the filtered fountain_list object, that 'all' would just be one single photo. So tried this in the template:

{% for photo in fountain.photos_set.all %}

But it retrieves all photos for all fountains.

I found a few other vaguely similar examples elsewhere via search but they al had sufficiently different notation (eg 'object_set' didn't work for me) that didn't help me.

I am looking for way to get the one related photo record with gallery = True into my view and template so that I can show one photo for each fountain.

My presentation will be a responsive grid of fountain name plus the single photo. Thanks!


EDIT to show new view and template based on accepted answer below:

My updated view:

def home(request):
    """Renders the home page."""
    assert isinstance(request, HttpRequest)
    photo_list = Photos.objects.filter(gallery=True)
    context_dict = { 'photo_list': photo_list }
    return render(
        request,
        'app/index.html',
        context_dict,
        context_instance = RequestContext(request)
    )

My updated template:

{% extends "app/layout.html" %}

{% block content %}

<div class="col-sm-10">
    {% for photo in photo_list %}
        <div style="float:left; class="img-responsive">
            <a href="/photos/{{ photo.fountain.id }}/"}>{{ photo.fountain.name }}</a>
                <img src="{{ MEDIA_URL }}{{ photo.filename }}" alt="{{ photo.filename }}" class="thumbnail" width="100" height="100" style="border:none;"/>
                </a>

        </div>
    {% endfor%}
    </div>


{% endblock %}

Upvotes: 0

Views: 152

Answers (1)

Alex Karahanidi
Alex Karahanidi

Reputation: 911

def home(request):
context = {}
context['photos'] = Photo.objects.first()
return render (request, 'html', context)

or

  photo = Photo.objects.first()
  return render(request, 'html', {'photo':photo})

html

<p>{{ photo.fanat.name }}</p>
<img src="{{ photo.image.url }}">

Upvotes: 2

Related Questions