This file is probably outdated. Please use sphinx docs instead.

Overview
========

django-photo-albums is a pluggable django image gallery app.

Image galleries can be attached to any Django model. And thanks to 
django 1.1 url namespaces it is possible to have multiple 'albums' app 
instances (for example, for different models) that use different sets of 
templates, different permission rules, have dedicated integration test suites 
and are available from different urls.

Each image gallery provide functionality for image viewing, editing, 
uploading, reordering, marking/unmarking as main and deleting.

django-photo-albums requires Django >= 1.1 (or svn version with 
url namespaces), setuptools for installation, django-generic-images 
for image management and django-annoying. 

Sorl-thumbnails should be mentioned as a very good optional dependency for 
generating thumbnails, but you can use any other library if you want.

Testing if app instance is integrated correctly (at least that templates 
don't raise exceptions) is easy because base class for integration testcases 
is provided.


Installation
============

$ pip install django-photo-albums

or

$ easy_install django-photo-albums

or

$ hg clone http://bitbucket.org/kmike/django-photo-albums/ 
$ cd django-photo-albums
$ python setup.py install

Then add 'photo_albums' and 'generic_images' to your INSTALLED_APPS in 
settings.py and run ./manage.py syncdb (syncdb is not needed if 
django-generic-images was already installed).


Basic use
=========

To add image gallery for model you should complete following steps:

1. Create album site instance and plug it's urls to urlconf:

	from photo_albums.urls import PhotoAlbumSite
	accounts_photo_site = PhotoAlbumSite(instance_name = 'user_images', 
                             queryset = User.objects.all(), 
                             template_object_name = 'album_user',
                             has_edit_permission = lambda request, obj: request.user==obj) 
	urlpatterns += patterns('', url(r'^accounts/', include(accounts_photo_site.urls)),)

Please note that if you deploy multiple albums (ex. for different models), 
you must provide unique ``instance_name`` for each instance to make url 
reversing work.

Included urls looks like "<object_id>/<app_name>/<action>" or 
"<object_id>/<app_name>/<image_id>/<action>",
where object_id is the id of object which is gallery attached to, 
app_name is "albums" by default, image_id is image id :) and action 
is performed action (view, edit, etc). It is possible to use slug 
instead of object's id (look at ``object_regex`` and ``lookup_field`` 
parameters). 

2. Create the necessary templates (see the section on templates below
   for details). 
   
3. Link people to image gallery using {% url .. %} template tag.

You can use these urls (assuming that `user_images` in an instance name,
`album_user` is object for which gallery is attached to, `image` is image 
in gallery):

	{% url user_images:show_album album_user.id %}
	{% url user_images:edit_album album_user.id %}
	{% url user_images:upload_main_image album_user.id %}
	{% url user_images:upload_images album_user.id %}
	{% url user_images:show_image album_user.id image.id %}
	{% url user_images:edit_image album_user.id image.id %}
	{% url user_images:delete_image album_user.id image.id %}
	{% url user_images:set_as_main_image album_user.id image.id %}
	{% url user_images:clear_main_image album_user.id image.id %}
	{% url user_images:reorder_images album_user.id %}
	{% url user_images:set_image_order album_user.id %}


Templates used by django-photo-albums
=====================================

Templates should be placed in "templates/albums/<app_name>" folder. App_name 
should be the name of queryset model's app as it appears in contenttypes 
table (e.g. `auth` for User).

Each view have at least 2 variables in context:
	<template_object_name>: object for which gallery is attached to
	'current_app': app name, 'albums' by default

The views included in django-photo-albums make use of 7 templates:

* ``show_album.html`` displays entire album
* ``edit_album.html`` displays entire album. Used by edit_album view.
* ``reorder_images.html`` displays entire album. Used by reorder_images view. 
Theese 3 templates have `images` variable in context with iterable of all 
images in gallery. 

* ``show_image.html`` - displays one image. Has `image`, 'prev' and 'next' 
variables in context. `prev` and `next` are id's of previous and next 
(by image.order field) images in gallery.

