From: Marcin Koziej Date: Tue, 20 Dec 2011 09:37:37 +0000 (+0100) Subject: merge picture to pretty X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/3438c79639fca7268c397dd3fcfdcf9ca5014a09?ds=sidebyside merge picture to pretty --- diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index 8b65d4bbb..6470ebb83 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -174,7 +174,11 @@ class Tag(TagBase): try: tag_names = getattr(info, field_name) except: - tag_names = [getattr(info, category)] + try: + tag_names = [getattr(info, category)] + except: + # For instance, Pictures do not have 'genre' field. + continue for tag_name in tag_names: tag_sort_key = tag_name if category == 'author': diff --git a/apps/catalogue/urls.py b/apps/catalogue/urls.py index 452335aca..bb1b96033 100644 --- a/apps/catalogue/urls.py +++ b/apps/catalogue/urls.py @@ -5,7 +5,7 @@ from django.conf.urls.defaults import * from catalogue.feeds import AudiobookFeed from catalogue.models import Book - +from picture.models import Picture urlpatterns = patterns('catalogue.views', url(r'^$', 'catalogue', name='catalogue'), @@ -43,5 +43,10 @@ urlpatterns = patterns('catalogue.views', url(r'^audiobooki/(?Pmp3|ogg|daisy|all).xml$', AudiobookFeed(), name='audiobook_feed'), url(r'^custompdf/(?P%s).pdf' % Book.FILEID_RE, 'download_custom_pdf'), -) + +) + patterns('picture.views', + # pictures - currently pictures are coupled with catalogue, hence the url is here + url(r'^obraz/?$', 'picture_list'), + url(r'^obraz/(?P%s)/?$' % Picture.URLID_RE, 'picture_detail') + ) diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 902907db9..13bb5ac18 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -226,7 +226,7 @@ def book_detail(request, book): book = models.Book.objects.get(**kwargs) except models.Book.DoesNotExist: return pdcounter_views.book_stub_detail(request, kwargs['slug']) - + book_tag = book.book_tag() tags = list(book.tags.filter(~Q(category='set'))) categories = split_tags(tags) diff --git a/apps/picture/admin.py b/apps/picture/admin.py new file mode 100644 index 000000000..fb6bcf261 --- /dev/null +++ b/apps/picture/admin.py @@ -0,0 +1,9 @@ + +from django.contrib import admin +from picture.models import Picture +from sorl.thumbnail.admin import AdminImageMixin + +class PictureAdmin(AdminImageMixin, admin.ModelAdmin): + pass + +admin.site.register(Picture, PictureAdmin) diff --git a/apps/picture/models.py b/apps/picture/models.py index af691f8ae..01f9b8d48 100644 --- a/apps/picture/models.py +++ b/apps/picture/models.py @@ -1,8 +1,12 @@ from django.db import models import catalogue.models -from catalogue.fields import OverwritingFileField +from django.db.models import permalink +from sorl.thumbnail import ImageField from django.conf import settings from django.core.files.storage import FileSystemStorage +from django.utils.datastructures import SortedDict +from librarian import dcparser, picture + from django.utils.translation import ugettext_lazy as _ from newtagging import managers from os import path @@ -22,7 +26,7 @@ class Picture(models.Model): created_at = models.DateTimeField(_('creation date'), auto_now_add=True, db_index=True) changed_at = models.DateTimeField(_('creation date'), auto_now=True, db_index=True) xml_file = models.FileField('xml_file', upload_to="xml", storage=picture_storage) - image_file = models.FileField(_('image_file'), upload_to="images", storage=picture_storage) + image_file = ImageField(_('image_file'), upload_to="images", storage=picture_storage) objects = models.Manager() tagged = managers.ModelTaggedItemManager(catalogue.models.Tag) tags = managers.TagDescriptor(catalogue.models.Tag) @@ -36,6 +40,9 @@ class Picture(models.Model): verbose_name = _('picture') verbose_name_plural = _('pictures') + URLID_RE = r'[a-z0-9-]+' + FILEID_RE = r'[a-z0-9-]+' + def save(self, force_insert=False, force_update=False, reset_short_html=True, **kwargs): from sortify import sortify @@ -48,6 +55,13 @@ class Picture(models.Model): def __unicode__(self): return self.title + @permalink + def get_absolute_url(self): + return ('picture.views.picture_detail', [self.urlid()]) + + def urlid(self): + return self.slug + @classmethod def from_xml_file(cls, xml_file, images_path=None, overwrite=False): """ @@ -84,3 +98,37 @@ class Picture(models.Model): if close_xml_file: xml_file.close() return picture + + @classmethod + def picture_list(cls, filter=None): + """Generates a hierarchical listing of all pictures + Pictures are optionally filtered with a test function. + """ + + pics = cls.objects.all().order_by('sort_key')\ + .only('title', 'slug', 'image_file') + + if filter: + pics = pics.filter(filter).distinct() + + pics_by_author = SortedDict() + orphans = [] + for tag in catalogue.models.Tag.objects.filter(category='author'): + pics_by_author[tag] = [] + + for pic in pics: + authors = list(pic.tags.filter(category='author')) + if authors: + for author in authors: + pics_by_author[author].append(pic) + else: + orphans.append(pic) + + return pics_by_author, orphans + + @property + def info(self): + if not hasattr(self, '_info'): + info = dcparser.parse(self.xml_file.path, picture.PictureInfo) + self._info = info + return self._info diff --git a/apps/picture/views.py b/apps/picture/views.py new file mode 100644 index 000000000..105f6b863 --- /dev/null +++ b/apps/picture/views.py @@ -0,0 +1,35 @@ +from catalogue import forms +from picture.models import Picture +from django.utils.datastructures import SortedDict +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext + + +def picture_list(request, filter=None, template_name='catalogue/picture_list.html'): + """ generates a listing of all books, optionally filtered with a test function """ + + form = forms.SearchForm() + + pictures_by_author, orphans = Picture.picture_list() + books_nav = SortedDict() + for tag in pictures_by_author: + if pictures_by_author[tag]: + books_nav.setdefault(tag.sort_key[0], []).append(tag) + + # import pdb; pdb.set_trace() + return render_to_response(template_name, locals(), + context_instance=RequestContext(request)) + + +def picture_detail(request, picture): + form = forms.SearchForm() + picture = get_object_or_404(Picture, slug=picture) + + categories = SortedDict() + for tag in picture.tags: + categories.setdefault(tag.category, []).append(tag) + + picture_themes = [] + + return render_to_response("catalogue/picture_detail.html", locals(), + context_instance=RequestContext(request)) diff --git a/apps/sponsors/models.py b/apps/sponsors/models.py index 4357d7863..1e0d2e52d 100644 --- a/apps/sponsors/models.py +++ b/apps/sponsors/models.py @@ -12,8 +12,9 @@ from PIL import Image from sponsors.fields import JSONField from django.core.files.base import ContentFile -THUMB_WIDTH=120 -THUMB_HEIGHT=120 +THUMB_WIDTH = 120 +THUMB_HEIGHT = 120 + class Sponsor(models.Model): name = models.CharField(_('name'), max_length=120) @@ -57,7 +58,7 @@ class SponsorPage(models.Model): for column in self.get_sponsors_value(): sponsor_ids.extend(column['sponsors']) sponsors = Sponsor.objects.in_bulk(sponsor_ids) - sprite = Image.new('RGBA', (THUMB_WIDTH, len(sponsors)*THUMB_HEIGHT)) + sprite = Image.new('RGBA', (THUMB_WIDTH, len(sponsors) * THUMB_HEIGHT)) for i, sponsor_id in enumerate(sponsor_ids): simg = Image.open(sponsors[sponsor_id].logo.path) if simg.size[0] > THUMB_WIDTH or simg.size[1] > THUMB_HEIGHT: diff --git a/lib/librarian b/lib/librarian index 808e7c296..262c7082c 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 808e7c2967440cacbc15af82cde171e10aea8a6a +Subproject commit 262c7082c23ab266254175438d1524470996c4d2 diff --git a/requirements.txt b/requirements.txt index 5f994419d..52ffd1f47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ Feedparser>=4.1 # PIL PIL>=1.1.6 mutagen>=1.17 -sorl-thumbnail>=10,<12 +sorl-thumbnail>=11.09<12 # home-brewed & dependencies lxml>=2.2.2 diff --git a/wolnelektury/static/css/master.css b/wolnelektury/static/css/master.css index 739ecee91..85f1a40d7 100644 --- a/wolnelektury/static/css/master.css +++ b/wolnelektury/static/css/master.css @@ -1195,4 +1195,22 @@ div.shown-tags p, div.all-tags p { /* report */ .stats td { vertical-align: top; -} \ No newline at end of file +} + +/* ============ */ +/* = Pictures = */ +/* ============ */ + + +#picture-list .picture .title { + font-weight: bold; +} + +#picture-list .picture { + background-color: white; + padding: 0.8em; + margin: 0.8em; + border: black 1px solid; + width: 600px; +} + diff --git a/wolnelektury/templates/catalogue/book_list.html b/wolnelektury/templates/catalogue/book_list.html index dd01066e8..ec6aae8c6 100644 --- a/wolnelektury/templates/catalogue/book_list.html +++ b/wolnelektury/templates/catalogue/book_list.html @@ -33,6 +33,7 @@ {% endfor %}
+ {% block book_list %} {% book_tree orphans books_by_parent %} {% for author, group in books_by_author.items %} {% if group %} @@ -43,6 +44,7 @@
{% endif %} {% endfor %} + {% endblock %}

