Welcome to django-photologue’s documentation!

The Photologue documentation is being transferred from a Google Code wiki to a Sphinx-generated setup (if you’re reading this at readthedocs.org, then you’re looking at these docs).

This documentation is accurate and up-to-date (hopefully!); the old docs on the Google Code wiki are extensive but have not been updated in a long time.

Contents:

Installation & configuration

Installation

The easiest way to install Photologue is with pip:

pip install django-photologue

You can also live life on the edge and install the latest code directly from the Github repository:

pip install -e git+https://github.com/jdriscoll/django-photologue.git#egg=django-photologue

This code should work ok - like Django itself, we try to keep the master branch bug-free.

Python 3

Django from version 1.5 onwards works with Python 3.

Photologue also works with Python 3 (3.3 or later). Like Django itself, support for Python 3 can be described as “should work, but needs more time on production sites to prove itself”. Use it, but apply caution!

Dependencies

5 apps that will be installed automatically if required.

And 2 dependencies that you will have to manage yourself:

Note

  • Photologue has the same support policy as Django.

That troublesome Pillow...

Pillow can be tricky to install; sometimes it will install smoothly out of the box, sometimes you can spend hours figuring it out - installation issues vary from platform to platform, and from one OS release to the next, so listing them all here would not be realistic. Google is your friend, and it’s worth noting that Pillow is a fork of PIL, so googling ‘PIL installation <your platform>’ can also help.

  1. You should not have installed both PIL and Pillow; this can cause strange bugs. Please uninstall PIL before you install Pillow.

  2. In some situations, you might not be able to use Pillow at all (e.g. if another package has a dependency on PIL). Photologue has a clumsy answer for this: write a temporary file /tmp/PHOTOLOGUE_NO_PILLOW, then install Photologue. This will tell Photologue to install without Pillow. It should work, but it hasn’t been tested!

  3. Sometimes Pillow will install... but is not actually installed. This ‘undocumented feature’ has been reported by a user on Windows. If you can’t get Photologue to disaply any images, check that you can actually import Pillow:

    $ python manage.py shell
    Python 3.3.1 (default, Sep 25 2013, 19:29:01)
    [GCC 4.7.3] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from PIL import Image
    >>>
    

Configure Your Django Settings

  1. Add to your INSTALLED_APPS setting:

    INSTALLED_APPS = (
         # ...other installed applications,
         'photologue',
         'south',               # if it's not already in your INSTALLED_APPS.
         'sortedm2m',
    )
    
  2. Confirm that your MEDIA_ROOT and MEDIA_URL settings are correct (Photologue will store uploaded files in a folder called ‘photologue’ under your MEDIA_ROOT).

  3. Enable the admin app if you have not already done so.

Add the urls

Add photologue to your projects urls.py file:

urlpatterns += patterns('',
    ...
    (r'^photologue/', include('photologue.urls')),
)

Sync Your Database

Use South to setup the new tables:

python manage.py migrate photologue

If you are installing Photologue for the first time, this will set up some default PhotoSizes to get you started - you are free to change them of course!

Sitemap

The Sitemaps protocol allows a webmaster to inform search engines about URLs on a website that are available for crawling. Django comes with a high-level framework that makes generating sitemap XML files easy.

Install the sitemap application as per the instructions in the django documentation, then edit your project’s urls.py and add a reference to Photologue’s Sitemap classes in order to included all the publicly-viewable Photologue pages:

...
from photologue.sitemaps import GallerySitemap, PhotoSitemap

sitemaps = {...
            'photologue_galleries': GallerySitemap,
            'photologue_photos': PhotoSitemap,
            ...
            }
etc...

There are 2 sitemap classes, as in some case you may want to have gallery pages, but no photo detail page (e.g. if all photos are displayed via a javascript lightbox).

Note

There is also a PhotologueSitemap class which combines the above 2 classes, but it will be removed in Photologue 3.0.

Sites

Photologue supports Django’s site framework since version 2.8. That means that each Gallery and each Photo can be displayed on one or more sites.

