Permalink
Browse files

merge with my photogallery application

  • Loading branch information...
2 parents 27131b2 + d51ea70 commit b8bca35b62174f9fbb6ed24403a5c61842311bd8 @marcinn committed Oct 20, 2009
Showing with 1,129 additions and 226 deletions.
  1. +1 −0 .gitignore
  2. +20 −0 .project
  3. +10 −0 .pydevproject
  4. 0 README.txt
  5. +62 −20 photogallery/admin.py
  6. +4 −0 photogallery/auth.py
  7. +50 −0 photogallery/fields.py
  8. +46 −0 photogallery/forms.py
  9. BIN photogallery/locale/pl/LC_MESSAGES/django.mo
  10. +117 −0 photogallery/locale/pl/LC_MESSAGES/django.po
  11. +31 −0 photogallery/managers.py
  12. +152 −140 photogallery/models.py
  13. +41 −0 photogallery/plugins.py
  14. +6 −0 photogallery/templates/admin/photogallery/edit_inline/photo.html
  15. +17 −0 photogallery/templates/photogallery/add_album.html
  16. +11 −0 photogallery/templates/photogallery/ajax/photo_add.html
  17. +13 −0 photogallery/templates/photogallery/album_confirm_delete.html
  18. +26 −0 photogallery/templates/photogallery/base.html
  19. +1 −0 photogallery/templates/photogallery/base_site.html
  20. +15 −0 photogallery/templates/photogallery/dashboard/summary.html
  21. +17 −0 photogallery/templates/photogallery/delete_photo.html
  22. +17 −0 photogallery/templates/photogallery/edit_album.html
  23. +23 −0 photogallery/templates/photogallery/edit_photo.html
  24. +22 −0 photogallery/templates/photogallery/list.html
  25. +17 −0 photogallery/templates/photogallery/list_albums.html
  26. +10 −0 photogallery/templates/photogallery/show.html
  27. +29 −0 photogallery/templates/photogallery/widgets/album_list.html
  28. +8 −0 photogallery/templates/photogallery/widgets/base.html
  29. +24 −0 photogallery/templates/photogallery/widgets/photo_list.html
  30. +26 −0 photogallery/templates/photogallery/widgets/photo_view.html
  31. +34 −0 photogallery/templatetags/photogallery.py
  32. +8 −8 photogallery/urls.py
  33. +48 −0 photogallery/views/albums.py
  34. +1 −1 photogallery/views/comments.py
  35. +14 −55 photogallery/views/gallery.py
  36. +2 −2 photogallery/views/photo.py
  37. +195 −0 photogallery/views/photos.py
  38. +11 −0 photogallery/widgets.py