* ``upload_images.html`` - displays the formset for bulk image upload. 
Formset is of PhotoFormSet type (defined in photo_albums.forms module) and is 
available as `formset` context variable. 

* ``upload_main_image.html`` - displays form for uploading one image. Uploaded 
image becomes main in gallery. Has `form` in context, it's a form of type 
AttachedImageForm defined in generic_images.forms module.

* ``confirm_delete.html`` - displays confirmation dialog for deleting image. 
Has `image`in context. Should have a form that do POST request to delete view
on submit.


PhotoAlbumSite constructor parameters
=====================================

* ``instance_name`` - Required. App instance name for url reversing. 
Must be unique.

* ``queryset`` - Required. Albums will be attached to objects in this queryset.

* ``object_regex`` - Optional, default is '\d+'. It should be a URL regular 
expression for object in URL. You should use smth. like '[\w\d-]+' for
slugs.

* ``lookup_field`` - Optional, default is 'pk'. It is a field name to lookup.
It may contain ``__`` and follow relations (ex.: `userprofile__slug`).

* ``app_name`` - Optional, default value is 'album'. Used by url namespaces stuff.

* ``extra_context`` - Optional. Extra context that will be passed to each view.

* ``template_object_name`` - Optional. The name of template context variable 
with object for which album is attached. Default is 'object'.

* ``has_edit_permission`` - Optional. Function that accepts request and object 
and returns True if user is allowed to edit album for object and False otherwise. 
Default behaviour is to always return True.

* ``context_processors`` - Optional. A list of callables that will be used as 
additional context_processors in each view

* ``edit_form_class``: Optional. ModelForm subclass to be used in 
edit_image view

* ``upload_form_class``: Optional. ModelForm subclass to be used in 
upload_main_image view

* ``upload_formset_class``: Optional. ModelFormSet to be used in upload_images 
view



Provided views
==============

* ``show_album`` - show album for object using show_album.html template
* ``edit_album`` - same as ``show_album`` view but with login_required decorator
* ``upload_main_image`` - upload 1 image and make it main image in gallery
* ``upload_images`` - upload several images at once
* ``show_image`` - show one image
* ``edit_image`` - show one image, use login_required decorator and provide edit form
* ``delete_image`` - delete image if request method is POST, displays 
`confirm_delete.html` template otherwise
* ``set_as_main_image`` - mark image as main and redirect to ``show_image`` view
* ``clear_main_image`` - mark image as not main and redirect to ``show_image`` view
* ``reorder_images`` - same as `edit_album` but using `reorder_images.html` template
* ``set_image_order`` - ajax view that can be used to implement image reorder
functionality. Accepts json data in form 

	{'items': '[
					{"id":"<id1>", "order":"<order1>"},
					{"id":"<id2>", "order":"<order2>"}, 
					...
			    ]'
    }
	    
and assigns passed order to images with passed id's, with permission checks. 


Integration testing
===================

django-photo-albums provides base class (photo_albums.test_utils.AlbumTest) for 
writing integration tests for app instances. 

The example usage:

	from accounts.urls import accounts_photo_site
	from photo_albums import test_utils
	
	class UserAlbumTest(test_utils.AlbumTest):
		# existing user's data
	    username = 'obiwanus' 
	    password = 'vasia'
	    
	    # fixtures to be loaded (at least with users, images and 
	    # objects with galleries)
	    fixtures = ['my_fixtures']
	    
	    # app instance which is to be tested
	    album_site = accounts_photo_site
		
		# we don't need edit_image view and don't create template for it
		# so it should be excluded from testing
	    excluded_views = ['edit_image']
	    
	    # id of object for which album is attached
	    album_for_id = 4
	    
	    # if slugs are in use:
	    # album_for_id = 'my_object_slug'
	    
	    # id's of various images: 2 images in album (second is nedded if tou want 
	    # to test reordering) and one image in other album to test permission checks
	    image_in_album_id = 48
	    image2_in_album_id = 66
	    image_in_other_album_id = 42    
	        
If you don't use fixtures you can override setUp method and create necessery 
objects there. 