{% trans "↑ top ↑" %}

diff --git a/wolnelektury/templates/catalogue/picture_detail.html b/wolnelektury/templates/catalogue/picture_detail.html new file mode 100644 index 000000000..dbea337a6 --- /dev/null +++ b/wolnelektury/templates/catalogue/picture_detail.html @@ -0,0 +1,103 @@ +{% extends "base.html" %} +{% load i18n %} +{% load catalogue_tags pagination_tags %} +{% load thumbnail %} + + +{% block title %}{{ picture.title }} {% trans "on WolneLektury.pl" %}{% endblock %} + +{% block bodyid %}picture-detail{% endblock %} + +{% block body %} +

{{picture.title}}

+
+

{{ form.q }} {% trans "or" %} {% trans "return to main page" %}

+
+ +
+ + + {% thumbnail picture.image_file "400x500" upscale="false" as im %} + + {% endthumbnail %} + + {% if picture.info.license %} +

{% trans "Work is licensed under " %} {{ picture.info.license_description }}.

+ {% endif %} +

{% trans "Based on" %}: {{ picture.info.source_name }}

+ {% if picture.info.description %} +
+
{{ picture.info.description|safe }}
+
{{ picture.info.description|safe|truncatewords_html:30 }}
+
+

+ {% endif %} + +
+ +
+
+