View
1 .gitignore
@@ -4,3 +4,4 @@
.DS_Store
.project
.pydevproject
+*-dist
View
20 .project
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>netwizard-photogallery</name>
+ <comment></comment>
+ <projects>
+ <project>netwizard-imageprocess</project>
+ <project>netwizard-platform</project>
+ <project>netwizard-widgets</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
View
10 .pydevproject
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python 2.6</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/netwizard-photogallery/src</path>
+</pydev_pathproperty>
+</pydev_project>
View
0 README.txt
No changes.
View
82 photogallery/admin.py
@@ -1,32 +1,74 @@
"""
- Copyright (c) 2008, Myles Braithwaite
- All rights reserved.
-
- This software is provided without warranty under the terms of the BSD
- license included in photos/LICENSE.markdown and may be redistributed only under
- the conditions described in the aforementioned license. This license is also
- available online at http://code.google.com/p/django-photo-gallery/wiki/License
-
- Author: Myles Braithwaite
+ Copyright (c) 2008, Myles Braithwaite
+ All rights reserved.
+
+ This software is provided without warranty under the terms of the BSD
+ license included in photos/LICENSE.markdown and may be redistributed only under
+ the conditions described in the aforementioned license. This license is also
+ available online at http://code.google.com/p/django-photo-gallery/wiki/License
+
+ Author: Myles Braithwaite
+ Author: Marcin Nowak (fork)
"""
from django.contrib import admin
+from django.contrib.admin import site
+from django.utils.translation import ugettext_lazy as _
+from django.conf import settings
+from forms import PhotoAdminModelForm
-from photos.models import Module, Gallery, Photo
+import models
-class ModuleAdmin(admin.ModelAdmin):
- list_display = ('module_type', 'site',)
+class AlbumAdmin(admin.ModelAdmin):
+ list_display = ('title', 'is_published', 'display_order', 'created_at',)
+ list_editable = ('display_order',)
+ search_fields = ('title', 'description',)
+ list_filter = ('is_published', )
+ actions = ['publish','hide']
-admin.site.register(Module, ModuleAdmin)
+ def publish(self, request, queryset):
+ queryset.update(is_published=True)
+ publish.short_description = 'Mark selected albums as published'
-class GalleryAdmin(admin.ModelAdmin):
- list_display = ('title',)
- prepopulated_fields = {'slug': ('title',)}
+ def hide(self, request, queryset):
+ queryset.update(is_published=False)
+ hide.short_description = 'Hide selected albums'
-admin.site.register(Gallery, GalleryAdmin)
class PhotoAdmin(admin.ModelAdmin):
- prepopulated_fields = {'slug': ('title',)}
- list_display = ('title', 'gallery', 'location', 'favorite')
+ form = PhotoAdminModelForm
+ prepopulated_fields = {'slug': ('title',)}
+ list_display = ('id', 'title', 'album', 'location', 'shoot_date', 'is_published', 'is_featured', 'uploader', 'created_at',)
+ list_display_links = ('id', 'title', )
+ search_fields = ('title', 'description', )
+ list_filter = ('album', 'is_published', 'is_featured',)
+ actions = ['publish','hide']
+
+ def publish(self, request, queryset):
+ queryset.update(is_published=True)
+ publish.short_description = 'Mark selected photos as published'
+
+ def hide(self, request, queryset):
+ queryset.update(is_published=False)
+ hide.short_description = 'Hide selected photos'
+
+
+# registering model admins
+
+site.register(models.Album, AlbumAdmin)
+site.register(models.Photo, PhotoAdmin)
+
+
+# backward compatibility
+
+GalleryAdmin = AlbumAdmin
+
+# experimetnal custom admin support
+
+if hasattr(admin.site, 'register_dashboard'):
+ from plugins import GallerySummary
+ admin.site.register_dashboard(GallerySummary())
+
+if hasattr(admin.site, 'menu_connect'):
+ admin.site.menu_connect('apps', 'Photo gallery', settings.ADMIN_URL+'photogallery', pri=5, name='apps.photogallery')
-admin.site.register(Photo, PhotoAdmin)
View
4 photogallery/auth.py
@@ -0,0 +1,4 @@
+from django.contrib.auth.decorators import permission_required
+
+def can_edit_photo(user, photo):
+ return user.is_superuser or user.has_perm('admin') or (user == photo.uploader) or photo.id is None
View
50 photogallery/fields.py
@@ -0,0 +1,50 @@
+from django import forms
+import widgets
+from django.utils.safestring import mark_safe
+from tagging.forms import TagField
+from tagging.models import Tag
+from django.utils import simplejson
+import models
+
+class AutoCompleteTagInput(forms.TextInput):
+ class Media:
+ css = {
+ 'all': ('css/jquery.autocomplete.css',)
+ }
+ js = (
+ 'js/jquery.js',
+ 'js/jquery.bgiframe.min.js',
+ 'js/jquery.ajaxQueue.js',
+ 'js/jquery.autocomplete.pack.js'
+ )
+
+ """
+ def value_from_datadict(self, data, files, name):
+ out = super(AutoCompleteTagInput, self).\
+ value_from_datadict(data, files, name)
+ return out
+ """
+
+ def render(self, name, value, attrs=None):
+ output = super(AutoCompleteTagInput, self).render(name, value, attrs)
+ page_tags = Tag.objects.usage_for_model(models.Photo)
+ tag_list = simplejson.dumps([tag.name for tag in page_tags],
+ ensure_ascii=False)
+ common = mark_safe('<ul class="append_tags">%s</ul>' % ''.join(
+ ['<li><a href="#">%s</a></li>' % unicode(tag) for tag in page_tags]))
+ return output + common + mark_safe(u'''<script type="text/javascript">
+ jQuery("#id_%s").autocomplete(%s, {
+ width: 150,
+ max: 10,
+ highlight: false,
+ multiple: true,
+ multipleSeparator: ", ",
+ scroll: true,
+ scrollHeight: 300,
+ matchContains: true,
+ autoFill: true,
+ });
+ </script>''' % (name, tag_list))
+
+class CityAlbumChoice(forms.ModelChoiceField):
+ widget = widgets.AlbumSelectOrCreateWidget
View
46 photogallery/forms.py
@@ -0,0 +1,46 @@
+from django.forms.models import ModelForm
+from django import forms
+from django.utils.safestring import mark_safe
+from tagging.forms import TagField
+from tagging.models import Tag
+import models
+import fields
+
+class PhotoAdminModelForm(ModelForm):
+ tags = TagField(widget=fields.AutoCompleteTagInput(), required=False)
+ class Meta:
+ model = models.Photo
+
+ def __init__(self, *args, **kwargs):
+ super(PhotoAdminModelForm, self).__init__(*args, **kwargs)
+ if self.instance:
+ self.initial['tags'] = ', '.join([unicode(tag) for tag in self.instance.tags])
+
+ def save(self, commit=True):
+ out = super(PhotoAdminModelForm, self).save(commit=commit)
+ if self.instance:
+ if not self.instance.is_published:
+ self.instance.is_published = True
+ self.instance.tags = self.cleaned_data['tags']
+ self.instance.save()
+ return out
+
+class PhotoEdit(PhotoAdminModelForm):
+ class Meta(PhotoAdminModelForm.Meta):
+ fields = ('image', 'title', 'album', 'description', 'tags',)
+
+
+class PhotoWithAlbumEdit(PhotoAdminModelForm):
+ album = fields.CityAlbumChoice(models.Album.objects, required=False)
+
+ class Meta:
+ model = models.Photo
+ fields = ('image', 'title', 'album', 'description', 'tags',)
+
+
+class AlbumEdit(ModelForm):
+ class Meta:
+ model = models.Album
+ fields = ('title', 'description')
+
+
View
BIN photogallery/locale/pl/LC_MESSAGES/django.mo
Binary file not shown.
View
117 photogallery/locale/pl/LC_MESSAGES/django.po
@@ -0,0 +1,117 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-10-07 22:23+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: models.py:43 models.py:92 migrations/0013_album-slug.py:29
+#: migrations/0013_album-slug.py:47
+msgid "title"
+msgstr "tytuł"
+
+#: models.py:45 models.py:94 migrations/0013_album-slug.py:23
+#: migrations/0013_album-slug.py:44
+msgid "description"
+msgstr "opis"
+
+#: models.py:48
+msgid "default photo"
+msgstr "zdjęcie główne"
+
+#: models.py:49 models.py:95 migrations/0013_album-slug.py:17
+#: migrations/0013_album-slug.py:50
+msgid "created at"
+msgstr "utworzono"
+
+#: models.py:50 models.py:96 migrations/0013_album-slug.py:35
+#: migrations/0013_album-slug.py:53
+msgid "updated at"
+msgstr "uaktualniono"
+
+#: models.py:51 models.py:97 migrations/0013_album-slug.py:41
+#: migrations/0013_album-slug.py:56
+msgid "is published"
+msgstr "opublikowany?"
+
+#: models.py:52
+msgid "display order"
+msgstr "kolejność"
+
+#: models.py:56 models.py:91 migrations/0013_album-slug.py:14
+msgid "album"
+msgstr "album"
+
+#: models.py:57
+msgid "albums"
+msgstr "albumy"
+
+#: models.py:89 migrations/0013_album-slug.py:32
+msgid "image path"
+msgstr "ścieżka obrazka"
+
+#: models.py:93 migrations/0013_album-slug.py:26
+msgid "shot date"
+msgstr "data zdjęcia"
+
+#: models.py:98 migrations/0013_album-slug.py:20
+msgid "is featured"
+msgstr "wyróżniony?"
+
+#: models.py:99 migrations/0013_album-slug.py:38
+msgid "uploader"
+msgstr "dodał"
+
+#: models.py:105
+msgid "photo"
+msgstr "zdjęcie"
+
+#: models.py:106
+msgid "photos"
+msgstr "zdjęcia"
+
+#: templates/photogallery/add_album.html:10
+msgid "Add"
+msgstr "Dodaj"
+
+#: templates/photogallery/delete_photo.html:12
+msgid "Are you sure?"
+msgstr "Na pewno?"
+
+#: templates/photogallery/delete_photo.html:13
+msgid "Yes, delete photo."
+msgstr "Tak, usuń zdjęcie."
+
+#: templates/photogallery/edit_album.html:10
+msgid "Update"
+msgstr "Aktualizuj"
+
+#: views/ajax.py:28 views/photos.py:128
+msgid "Album %(name)s created"
+msgstr "Album %(name)s został utworzony"
+
+#: views/ajax.py:35 views/photos.py:135
+msgid "Photo updated"
+msgstr "Zdjęcie zostało uaktualnione"
+
+#: views/ajax.py:35 views/photos.py:135
+msgid "Photo added"
+msgstr "Zdjęcie zostało dodane"
+
+#: views/photos.py:161
+msgid "Photo deleted"
+msgstr "Zdjęcie zostało usunięte"
+
+#~ msgid "photogallery"
+#~ msgstr "galeria zdjęć"
View
31 photogallery/managers.py
@@ -8,4 +8,35 @@
available online at http://code.google.com/p/django-photo-gallery/wiki/License
Author: Myles Braithwaite
+ Author: Marcin Nowak
"""
+
+__all__ = ['AlbumManager', 'PhotoManager',]
+
+class PhotoQuerySet(models.query.QuerySet):
+ def published(self):
+ return self.filter(is_published=True)
+
+
+class AlbumManager(models.Manager):
+ def published(self):
+ return self.get_query_set().filter(is_published=True).order_by('display_order')
+
+
+class PhotoManager(models.Manager):
+
+ def published(self):
+ return self.get_query_set().published()
+
+ def get_max_updated_at(self, qs):
+ return None
+
+ def albums(self):
+ albums = self.values_list('album_id', flat=True)
+ return Album.objects.filter(id__in = albums)
+
+ def featured(self):
+ return self.filter(is_featured=True)
+
+ def get_query_set(self):
+ return PhotoQuerySet(self.model)
View
292 photogallery/models.py
@@ -1,155 +1,167 @@
"""
- Copyright (c) 2008, Myles Braithwaite
- All rights reserved.
-
- This software is provided without warranty under the terms of the BSD
- license included in photos/LICENSE.markdown and may be redistributed only under
- the conditions described in the aforementioned license. This license is also
- available online at http://code.google.com/p/django-photo-gallery/wiki/License
-
- Author: Myles Braithwaite
+ Copyright (c) 2008, Myles Braithwaite
+ All rights reserved.
+
+ This software is provided without warranty under the terms of the BSD
+ license included in photos/LICENSE.markdown and may be redistributed only under
+ the conditions described in the aforementioned license. This license is also
+ available online at http://code.google.com/p/django-photo-gallery/wiki/License
+
+ Author: Myles Braithwaite
+ Author: Marcin Nowak
"""
import os
-from PIL import Image
from django.db import models
+from django.db.models import Max
from django.utils.translation import ugettext_lazy as _
from django.db.models import permalink
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.conf import settings
from django.utils.text import truncate_words
+from django.contrib.auth.models import User
+
+from tagging.fields import TagField
+from tagging.models import Tag
+import tagging
+
+from photogallery.utils import slugify
+from photogallery.managers import *
+
+from warnings import warn
+import os
+
+
+class Album(models.Model):
+ title = models.CharField(max_length=255, verbose_name=_('title'))
+ slug = models.SlugField(unique=True, max_length=255)
+ description = models.TextField(null=True, blank=True, verbose_name=_('description'))
+ default_image = models.ImageField(max_length=255, db_column='image',
+ upload_to=os.path.join('uploads','photogallery','album_icons'),
+ null=True, blank=True, verbose_name=_('default photo'))
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at'))
+ updated_at = models.DateTimeField(auto_now_add=True, auto_now=True, verbose_name=_('updated at'))
+ is_published = models.BooleanField(default=False, verbose_name=_('is published'))
+ display_order = models.PositiveIntegerField(blank=True, default=0, verbose_name=_('display order'))
+ objects = AlbumManager()
+
+ class Meta:
+ verbose_name = _('album')
+ verbose_name_plural = _('albums')
+
+ def image(self):
+ if self.default_image:
+ return self.default_image
+ if self.photos.count():
+ return self.photos.all()[0].image
+ return None
+
+ def __str__(self):
+ return 'Album #%d' % self.id
+
+ def __unicode__(self):
+ return self.title
+
+ def save(self, force_insert=False, force_update=False):
+ if not self.slug:
+ self.slug = slugify(self.title)
+ if not self.display_order:
+ self.display_order = self.__class__.objects.aggregate(display_order=Max('display_order'))['display_order']+1;
+ return super(Album, self).save(force_insert, force_update)
+
+ @permalink
+ def get_absolute_url(self):
+ return ('photo_album_title', None, {
+ 'slug' : self.slug
+ })
+
+ @permalink
+ def get_album_url(self):
+ return ('photo_album_detail', None, {
+ 'slug' : self.slug
+ })
+
+ # backward compatibility
+
+ @property
+ def photo_count(self):
+ warn('deprecated')
+ return self.photo_set.count
+
+ @property
+ def created(self):
+ warn('deprecated')
+ return self.modified_at
+
+ @property
+ def modified(self):
+ warn('deprecated')
+ return self.modified_at
+
+ @property
+ def latest_photo(self):
+ warn('deprecated')
+ return self.photo_set.all().order_by('-created')[0]
+
+ @property
+ def date_last_photo(self):
+ """
+ Date of last photo uploaded to the gallery.
+ """
+ warn('deprecated')
+ photo = Photo.objects.order_by('-created')[:0]
+ return photo.created
-from photos.managers import *
-
-class Module(models.Model):
- """
- Photo gallery site.
- """
- MODULE_TYPE_CHOICES = (
- (1, 'Footer'),
- (2, 'Description'),
- )
- site = models.ForeignKey(Site)
- module_type = models.IntegerField(_('module type'), choices=MODULE_TYPE_CHOICES)
- body = models.TextField(_('body'), help_text=_("Use Raw HTML"))
-
- class Meta:
- verbose_name = _('module')
- verbose_name_plural = _('modules')
- db_table = 'photo_modules'
- ordering = ('module_type', 'site',)
-
- def __unicode__(self):
- return "%s - %s" % (self.site, self.module_type)
-
-class Gallery(models.Model):
- """
- Gallery model.
- """
- title = models.CharField(_('title'), max_length=100)
- slug = models.SlugField(_('slug'), unique=True)
- description = models.TextField(_('description'), blank=True, null=True)
- created = models.DateTimeField(_('created'), auto_now_add=True)
- modified = models.DateTimeField(_('modified'), auto_now=True)
-
- class Meta:
- verbose_name = _('gallery')
- verbose_name_plural = _('galleries')
- db_table = 'photo_galleries'
- ordering = ('title',)
-
- def __unicode__(self):
- return u"%s" % self.title
-
- @permalink
- def get_absolute_url(self):
- return ('photo_gallery_title', None, {
- 'gallery_slug' : self.slug
- })
-
- @permalink
- def get_gallery_url(self):
- return ('photo_gallery_detail', None, {
- 'gallery_slug' : self.slug
- })
-
- @property
- def latest_photo(self):
- photo = Photo.objects.filter(gallery=self).order_by('-created')[0]
- return photo
-
- @property
- def description_truncate(self):
- return u"%s" % truncate_words(self.description, 20)
-
- @property
- def photo_count(self):
- """
- How many photos are in a given gallery.
- """
- count = Photo.objects.filter(gallery=self).count()
- return u"%s" % count
-
- @property
- def date_last_photo(self):
- """
- Date of last photo uploaded to the gallery.
- """
- photo = Photo.objects.order_by('-created')[:0]
- return photo.created
class Photo(models.Model):
- """
- Photo model.
- """
- title = models.CharField(_('title'), max_length=200)
- slug = models.SlugField(_('slug'), unique=True)
- location = models.CharField(_('location'), max_length=50, blank=True, null=True)
- description = models.TextField(_('description'), blank=True, null=True)
- gallery = models.ForeignKey(Gallery)
- favorite = models.BooleanField(_('favorite'), default=False)
-
- original = models.ImageField(_('original'), upload_to='photos/o/%Y-%m-%d')
- large = models.ImageField(_('large'), upload_to='photos/l/%Y-%m-%d', editable=False) # Image size no greater than 480x480
- thumbnail = models.ImageField(_('thumbnail'), upload_to='photos/t/%Y-%m-%d', editable=False) # Image size no greater than 220x220
- small = models.ImageField(_('small'), upload_to='photos/s/%Y-%m-%d', editable=False) # Image size no greater than 90x90
-
- created = models.DateTimeField(_('created'), auto_now_add=True)
- modified = models.DateTimeField(_('modified'), auto_now=True)
-
- class Meta:
- verbose_name = _('photo')
- verbose_name_plural = _('photos')
- db_table = 'photos'
- ordering = ('modified',)
-
- def __unicode__(self):
- return u"%s" % self.title
-
- @permalink
- def get_absolute_url(self):
- return ('photo_gallery_photo_detail', None, {
- 'photo_slug' : self.slug,
- 'gallery_slug' : self.gallery.slug,
- })
-
- def save(self):
- LARGE_SIZE = (480, 480)
- THUMBNAIL_SIZE = (220, 220)
- SMALL_SIZE = (90, 90)
-
- # TODO: Still thinking of a good way to to this.
- # Need to convert the Photos to Large and Small thumbnails.
-
- super(Photo, self).save()
-
- def admin_thumbnail(self):
- """
- Adds a photo thumbnail to the administration interface.
- """
- return u"<img src=\"%s/%s\" />" % (settings.MEDIA_URL, self.small)
-
- admin_thumbnail.sort_description = 'Thumbnail'
- admin_thumbnail.allow_tags = True
+ image = models.ImageField(
+ max_length=255,
+ upload_to=os.path.join('uploads','photogallery'),
+ verbose_name=_('image path'),
+ )
+ album = models.ForeignKey(Album, null=True, blank=True, related_name='photos', verbose_name=_('album'))
+ title = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('title'))
+ shoot_date = models.DateField(null=True, blank=True, verbose_name=_('shot date'))
+ description = models.TextField(null=True, blank=True, verbose_name=_('description'))
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at'))
+ updated_at = models.DateTimeField(auto_now_add=True, auto_now=True, verbose_name=_('updated at'))
+ is_published = models.BooleanField(default=False, verbose_name=_('is published'))
+ is_featured = models.BooleanField(default=False, verbose_name=_('is featured'))
+ uploader = models.ForeignKey(User, null=True, blank=True, related_name='uploaded_photos', verbose_name=_('uploader'))
+ slug = models.SlugField(_('slug'), unique=True)
+ location = models.CharField(_('location'), max_length=50, blank=True, null=True)
+
+ objects = PhotoManager()
+ tag_objects = tagging.managers.ModelTaggedItemManager()
+
+ class Meta:
+ verbose_name = _('photo')
+ verbose_name_plural = _('photos')
+
+ def __unicode__(self):
+ return u"%s" % self.title
+
+ @permalink
+ def get_absolute_url(self):
+ return ('photo_gallery_photo_detail', None, {
+ 'photo_slug' : self.slug,
+ 'album_slug' : self.album.slug,
+ })
+
+ # backward compatibility
+
+ @property
+ def created(self):
+ warn('deprecated')
+ return self.created_at
+
+ @property
+ def favorite(self):
+ warn('deprecated')
+ return self.is_featured
+
+
+tagging.register(Photo)
+
View
41 photogallery/plugins.py
@@ -0,0 +1,41 @@
+"""
+wizardcms plugins
+"""
+
+from django import template
+import models
+
+try:
+ from netwizard.wizardcms.plugins import BaseMenuItemProvider, get_all_menu_item_providers
+ from django.core.urlresolvers import reverse
+ class PhotoGalleryAlbum(BaseMenuItemProvider):
+ def get_url(self, value):
+ return reverse('photogallery-album-photos', args=[value])
+ def get_object(self, value):
+ obj = models.Album.objects.get(id=value)
+ obj.short_title = obj.title
+ obj.url = self.get_url(value)
+ return obj
+
+except ImportError:
+ pass
+
+
+class GallerySummary(object):
+ title = "Podsumowanie galerii"
+ def render(self):
+ data = {
+ 'albums': {
+ 'published': models.Album.objects.published().count(),
+ 'overall': models.Album.objects.count(),
+ },
+ 'photos': {
+ 'published': models.Photo.objects.published().count(),
+ 'overall': models.Photo.objects.count(),
+ },
+ }
+ return template.loader.render_to_string(
+ 'photogallery/dashboard/summary.html',
+ data)
+
+
View
6 photogallery/templates/admin/photogallery/edit_inline/photo.html
@@ -0,0 +1,6 @@
+{% load imageprocess %}
+<div class="photo">
+ {% if photo.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail_url photo.image 120 80 %}" alt="{{ photo }}"/>
+ {% endif %}
+</div>
View
17 photogallery/templates/photogallery/add_album.html
@@ -0,0 +1,17 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets i18n %}
+
+{% block content %}
+
+<form method="post" action="">
+ <fieldset>
+ <table>
+ {{ form.as_table }}
+ <tr><td>&nbsp;</td><td><input type="submit" value="{% trans "Add" %}" /></tr>
+</form>
+
+ </table>
+ </fieldset>
+</form>
+
+{% endblock %}
View
11 photogallery/templates/photogallery/ajax/photo_add.html
@@ -0,0 +1,11 @@
+{% load widgets %}
+
+
+<form id="PhotoEditForm" method="post" action="{% url photogallery-ajax-photo-add %}" enctype="multipart/form-data">
+ <fieldset>
+ <table>
+ {{ form.as_table }}
+ <tr><td>&nbsp;</td><td><input type="submit" value="{% if photo.id %}Zapisz{% else %}Dodaj{% endif %}" /></tr>
+ </table>
+ </fieldset>
+</form>
View
13 photogallery/templates/photogallery/album_confirm_delete.html
@@ -0,0 +1,13 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets i18n %}
+
+{% block content %}
+
+<form method="post" action="{% url photogallery-album-delete album.id %}">
+ <fieldset>
+ <p>Na pewno usunąć album {{ album.title }} i wszystkie jego zdjęcia?</p>
+ <input type="submit" name="confirm_delete" value="Tak, proszę..." />
+ </fieldset>
+</form>
+
+{% endblock %}
View
26 photogallery/templates/photogallery/base.html
@@ -0,0 +1,26 @@
+<html>
+ <head>
+ <title>{% block title %}Your photo gallery{% endblock %}</title>
+ <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/photogallery.css" />
+ {% block stylesheets %}{% endblock %}
+ {% block javascripts %}{% endblock %}
+ {% block metas %}{% endblock %}
+ </head>
+ <body class="{% block body_class %}default{% endblock %}">
+ <div id="Container">
+ {% block container %}
+ <h1>{% block content_title %}Your photo gallery{% endblock %}</h1>
+ {% block header %}{% endblock %}
+ {% block left %}{% endblock %}
+ <div id="Main">
+ {% block content %}{% endblock %}
+ </div>
+ {% block right %}{% endblock %}
+ <div class="clr" /></div>
+ <div id="Footer">
+ {% block footer %}{% endblock %}
+ </div>
+ </div>
+ {% endblock %}
+ </body>
+</html>
View
1 photogallery/templates/photogallery/base_site.html
@@ -0,0 +1 @@
+{% extends "photogallery/base.html" %}
View
15 photogallery/templates/photogallery/dashboard/summary.html
@@ -0,0 +1,15 @@
+<h3>Albumy</h3>
+<dl>
+ <dt>Opublikowanych:</dt>
+ <dd>{{ albums.published }}</dd>
+ <dt>Wszystkich:</dt>
+ <dd>{{ albums.overall }}</dd>
+</dl>
+
+<h3>Zdjęcia</h3>
+<dl>
+ <dt>Opublikowanych:</dt>
+ <dd>{{ photos.published }}</dd>
+ <dt>Wszystkich:</dt>
+ <dd>{{ photos.overall }}</dd>
+</dl>
View
17 photogallery/templates/photogallery/delete_photo.html
@@ -0,0 +1,17 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets i18n %}
+
+{% block content %}
+
+{% if photo.id %}
+{% include_widget PhotoView photo %}
+{% endif %}
+
+<form id="PhotoEditForm" method="post" action="{% url photogallery-photo-delete photo.id %}">
+ <fieldset>
+ {% trans "Are you sure?" %}
+ <input type="submit" name="confirm" value="{% trans "Yes, delete photo." %}" />
+ </fieldset>
+</form>
+
+{% endblock %}
View
17 photogallery/templates/photogallery/edit_album.html
@@ -0,0 +1,17 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets i18n %}
+
+{% block content %}
+
+<form method="post" action="">
+ <fieldset>
+ <table>
+ {{ form.as_table }}
+ <tr><td>&nbsp;</td><td><input type="submit" value="{% trans "Update" %}" /></tr>
+</form>
+
+ </table>
+ </fieldset>
+</form>
+
+{% endblock %}
View
23 photogallery/templates/photogallery/edit_photo.html
@@ -0,0 +1,23 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets %}
+
+{% block content %}
+
+{% if photo.id %}
+{% include_widget PhotoView photo %}
+{% endif %}
+
+{% if can_edit %}
+<form id="PhotoEditForm" method="post" action="{% url photogallery-photo-edit photo.id %}" enctype="multipart/form-data">
+ <fieldset>
+ <table>
+ {{ form.as_table }}
+ <tr><td>&nbsp;</td><td><input type="submit" value="{% if photo.id %}Zapisz{% else %}Dodaj{% endif %}" /></tr>
+ </table>
+ </fieldset>
+</form>
+{% else %}
+ Nie masz upranień do modyfikacji tego zdjęcia
+{% endif %}
+
+{% endblock %}
View
22 photogallery/templates/photogallery/list.html
@@ -0,0 +1,22 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets cache %}
+
+{% block content %}
+
+{% if album %}
+<h3>{{ album.title }}</h3>
+{% endif %}
+
+<div id="PhotoList" class="photo_list">
+{% if album %}
+{% cache 60 photogallery_photo_list photo_list.count album.id album.updated_at last_updated_at tag %}
+ {% include_widget PhotoList photo_list %}
+{% endcache %}
+{% else %}
+{% cache 60 photogallery_photo_list photo_list.count last_updated_at tag %}
+ {% include_widget PhotoList photo_list %}
+{% endcache %}
+{% endif %}
+</div>
+
+{% endblock content %}
View
17 photogallery/templates/photogallery/list_albums.html
@@ -0,0 +1,17 @@
+{% extends "photogallery/base_site.html" %}
+{% load cache widgets %}
+
+
+{% block content %}
+
+{% cache 60 album_list.count %}
+<div id="PhotoAlbumList">
+<h2>Albumy</h2>
+{% block content_body %}
+{% include_widget AlbumList album_list %}
+{% endblock %}
+
+</div>
+{% endcache %}
+
+{% endblock content %}
View
10 photogallery/templates/photogallery/show.html
@@ -0,0 +1,10 @@
+{% extends "photogallery/base_site.html" %}
+{% load widgets cache %}
+
+{% block content %}
+
+{% cache 10 photo_view photo.id photo.updated_at %}
+{% include_widget PhotoView photo %}
+{% endcache %}
+
+{% endblock %}
View
29 photogallery/templates/photogallery/widgets/album_list.html
@@ -0,0 +1,29 @@
+{% extends "photogallery/widgets/base.html" %}
+{% load imageprocess %}
+
+{% block content %}
+
+{% if albums %}
+
+{% for album in albums %}
+{% block content_album %}
+ <div class="album">
+ <a href="{% url photogallery-album-photos album.id %}">
+ {% if album.image %}
+ <img src="{{ MEDIA_URL}}{% thumbnail_url album.image thumb_width|default:120 thumb_height|default:80 %}" alt="{{ album.title|default:"Untitled" }}" />
+ {% else %}
+ {{ album.title|default:"Untitled" }}
+ {% endif %}
+ </a>
+ {% if album.title %}<h4>{{ album.title }}</h4>{% endif %}
+ </div>
+{% endblock content_album %}
+{% endfor %}
+
+{% else %}
+
+<p>Brak albumów</p>
+{% endif %}
+
+
+{% endblock %}
View
8 photogallery/templates/photogallery/widgets/base.html
@@ -0,0 +1,8 @@
+<div{% if id %} id="{{ id }}"{% endif %} class="widget{% if class %} {{ class }}{% endif %}">
+ {% block header %}
+ {% if title %}<h3><span>{{ title }}</span></h3>{% endif %}
+ {% endblock %}
+ {% block content %}{% endblock %}
+ {% block footer %}{% endblock %}
+</div>
+
View
24 photogallery/templates/photogallery/widgets/photo_list.html
@@ -0,0 +1,24 @@
+{% extends "photogallery/widgets/base.html" %}
+{% load imageprocess %}
+
+{% block content %}
+
+{% if photos %}
+
+{% for photo in photos %}
+{% block content_photo %}
+ <div class="photo">
+ <a href="{% url photogallery-photos-show photo.id %}"><img src="{{ MEDIA_URL}}{% thumbnail_url photo.image 110 80 %}" alt="{{ photo.title|default:"Untitled" }}" /></a>
+ {% if photo.title %}<h4>{{ photo.title }}</h4>{% endif %}
+ {% if photo.intro %}<p class="intro">{{ photo.intro }}</p>{% endif %}
+ </div>
+{% endblock content_photo %}
+{% endfor %}
+
+{% else %}
+
+<p>Brak zdjęć</p>
+{% endif %}
+
+
+{% endblock %}
View
26 photogallery/templates/photogallery/widgets/photo_view.html
@@ -0,0 +1,26 @@
+{% extends "photogallery/widgets/base.html" %}
+{% load imageprocess widgets %}
+
+{% block content %}
+ {% block photo_title %}
+ <h3>
+ {% if photo.album %}
+ <a href="{% url photogallery-album-photos photo.album.id %}">{{ photo.album.title }}</a> -
+ {% endif %}
+ {{ photo.title|default:"Bez tytułu" }}
+ </h3>
+ {% endblock %}
+ <div class="photo">
+ <img src="{{ MEDIA_URL }}{% thumbnail_url photo.image 640 480 %}" alt="{{ photo.title|default:"Bez tytułu" }}" />
+ </div>
+ <div class="details">
+ <dl>
+ <dt class="upload_time">Dodano:</dt>
+ <dd>{{ photo.created_at }}</dd>
+ {% if photo.uploader %}<dd class="uploader">przez <a href="#">{{ photo.uploader }}</a></dd>{% endif %}
+ {% if photo.author %}<dt class="author">Autor fotografii:</dt><dd class="author">{{ photo.author }}</dd>{% endif %}
+ {% if photo.shoot_date %}<dt class="shoot_date">Autor fotografii:</dt><dd class="description">{{ photo.author }}</dd>{% endif %}
+ {% if photo.description %}<dt class="description">Opis:</dt><dd class="description">{{ photo.description }}</dd>{% endif %}
+ </dl>
+ </div>
+{% endblock %}
View
34 photogallery/templatetags/photogallery.py
@@ -0,0 +1,34 @@
+from django.utils.safestring import mark_safe, mark_for_escaping
+from django import template
+from netwizard.photogallery.models import Album
+
+register = template.Library()
+
+class PhotoAlbumsNode(template.Node):
+ def __init__(self, cast_as, limit):
+ self.cast_as = cast_as
+ self.limit = limit
+
+ def render(self, context):
+ albums = Album.objects.published()[:self.limit]
+ if self.cast_as:
+ context[self.cast_as] = albums
+ return ''
+ return albums
+
+@register.tag
+def get_photo_albums(parser, token):
+ bits = token.contents.split()
+ if len(bits) <3 or len(bits) >4:
+ raise TemplateSyntaxError, "%s tag takes two or three arguments" % bits[0]
+ if bits[2] == 'as':
+ limit = bits[1]
+ cast_as = bits[3]
+ elif bits[3] == 'as':
+ limit = bits[2]
+ cast_as = bits[4]
+ else:
+ raise TemplateSyntaxError, "%s invalid tag arguments" % bits[0]
+
+ return PhotoAlbumsNode(cast_as, limit)
+
View
16 photogallery/urls.py
@@ -18,23 +18,23 @@
name = 'photo_gallery_comment',
),
url(r'^galleries/$',
- view = 'photos.views.gallery.archive',
+ view = 'photos.views.albums.list',
name = 'photo_gallery_archive',
),
- url(r'^(?P<gallery_slug>[-\w]+)/gallery/(?P<photo_slug>[-\w]+)/$',
- view = 'photos.views.photo.detail',
+ url(r'^(?P<album_slug>[-\w]+)/gallery/(?P<photo_slug>[-\w]+)/$',
+ view = 'photos.views.photos.detail',
name = 'photo_gallery_photo_detail',
),
- url(r'^(?P<gallery_slug>[-\w]+)/gallery/$',
- view = 'photos.views.gallery.detail',
+ url(r'^(?P<album_slug>[-\w]+)/gallery/$',
+ view = 'photos.views.photos.list',
name = 'photo_gallery_detail',
),
- url(r'^(?P<gallery_slug>[-\w]+)/$',
- view = 'photos.views.gallery.title',
+ url(r'^(?P<album_slug>[-\w]+)/$',
+ view = 'photos.views.albums.title', # use directly object_detail generic view
name = 'photo_gallery_title',
),
url(r'^$',
view = 'photos.views.gallery.index',
name = 'photo_gallery_index',
),
-)
+)
View
48 photogallery/views/albums.py
@@ -0,0 +1,48 @@
+"""
+views for albums
+"""
+
+from django.views.generic.list_detail import object_list, object_detail
+from django.views.generic.create_update import create_object, update_object, delete_object
+from django.core.urlresolvers import reverse
+from netwizard.photogallery.models import Photo, Album
+
+def list(request, queryset=None, template_name=None, **kwargs):
+ queryset = queryset or Album.objects.published()
+ return object_list(request, paginate_by=50,
+ queryset=queryset,
+ template_name=template_name or 'photogallery/list_albums.html',
+ template_object_name='album')
+
+def index(request, **kwargs):
+ return list(request, **kwargs)
+
+def title(request, album_id=None, album_slug=None, template_name=None, extra_context=None):
+ return object_detail(request, object_id=album_id, slug=album_slug,
+ template_name = template_name or 'photogallery/gallery_title.html',
+ extra_context = extra_context);
+
+def create(request, login_required=True, template_name=None,
+ extra_context=None, post_save_redirect=None, **kw):
+ ctx = extra_context or {}
+ return create_object(request, login_required=login_required,
+ template_name=template_name or 'photogallery/add_album.html',
+ extra_context=ctx, post_save_redirect=post_save_redirect,
+ model=Album)
+
+def edit(request, id=None, slug=None, login_required=True, template_name=None,
+ extra_context=None, post_save_redirect=None, **kw):
+ ctx = extra_context or {}
+ return update_object(request, object_id=id, slug=slug, model=Album,
+ login_required=login_required, template_object_name='album',
+ template_name=template_name or 'photogallery/edit_album.html',
+ extra_context=ctx, post_save_redirect=post_save_redirect)
+
+def delete(request, id=None, slug=None, login_required=True, template_name=None,
+ extra_context=None, post_delete_redirect=None, **kw):
+ ctx = extra_context or {}
+ return delete_object(request, Album, post_delete_redirect or reverse('photogallery-albums'),
+ object_id=id, slug=slug, login_required=login_required,
+ template_object_name='album', template_name=template_name,
+ extra_context=ctx)
+
View
2 photogallery/views/comments.py
@@ -13,7 +13,7 @@
from django.core.paginator import QuerySetPaginator, InvalidPage
from django.contrib.comments.models import FreeComment
-from photos.views import render
+from photogallery.views import render
from photos.models import Photo
def list(request, page=0):
View
69 photogallery/views/gallery.py
@@ -13,69 +13,28 @@
from django.shortcuts import get_object_or_404
from django.core.paginator import QuerySetPaginator, InvalidPage
-from photos.views import render
-from photos.models import Gallery, Photo
+from photogallery.views import render
+from photogallery.models import Album, Photo
def index(request):
- galleries = Gallery.objects.all()[:6]
- favorites = Photo.objects.filter(favorite=True)[:6]
- galleries_count = Gallery.objects.all().count()
- photos_count = Photo.objects.all().count()
- favorites_count = Photo.objects.filter(favorite=True).count()
+ albums = Album.objects.published()[:6]
+ favorites = Photo.objects.published().filter(is_featured=True)[:6]
+ albums_count = albums.count()
+ photos_count = Photo.objects.published().count()
+ favorites_count = favorites.count()
- return render(request=request, template_name='photos/gallery_index.html', payload={
- 'galleries' : galleries,
+ return render(request=request, template_name='photogallery/gallery_index.html', payload={
+ 'albums' : albums,
'favorites' : favorites,
- 'galleries_count' : galleries_count,
+ 'albums_count' : albums_count,
'photos_count' : photos_count,
'favorites_count' : favorites_count,
})
-def title(request, gallery_slug, page=0):
- gallery = get_object_or_404(Gallery, slug__iexact=gallery_slug)
-
- return render(request, 'photos/gallery_title.html', { 'gallery': gallery })
-
-def detail(request, gallery_slug, page=0):
- gallery = get_object_or_404(Gallery, slug__iexact=gallery_slug)
- photos = Photo.objects.filter(gallery=gallery)
-
- paginator = QuerySetPaginator(photos, 25, allow_empty_first_page=True)
- if not page:
- page = request.GET.get('page', 1)
- try:
- page_number = int(page)
- except ValueError:
- if page == 'last':
- page_number = paginator.num_pages
- else:
- raise Http404
-
- try:
- page_obj = paginator.page(page_number)
- except InvalidPage:
- raise Http404
-
- return render(request, 'photos/gallery_detail.html', {
- 'gallery': gallery,
- 'photos': photos,
- 'is_paginated': page_obj.has_other_pages(),
- 'results_per_page': paginator.per_page,
- 'has_next': page_obj.has_next(),
- 'has_previous': page_obj.has_previous(),
- 'page': page_obj.number,
- 'next': page_obj.next_page_number(),
- 'previous': page_obj.previous_page_number(),
- 'first_on_page': page_obj.start_index(),
- 'last_on_page': page_obj.end_index(),
- 'pages': paginator.num_pages,
- 'hits': paginator.count,
- 'page_range': paginator.page_range,
- })
def archive(request):
- galleries = Gallery.objects.all()
+ galleries = Album.objects.all()
- return render(request=request, template_name='photos/gallery_archive.html', payload={
- 'galleries': galleries,
- })
+ return render(request=request, template_name='photogallery/gallery_archive.html', payload={
+ 'albums': galleries,
+ })
View
4 photogallery/views/photo.py
@@ -12,8 +12,8 @@
from django.shortcuts import get_object_or_404
-from photos.views import render
-from photos.models import Gallery, Photo
+from photogallery.views import render
+from photogallery.models import Gallery, Photo
def photo_detail(request, gallery_slug, photo_slug):
gallery = get_object_or_404(Gallery, slug__iexact=gallery_slug)
View
195 photogallery/views/photos.py
@@ -0,0 +1,195 @@
+import datetime
+from django.contrib.auth.decorators import login_required
+from django.views.decorators.cache import never_cache, cache_page
+from django.http import Http404, HttpResponseRedirect
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _
+from django.shortcuts import render_to_response
+from netwizard.django.helpers import flash, redirect
+from tagging.views import tagged_object_list
+from tagging.models import TaggedItem
+from django.db.models.query import Q
+
+from django.views.generic.list_detail import object_list, object_detail
+from django.views.generic.create_update import update_object, create_object
+from django.template import RequestContext
+
+from photogallery.models import Photo, Album
+from photogallery import forms, auth
+import re
+
+
+def list(request, id=None, album_slug=None, template_name=None, paginate_by=None, queryset=None, extra_context=None, **kwargs):
+ photos = queryset if queryset is not None else Photo.objects
+ if photos:
+ photos = photos.published()
+ album = None
+ if id: # album
+ photos = photos.filter(album=id)
+ album = Album.objects.published().get(id=id)
+ elif slug:
+ photos = photos.filter(album__slug=slug)
+ album = Album.objects.published().get(slug=slug)
+
+ extra_context = extra_context or {}
+ extra_context.update({
+ 'album': album,
+ 'last_updated_at': Photo.objects.get_max_updated_at(photos),
+ 'tag': None,
+ })
+
+ return object_list(request, paginate_by=paginate_by or 25,
+ queryset=photos, template_name=template_name or 'photogallery/list.html',
+ extra_context=extra_context, template_object_name='photo')
+
+
+def list_tagged(request, tag, template_name=None, extra_context=None, paginate_by=None, **kwargs):
+ photos = Photo.objects.published()
+ ctx = extra_context or {}
+ ctx.update({
+ 'last_updated_at': Photo.objects.get_max_updated_at(photos),
+ 'tag': tag,
+ })
+ return tagged_object_list(request, tag=tag, paginate_by=paginate_by or 25,
+ queryset_or_model=photos, template_name=template_name or 'photogallery/list.html',
+ extra_context=ctx, template_object_name='photo', **kwargs)
+
+
+def detail(request, id=None, photo_slug=None, album_slug=None, template_name=None, extra_context=None, **kw):
+ qs = Photo.objects.published()
+ if album_slug:
+ qs.filter(album__slug__exact = album_slug)
+
+ extra_context = extra_context or {}
+ try:
+ photo = qs.get(id=id)
+ extra_context['next_album_photo'] =\
+ photo.get_next_by_created_at(album=photo.album)
+ except Photo.DoesNotExist:
+ pass
+ try:
+ extra_context['prev_album_photo']=\
+ photo.get_previous_by_created_at(album=photo.album)
+ except Photo.DoesNotExist:
+ pass
+
+ return object_detail(request, object_id=id, slug=photo_slug,
+ queryset=qs,
+ template_name=template_name or 'photogallery/show.html',
+ extra_context = extra_context,
+ template_object_name='photo')
+
+show = detail # BC
+
+@login_required
+@never_cache
+def create(request, albumslug=None, form_class=forms.PhotoEdit, template_name=None, extra_context=None, post_save_redirect=None):
+ ctx = {}
+ form_init = {}
+ album = None
+ if albumslug:
+ album = Album.objects.published().get(slug=albumslug)
+ ctx['album'] = album
+ form_init['album'] = album.id
+ if request.method == 'POST':
+ form = form_class(request.POST, request.FILES, initial=form_init)
+ if form.is_valid():
+ photo = form.save()
+ if post_save_redirect:
+ return HttpResponseRedirect(post_save_redirect % photo.__dict__)
+ elif hasattr(photo, 'get_absolute_url'):
+ return HttpResponseRedirect(photo.get_absolute_url())
+ else:
+ return redirect(reverse='photogallery-photos-show', id=photo.id)
+ else:
+ form = form_class(initial=form_init)
+
+ ctx['form'] = form
+ extra_context = extra_context or {}
+ extra_context.update(ctx)
+
+ return render_to_response(template_name or "photogallery/create_photo.html",
+ extra_context, RequestContext(request))
+
+@login_required
+@never_cache
+def edit(request, id, form_class=forms.PhotoEdit, redirect_to=None, template_name=None, extra_context=None):
+ try:
+ photo = Photo.objects.published().get(id=id)
+ if not auth.can_edit_photo(request.user, photo):
+ raise Photo.DoesNotExist
+ except Photo.DoesNotExist:
+ raise Http404
+
+ if request.method == 'POST':
+ form = form_class(request.POST, request.FILES, instance=photo)
+ if form.is_valid():
+ photo = form.save(commit=False)
+ if request.POST.get('create_album'):
+ album = Album()
+ album.title = request.POST.get('new_album_name')
+ self.flash(_('Album %(name)s created') % {'name': album.title })
+ album.save()
+ photo.album = album
+ if photo.album:
+ photo.album.updated_at = datetime.datetime.now()
+ photo.album.save(force_update=True)
+ photo.save()
+ flash(request, _('Photo updated') if id else _('Photo added'))
+ return redirect(reverse='photogallery-photos-show', id=photo.id)
+ else:
+ form = form_class(instance=photo)
+
+ ctx = extra_context or {}
+ ctx.update({
+ 'form': form,
+ 'photo': photo,
+ 'can_edit': auth.can_edit_photo(request.user, photo),
+ })
+
+ return render_to_response(template_name or 'photogallery/edit_photo.html',
+ ctx, RequestContext(request))
+
+
+@login_required
+@never_cache
+def delete(request, id, confirm=False, redirect_to=None, template_name=None, extra_context=None):
+ try:
+ photo = Photo.objects.published().get(id=id)
+ except Photo.DoesNotExist:
+ raise Http404
+
+ if confirm or request.POST.get('confirm'):
+ photo.delete()
+ flash(request, _('Photo deleted'))
+ return redirect(redirect_to or reverse('photogallery-album-photos', kwargs={'id':photo.album_id}))
+
+ ctx = extra_context or {}
+ ctx.update({
+ 'photo': photo,
+ })
+ return render_to_response(template_name or 'photogallery/delete_photo.html',
+ ctx, RequestContext(request))
+
+RE_SEARCH_SEPARATOR = re.compile('[\s\+]+')
+
+def search(request, keyword=None, **kwargs):
+ request_keyword = keyword or request.REQUEST.get('keyword').strip()
+ keywords = RE_SEARCH_SEPARATOR.split(request_keyword)
+ queryset = kwargs.get('queryset', Photo.objects)
+ extra_context = kwargs.get('extra_context', {})
+ if request_keyword:
+ tagged = tuple(Photo.tag_objects.with_any(keywords, queryset).values_list('id', flat=True))
+ photos = queryset
+ for keyword in keywords:
+ photos = photos.filter(Q(title__icontains=keyword) |
+ Q(description__icontains=keyword) | Q(pk__in=tagged) | Q(album__title__icontains=keyword) |
+ Q(album__description__icontains=keyword))
+ kwargs['queryset'] = photos
+ extra_context['keyword'] = request_keyword
+ else:
+ kwargs['queryset'] = queryset.none()
+ extra_context['search'] = True
+ extra_context['found_items_count'] = kwargs['queryset'].count()
+ kwargs['extra_context'] = extra_context
+ return list(request, **kwargs)
View
11 photogallery/widgets.py
@@ -0,0 +1,11 @@
+from django.forms import widgets
+from django.utils.safestring import mark_safe
+import models
+
+
+class AlbumSelectOrCreateWidget(widgets.Select):
+ def render(self, name, value, attrs=None, choices=()):
+ out = super(AlbumSelectOrCreateWidget, self).render(name, value, attrs, choices)
+ return mark_safe(out + '<input type="checkbox" name="create_album" value="1" />' +\
+ 'Nowy album: <input type="text" name="new_album_name" value="" size="16" />')
+

0 comments on commit b8bca35

Please sign in to comment.