# -*- coding: utf-8 -*-
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
-
+#
from datetime import datetime, timedelta
import json
-from urlparse import urljoin
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.cache import get_cache
from django.core.urlresolvers import reverse
+from django.utils.functional import lazy
+from django.utils.timezone import utc
from piston.handler import AnonymousBaseHandler, BaseHandler
from piston.utils import rc
from sorl.thumbnail import default
from api.models import Deleted
from catalogue.forms import BookImportForm
from catalogue.models import Book, Tag, BookMedia, Fragment, Collection
+from catalogue.utils import related_tag_name
from picture.models import Picture
from picture.forms import PictureImportForm
+from wolnelektury.utils import tz
from stats.utils import piwik_track
-API_BASE = WL_BASE = MEDIA_BASE = 'http://' + Site.objects.get_current().domain
+API_BASE = WL_BASE = MEDIA_BASE = lazy(
+ lambda: u'http://' + Site.objects.get_current().domain, unicode)()
category_singular = {
'themes': 'theme',
'books': 'book',
}
-category_plural={}
+category_plural = {}
for k, v in category_singular.items():
category_plural[v] = k
@classmethod
def director(cls, media):
return media.extra_info.get('director_name', '')
-
class BookDetails(object):
"""Custom fields used for representing Books."""
- @classmethod
- def author(cls, book):
- return ",".join(t[0] for t in book.related_info()['tags'].get('author', []))
-
@classmethod
def href(cls, book):
""" Returns an URI for a Book in the API. """
"""
allowed_methods = ('GET',)
model = Book
- fields = ['author', 'href', 'title', 'url', 'cover']
+ fields = book_tag_categories + ['href', 'title', 'url', 'cover', 'cover_thumb']
+
+ @classmethod
+ def genres(cls, book):
+ """ Returns all media for a book. """
+ return book.tags.filter(category='genre')
@piwik_track
def read(self, request, tags, top_level=False,
books = Book.tagged.with_all(tags)
else:
books = Book.objects.all()
-
+
if top_level:
books = books.filter(parent=None)
if audiobooks:
class BooksHandler(BookDetailHandler):
allowed_methods = ('GET', 'POST')
model = Book
- fields = ['author', 'href', 'title', 'url']
+ fields = book_tag_categories + ['href', 'title', 'url', 'cover', 'cover_thumb']
anonymous = AnonymousBooksHandler
def create(self, request, *args, **kwargs):
def get_tags(cls, book):
return book.tags.filter(category=category)
return get_tags
+def _tag_getter(category):
+ @classmethod
+ def get_tag(cls, book):
+ return ", ".join(related_tag_name(t) for t in book.related_info()['tags'].get(category, []))
+ return get_tag
for plural, singular in category_singular.items():
setattr(BookDetails, plural, _tags_getter(singular))
+ setattr(BookDetails, singular, _tag_getter(singular))
# add fields for files in Book
def _file_getter(format):
@piwik_track
def read(self, request, slug):
- print slug
""" Returns details of a collection, identified by slug. """
try:
return Collection.objects.get(slug=slug)
def href(cls, fragment):
""" Returns URI in the API for the fragment. """
- return API_BASE + reverse("api_fragment",
+ return API_BASE + reverse("api_fragment",
args=[fragment.book.slug, fragment.anchor])
@classmethod
"""
# set to five minutes ago, to avoid concurrency issues
if t is None:
- t = datetime.now() - timedelta(seconds=settings.API_WAIT)
+ t = datetime.utcnow().replace(tzinfo=utc) - timedelta(seconds=settings.API_WAIT)
# set to whole second in case DB supports something smaller
return t.replace(microsecond=0)
@classmethod
def book_changes(cls, request=None, since=0, until=None, fields=None):
- since = datetime.fromtimestamp(int(since))
+ since = datetime.fromtimestamp(int(since), tz)
until = cls.until(until)
changes = {
if updated:
changes['updated'] = updated
- for book in Deleted.objects.filter(content_type=Book,
+ for book in Deleted.objects.filter(content_type=Book,
deleted_at__gte=since,
deleted_at__lt=until,
created_at__lt=since).iterator():
@classmethod
def tag_changes(cls, request=None, since=0, until=None, fields=None, categories=None):
- since = datetime.fromtimestamp(int(since))
+ since = datetime.fromtimestamp(int(since), tz)
until = cls.until(until)
changes = {
updated = []
deleted = []
- for tag in Tag.objects.filter(category__in=categories,
+ for tag in Tag.objects.filter(category__in=categories,
changed_at__gte=since,
changed_at__lt=until).iterator():
# only serve non-empty tags
changes['updated'] = updated
for tag in Deleted.objects.filter(category__in=categories,
- content_type=Tag,
+ content_type=Tag,
deleted_at__gte=since,
deleted_at__lt=until,
created_at__lt=since).iterator():