Please bear in mind that photos don’t necessarily have to be assigned to the same sites as the gallery they’re belonging to: each gallery will only display the photos that are on its site. When a gallery does not belong the current site but a single photo is, that photo is only accessible directly as the gallery won’t be shown in the index.

Note

If you’re upgrading from a version earlier than 2.8 you don’t need to worry about the assignment of already existing objects to a site because a datamigration will assign all your objects to the current site automatically.

Note

This feature is switched off by default. See here to enable it and for more information.

Customisation: extending templates

Photologue comes with a set of basic templates to get you started quickly - you can of course replace them with your own. That said, it is possible to extend the basic templates in your own project and override various blocks, for example to add css classes. Often this will be enough.

The trick to extending the templates is not special to Photologue, it’s used in other projects such as Oscar.

First, set up your template configuration as so:

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)

from photologue import PHOTOLOGUE_APP_DIR
TEMPLATE_DIRS = (
    ...other template folders...,
    PHOTOLOGUE_APP_DIR
)

The PHOTOLOGUE_APP_DIR points to the directory above Photologue’s normal templates directory. This means that path/to/photologue/template.html can also be reached via templates/path/to/photologue/template.html.

For example, to customise photologue/gallery_list.html, you can have an implementation like:

# Create your own photologue/gallery_list.html
{% extends "templates/photologue/gallery_list.html" %}

... we are now extending the built-in gallery_list.html and we can override
the content blocks that we want to customise ...

Customisation: Settings

Photologue has several settings to customise behaviour.

PHOTOLOGUE_USE_CKEDITOR

Default: False

If you have already installed django-ckeditor then you can use to edit the TextArea fields of Gallery and Photo in the admin. Simply set the setting to True.

Deprecated since version 2.8: Instead, override the admin; see here.

PHOTOLOGUE_PHOTO_PAGINATE_BY

Default: 20

Number of photos to display per page for PhotoListView.

Deprecated since version 2.8: Instead, override the view; see here.

PHOTOLOGUE_IMAGE_FIELD_MAX_LENGTH

Default: 100

max_length setting for the ImageModel ImageField

PHOTOLOGUE_SAMPLE_IMAGE_PATH

Default: os.path.join(os.path.dirname(__file__), 'res', 'sample.jpg'))

Path to sample image

PHOTOLOGUE_MAXBLOCK

Default: 256 * 2 ** 10

Modify image file buffer size.

PHOTOLOGUE_DIR

Default: 'photologue'

The relative path from your MEDIA_ROOT setting where Photologue will save image files. If your MEDIA_ROOT is set to “/home/user/media”, photologue will upload your images to “/home/user/media/photologue”

PHOTOLOGUE_PATH

Default: None

Look for user function to define file paths. Specifies a “callable” that takes a model instance and the original uploaded filename and returns a relative path from your MEDIA_ROOT that the file will be saved. This function can be set directly.

For example you could use the following code in a util module:

# myapp/utils.py:

import os

def get_image_path(instance, filename):
    return os.path.join('path', 'to', 'my', 'files', filename)

Then set in settings:

# settings.py:

from utils import get_image_path

PHOTOLOGUE_PATH = get_image_path

Or instead, pass a string path:

# settings.py:

PHOTOLOGUE_PATH = 'myapp.utils.get_image_path'

PHOTOLOGUE_MULTISITE

Default: False

Photologue can integrate galleries and photos with Django’s site framework. Default is for this feature to be switched off, as only a minority of Django projects will need it.

In this case, new galleries and photos are automatically linked to the current site (SITE_ID = 1). The Sites many-to-many field is hidden is the admin, as there is no need for a user to see it.

If the setting is True, the admin interface is slightly changed:

  • The Sites many-to-many field is displayed on Gallery and Photos models.
  • The Gallery Upload allows you to associate one more sites to the uploaded photos (and gallery).

Note

Gallery Uploads (zip archives) are always associated with the current site. This will be fixed in a future version of Photologue.

Customisation: Admin

The Photologue admin can easily be customised to your project’s requirements. The technique described on this page is not specific to Photologue - it can be applied to any 3rd party library.

