Фотогалерея на Django с использованием Google Picasa в качестве хостинга

в 11:19, , рубрики: django, photo, python, метки: , ,

Фотогалерея на Django с использованием Google Picasa в качестве хостинга

Привет Читатели.

В этом посте хочу поделиться опытом организации фотогалереи на своем сайте с использованием Google Picasa как хранилища фотографий. Подобное решение для php уже было на Хабре, здесь же приводится реализация на Django. Кому интересна эта тема, добро пожаловать.

Некоторое время назад я озаботился выбором движка для организации фотогалереи на своем сайте. Требования были довольно простыми: организация фот в альбомы, показ всей галереи как миниатюр альбомов, а также фотографий в альбомах.

Для тех, кто дальше читать не хочет, сразу готовый результат.

Введение

Готовых решений галерей для Django великое множество, стоит к примеру заглянуть сюда. При этом фотографии, миниатюры, созданные кэши хранятся на нашем сервере, предлагаемый же способ использует сервера Гугла для всей черной работы, тем самым снижая нагрузки и экономя место на нашем. Сразу оговорюсь что никаких нагрузочных и других тестов не проводил, что позволяет заминусовать меня в хлам за голословные слова о повышении производительности и т.д.

Google Picasa как и многие продукты Гугла имеет свой API, подробно с которым можно ознакомиться в документации.
Что нам понадобится:

Описание приложения

Перейдем к описанию нашего приложения picasagallery. Основой приложения будут два представления(view), и шаблоны к ним.
Для начала определим две функции, возвращающие список альбомов и фотографий в альбоме соответственно:

from gdata.photos.service import PhotosService

def get_albums():
    pws = PhotosService()
    uf = pws.GetUserFeed(user=settings.PICASAGALLERY_USER)
    return pws.GetFeed(uf.GetAlbumsUri() + '&thumbsize=%s' % ALBUM_THUMBSIZE).entry

def get_photos(album):
    return PhotosService().GetFeed(album.GetPhotosUri() +
                       '&imgmax=%s&thumbsize=%s' % (PHOTO_IMGMAXSIZE, PHOTO_THUMBSIZE)).entry

Тут все очень просто(как впрочем и в дальнейшем). Наверное разве что стоит прокомментировать передаваемые в запрос параметры:

  • user — имя пользователя в Picasa;
  • thumbsize — размер миниатюр запрашиваемых объектов, т.е. альбомов и фотографий в данном случае. Доступные размеры миниатюр можно узнать в документации. Миниатюры могут быть обрезанными(cropped), т.е. квадратными, и необрезанными(uncropped), например '160c' или '128u'. Также можно указать несколько значений через запятую;
  • imgmax — максимальный размер фотографии (спасибо кэпу), т.е. это размер изображений, возвращаемых нашей функцией get_photos().

Для удобства поместим эти параметры в settings.py:

# Picasagallery settings
PICASAGALLERY_USER = 'your_email'
PICASAGALLERY_PHOTO_THUMBSIZE = '128'
PICASAGALLERY_PHOTO_IMGMAXSIZE = '1024'
PICASAGALLERY_ALBUM_THUMBSIZE = '160c'

При помощи django shell можно поэкспериментировать с этим хозяйством:

>>> from picasagallery.utils import get_albums, get_photos
>>> my_first_album = get_albums()[0]
>>> print my_first_album.title.text # имя альбома
>>> print my_first_album.media.thumbnail[0].url # url первой миниатюры альбома
https://lh3.googleusercontent.com/-aWPQC60j9zQ/TwCXlTD6CtE/AAAAAAAAAJk/E90Hu9OPiyg/s160-c/FotoLife.jpg
>>> my_first_photo = get_photos(my_first_album)[0]
>>> print my_first_photo.media.thumbnail[0].url # url первой фоты в альбоме
https://lh3.googleusercontent.com/-3Hb7VwUTBNg/TwCXlXqdAQI/AAAAAAAAAH8/v8ecBJtjV6k/s128/261799.jpg
>>> print my_first_photo.content.src # url изображения первой фоты, размер изображения определяется переданным параметром imgmax