{% trans "Details" %}

+
    +
  • + {% trans "Author" %}: + {% for tag in categories.author %} + {{ tag }}{% if not forloop.last %}, {% endif %} + {% endfor %} +
  • +
  • + {% trans "Epoch" %}: + {% for tag in categories.epoch %} + {{ tag }}{% if not forloop.last %}, {% endif %} + {% endfor %} +
  • +
  • + {% trans "Kind" %}: + {% for tag in categories.kind %} + {{ tag }}{% if not forloop.last %}, {% endif %} + {% endfor %} +
  • +
+

{% trans "Other resources" %}

+ +

{% trans "View XML source" %}

+
+
+

{% trans "Work's themes " %}

+ +
+
+
+
+ +
+

* {% trans "Loading" %}

+
+
+{% endblock %} diff --git a/wolnelektury/templates/catalogue/picture_list.html b/wolnelektury/templates/catalogue/picture_list.html new file mode 100644 index 000000000..c4edda899 --- /dev/null +++ b/wolnelektury/templates/catalogue/picture_list.html @@ -0,0 +1,32 @@ +{% extends "catalogue/book_list.html" %} +{% load i18n %} +{% load catalogue_tags chunks %} +{% load thumbnail %} + +{% block bodyid %}picture-list{% endblock %} + +{% block title %}{% trans "Listing of all pictures on WolneLektury.pl" %}{% endblock %} + +{% block picture_list_header %}{% trans "Listing of all pictures" %}{% endblock %} + + +{% block book_list %} +{% for author, group in pictures_by_author.items %} + +
+

{{ author }}

+ {% for picture in group %} +
+ {% thumbnail picture.image_file "300x300" as im %} + + {% endthumbnail %} + {{picture.title}} +
+
+ {% endfor %} +
+ +{% endfor %} + +{% endblock %} +