Create a customisation application

For clarity, it’s best to put our customisation code in a new application; let’s call it photologue_custom; create the application and add it to your INSTALLED_APPS setting.

Changing the admin

In the new photologue_custom application, create a new empty admin.py file. In this file we can replace the admin configuration supplied by Photologue, with a configuration specific to your project. For example:

from django import forms
from django.contrib import admin

from photologue.admin import GalleryAdmin as GalleryAdminDefault
from photologue.models import Gallery


class GalleryAdminForm(forms.ModelForm):

    class Meta:
        model = Gallery
        exclude = ['tags']


class GalleryAdmin(GalleryAdminDefault):
    form = GalleryAdminForm

admin.site.unregister(Gallery)
admin.site.register(Gallery, GalleryAdmin)

This snippet will define a new Gallery admin class based on Photologue’s own. The only change we make is to exclude the tags field from the change form.

We then unregister the default admin for the Gallery model and replace it with our new class.

Possible uses

The technique outlined above can be used to make many changes to the admin; here are a couple of suggestions.

Custom rich text editors

The description field on the Gallery model (and the caption field on the Photo model) are plain text fields. With the above technique, it’s easy to use a rich text editor to manage these fields in the admin. For example, if you have django-ckeditor installed:

from django import forms
from django.contrib import admin

from ckeditor.widgets import CKEditorWidget
from photologue.admin import GalleryAdmin as GalleryAdminDefault
from photologue.models import Gallery


class GalleryAdminForm(forms.ModelForm):

    description = forms.CharField(widget=CKEditorWidget())

    class Meta:
        model = Gallery
        exclude = ['']


class GalleryAdmin(GalleryAdminDefault):
    form = GalleryAdminForm

admin.site.unregister(Gallery)
admin.site.register(Gallery, GalleryAdmin)

Customisation: Views and Urls

The photologue views and urls can be tweaked to better suit your project. The technique described on this page is not specific to Photologue - it can be applied to any 3rd party library.

Create a customisation application

For clarity, it’s best to put our customisation code in a new application; let’s call it photologue_custom; create the application and add it to your INSTALLED_APPS setting.

We will also want to customise urls:

  1. Create a urls.py that will contain our customised urls:
from django.conf.urls import *

urlpatterns = patterns('',

                       # Nothing to see here... for now.

                       )

2. These custom urls will override the main Photologue urls, so place them just before Photologue in the project’s main urls.py file:

... other code
(r'^photologue/', include('photologue_custom.urls')),
(r'^photologue/', include('photologue.urls')),

... other code

Now we’re ready to make some changes.

Changing pagination from our new urls.py

The list pages of Photologue (both Gallery and Photo) display 20 objects per page. Let’s change this value. Edit our new urls.py file, and add:

from django.conf.urls import *

from photologue.views import GalleryListView

urlpatterns = patterns('',

                       url(r'^gallery/page/(?P<page>[0-9]+)/$',
                           GalleryListView.as_view(paginate_by=5), name='pl-gallery-list'),

                       )

We’ve copied the urlpattern for the gallery list view from Photologue itself, and changed it slightly by passing in paginate_by=5.

And that’s it - now when that page is requested, our customised urls.py will be called first, with pagination set to 5 items.

Values that can be overridden from urls.py

GalleryListView

  • paginate_by: number of items to display per page.

PhotoListView

  • paginate_by: number of items to display per page.

Changing views.py to create a RESTful api

More substantial customisation can be carried out by writing custom views. For example, it’s easy to change a Photologue view to return JSON objects rather than html webpages. For this quick demo, we’ll use the django-braces library to override the view returning a list of all photos.

Add the following code to views.py in photologue_custom:

from photologue.views import PhotoListView

from braces.views import JSONResponseMixin


class PhotoJSONListView(JSONResponseMixin, PhotoListView):

    def render_to_response(self, context, **response_kwargs):
        return self.render_json_object_response(context['object_list'],
                                                **response_kwargs)