Список my_first_album.media.thumbnail содержит миниатюры фотографий, его размер равен количеству переданных через запятую значений в параметре thumbsize.

Миниатюра альбома — это миниатюра его главной фотографии, по умолчанию это первая загруженная в альбом фотография, но это можно изменить в настройках альбома на сайте Google Picasa. Возможность изменения главной фотографии через API не нашел, если кто знает, подскажите в комментариях.

Представления

Определим два представления для страниц галереи и альбома соответственно.

from django.shortcuts import render_to_response
from django.http import Http404
from django.template import RequestContext

from picasagallery.utils import get_albums, get_photos

def gallery(request):
	albums = get_albums()
	return render_to_response('picasagallery/gallery.html', locals(),
                          context_instance = RequestContext(request))

def album_list(request, album_id):
	for album in get_albums():
    	if(album.gphoto_id.text == album_id):
        	photos = get_photos(album)
        	return render_to_response('picasagallery/album.html', locals(),
            	context_instance = RequestContext(request))
	raise Http404()

Шаблоны

Шаблон для галереи:

{% extends 'base.html' %}
{% load extras %}
{% load i18n %}

{% block head %}
    <link rel="stylesheet" href="{{ STATIC_URL }}picasagallery/css/base.css"
          type="text/css" media="screen" charset="utf-8" />
{% endblock %}

{% block content %}
    {% for album in albums %}
        <div class='album'>
            <div class='album-head'>
                <a href="{% url picasagallery.views.album_list album.GetAlbumId %}" >
                    <img class="album-preview" src="{%  thumbnail_url album %}">
                </a>
            </div>
            <div class="album-name">
                <a href="{% url picasagallery.views.album_list album.GetAlbumId %}">{{  album.title.text }}</a>
            </div>
        </div>
    {% endfor %}
	<p>
        <a href="/media/picasa_gdata.zip">{% trans 'Download source' %}</a>
    </p>
{%  endblock %}

Шаблон для альбома:

{% extends 'base.html' %}
{% load extras %}
{% load i18n %}

{% block head %}
    {% include 'picasagallery/pphoto.html' %}
    <link rel="stylesheet" href="{{ STATIC_URL }}picasagallery/css/base.css"
          type="text/css" media="screen" charset="utf-8" />
{% endblock %}

{% block content %}
    <a href='{% url picasagallery.views.gallery %}' >{% trans "Back to gallery" %}</a>
    <p>{% trans "Album:" %} {{ album.title.text }}</p>
    <div class='gallery'>
        {% for photo in photos %}
            <div class='image-preview-div'>
                <a class='image-preview-link' style='{% thumbnail_style photo %}' 
                        rel='gallery-image[pp_gal]' href='{{ photo.content.src }}'>
                    <img class='image-preview-img' style='{% thumbnail_style photo %}'
                            src='{%  thumbnail_url photo %}'>
                </a>
            </div>
        {% endfor %}
        <p>
            <a href='{{ album.GetHtmlLink.href }}' target='_blank'>{% trans "Show in Google Picasa" %}</a>
        </p>
    </div>
{% endblock %}

Для получения url миниатюр альбомов и фотографий эти шаблоны используют тег thumbnail_url, возвращающий url первой миниатюры из списка. Также используется тег thumbnail_style, возвращающий строку вида 'width: 48; height: 48;' для использования в качестве аргумента для

<img ... />

Эти теги определим в файле extras.py папки templatetags:

from django.template import Library

register = Library()

def get_thumbnail(obj):
    return obj.media.thumbnail[0]

@register.simple_tag
def thumbnail_url(obj):
    return get_thumbnail(obj).url

@register.simple_tag
def thumbnail_style(obj):
    style = 'width: %s; height: %s;'
    thumbnail = get_thumbnail(obj)
    return style % ('%spx' % thumbnail.width, '%spx' % thumbnail.height)

Шаблон для альбома содержит код для подключеня prettyPhoto:

{% include 'picasagallery/pphoto.html' %}

На этом моменте подробно останавливаться не буду, кому интересно, можно заглянуть в исходники.

Ну и в заключение, что из этого получилось, и тоже самое тут.

Спасибо за внимание.

Автор: pollydrag

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js