And call this new view from urls.py; here we are replacing the standard Photo list page provided by Photologue:

from .views import PhotoJSONListView

urlpatterns = patterns('',

                   # Other urls...

                   url(r'^photo/page/(?P<page>[0-9]+)/$',
                       PhotoJSONListView.as_view(),
                       name='pl-photo-list-json'),

                   # Other urls as required...
                   )

And that’s it! Of course, this is simply a demo and a real RESTful api would be rather more complex.

Customisation: third-party contributions

Photologue has a ‘contrib’ folder that includes some useful tweaks to the base project. At the moment, we have just one contribution:

Bootstrap templates

Replaces the normal templates with a new set that work well with Bootstrap.

To use these, edit your TEMPLATE_DIRS setting:

from photologue import PHOTOLOGUE_APP_DIR
TEMPLATE_DIRS = (
    ...
    os.path.join(PHOTOLOGUE_APP_DIR, 'contrib/bootstrap/templates'),
    ... other folders containing Photologue templates should come after...
)

The templates are incomplete - for example, we are missing templates for date-filtered galleries and photos. Pull requests are welcome!

Contributing to Photologue

Contributions are always very welcome. Even if you have never contributed to an open-source project before - please do not hesitate to offer help. Fixes for typos in the documentation, extra unit tests, etc... are welcome. And look in the issues list for anything tagged “easy_win”.

Example project

Photologue includes an example project to get you quickly ready for contributing to the project - do not hesitate to use it!

Workflow

Photologue is hosted on Github, so if you have not already done so, read the excellent Github help pages. We try to keep the workflow as simple as possible; most pull requests are merged straight into the master branch.

Features that will take a while to develop might warrant a separate branch in the project; at present only the ImageKit integration project is run on a separate branch.

Coding style

No surprises here - just try to follow the conventions used by Django itself.

Unit tests

Including unit tests with your contributions will earn you bonus points, maybe even a beer. So write plenty of tests.

Documentation

Keeping the documentation up-to-date is very important - so if your code changes how Photologue works, or adds a new feature, please check that the documentation is still accurate, and update it if required.

We use Sphinx to prepare the documentation; please refer to the excellent docs on that site for help.

Note

The CHANGELOG is part of the documentation, so if your patch needs the end user to do something - e.g. run a South migration - don’t forget to update it!

Translations

Photologue manages string translations with Transifex. The easiest way to help is to add new/updated translations there.

Once you’ve added translations, give the maintainer a wave and he will pull the updated translations into the master branch, so that you can install Photologue directly from the Github repository (see Installation) and use your translations straight away. Or you can do nothing - just before a release any new/updated translations get pulled from Transifex and added to the Photologue project.

New features

In the wiki there is a wishlist of new features already planned for Photologue - you are welcome to suggest other useful improvements.

If you’re interested in developing a new feature, it is recommended that you first discuss it on the mailing list or open a new ticket in Github, in order to avoid working on a feature that will not get accepted as it is judged to not fit in with the goals of Photologue.

A bit of history

Photologue was started by Justin Driscoll in 2007. He quickly built it into a powerful photo gallery and image processing application, and it became successful.

Justin then moved onto other projects, and no longer had the time required to maintain Photologue - there was only one commit between August 2009 and August 2012, and approximately 70 open tickets on the Google Code project page.

At this point Richard Barran took over as maintainer of the project. First priority was to improve the infrastructure of the project: moving to Github, adding South, Sphinx for documentation, Transifex for translations, Travis for continuous integration, zest.releaser.

The codebase has not changed much so far - and it needs quite a bit of TLC (Tender Loving Care), and new features are waiting to be added. This is where you step in...

And finally...

Please remember that the maintainer looks after Photologue in his spare time - so it might be a few weeks before your pull request gets looked at... and the pull requests that are nicely formatted, with code, tests and docs included, will always get reviewed first ;-)

Changelog

2.8 (2014-05-04)

Upgrade notes:

  1. Photologue now depends on django-sortedm2m and django-model-utils - please refer to installation instructions. These dependencies should be added automatically.
  2. Run South migrations.

List of changes:

  • Photo and Gallery models now support Django’s sites framework.
  • Photologue now uses django-sortedm2m to sort photos in a gallery.
  • Major rewrite of zip archive uploader: warn users of files that could not be processed, get code to work with Python 3 (issue #71), add extra error handling.
  • Renamed field title_slug to slug - this allows us to simplify views.py a bit.
  • PHOTOLOGUE_USE_CKEDITOR, PHOTOLOGUE_GALLERY_PAGINATE_BY and PHOTOLOGUE_PHOTO_PAGINATE_BY are deprecated.
  • Fixed pagination controls for photo list template.
  • Tightened naming rules for Photosize names.
  • Fixed a couple of unicode-related bugs.
  • Added to the documentation pages describing how to customise the admin and the views.
  • Refactored slightly views.py.
  • Started work on chainable querysets.

2.7 (2013-10-27)

Upgrade notes:

  1. All settings are now prefixed with PHOTOLOGUE_. Please check that you are not affected by this.

List of changes:

  • Fixed issue #56, Gallery pagination is broken.
  • Photologue now works with Python 3.
  • Added a set of templates that work well with Twitter-Bootstrap 3, and used them for the ‘example_project’.
  • Fixed issue #64 (allow installation without installing Pillow).
  • Optional use of CKEditor.
  • Updated/news translations for Polish, Slovak and German.
  • Bugfix: allow viewing latest galleries/latest photos pages even if they are empty.
  • Started using factory-boy - makes unit tests a bit easier to read.
  • Added settings to customise pagination count on list pages.
  • Documented all settings.
  • All settings are now prefixed with PHOTOLOGUE_.

2.6.1 (2013-05-19)

List of changes:

  • Fixed broken packaging in release 2.6.

2.6 (2013-05-19)

Upgrade notes:

  1. Photologue now relies on Pillow instead of PIL. The easiest way to upgrade is to remove PIL completely, then install the new version of Photologue.
  2. Photologue, in line with Django itself, has dropped support for Django 1.3.

List of changes:

  • Switched from PIL to Pillow - hopefully this should make installation easier.
  • Initial setup of data: removed plinit and replaced it with a South data migration.
  • Added feature to allow extending the built-in templates (and documented it!).
  • Allow editing of Photo added date (temp way of sorting photos).
  • Added an example project to help people wanting to contribute to the project.
  • Fixed buggy Travis CI script.
  • fixed issue #52, transactions in migration
  • fixed issue #51, uniqueness collisions in migration
  • Accessing the root url (usually /photologue/ will now redirect you to the gallery list view.
  • Photologue requires min. Django 1.4.
  • Tidied a data validator on PhotoSizes.

2.5 (2012-12-13)

  • added a sitemap.xml.
  • added some templatetags.
  • started using Sphinx for managing documentation.
  • started using Transifex for managing translations.
  • started using Travis CI.
  • added 12 new translations and improved some of the existing translations.
  • fixed issue #29 (quote URL of resized image properly).
  • misc improvements to clarity of unit tests.
  • added Django 1.4 timezone support.

2.4 (2012-08-13)

Upgrade notes:

  1. Starting with this version, Photologue uses South to manage the database schema. If you are upgrading an existing Photologue installation, please follow the South instructions at: http://south.readthedocs.org/en/latest/convertinganapp.html#converting-other-installations-and-servers
  2. Photologue has dropped support for Django 1.2.

List of changes:

  • use South to manage schema changes.
  • updated installation instructions.
  • fixed issue #9 (In Django 1.3, FileField no longer deletes files).
  • switched from function-based generic views to class-based views.
  • fixed PendingDeprecationWarnings seen when running Django 1.3 - this will make the move to Django 1.5 easier.
  • added unit tests.
  • fixed bug where GALLERY_SAMPLE_SIZE setting was not being used.
  • fixed issue #11 (GalleryUpload with len(title) > 50 causes a crash).
  • fixed issue #10 (Increase the size of the name field for photosize).

Indices and tables