detail page getting shape
[wolnelektury.git] / apps / api / handlers.py
index 9bb8900..d34806f 100644 (file)
@@ -15,7 +15,10 @@ from api.helpers import timestamp
 from api.models import Deleted
 from catalogue.forms import BookImportForm
 from catalogue.models import Book, Tag, BookMedia, Fragment
 from api.models import Deleted
 from catalogue.forms import BookImportForm
 from catalogue.models import Book, Tag, BookMedia, Fragment
+from picture.models import Picture
+from picture.forms import PictureImportForm
 
 
+from stats.utils import piwik_track
 
 API_BASE = WL_BASE = MEDIA_BASE = 'http://' + Site.objects.get_current().domain
 
 
 API_BASE = WL_BASE = MEDIA_BASE = 'http://' + Site.objects.get_current().domain
 
@@ -92,15 +95,18 @@ class BookDetailHandler(BaseHandler):
 
     """
     allowed_methods = ['GET']
 
     """
     allowed_methods = ['GET']
-    fields = ['title', 'parent',
-        'xml', 'html', 'pdf', 'epub', 'txt',
+    fields = ['title', 'parent'] + Book.formats + [
         'media', 'url'] + category_singular.keys()
 
         'media', 'url'] + category_singular.keys()
 
-    def read(self, request, slug):
-        """ Returns details of a book, identified by a slug. """
+    @piwik_track
+    def read(self, request, book):
+        """ Returns details of a book, identified by a slug and lang. """
+        kwargs = Book.split_urlid(book)
+        if not kwargs:
+            return rc.NOT_FOUND
 
         try:
 
         try:
-            return Book.objects.get(slug=slug)
+            return Book.objects.get(**kwargs)
         except Book.DoesNotExist:
             return rc.NOT_FOUND
 
         except Book.DoesNotExist:
             return rc.NOT_FOUND
 
@@ -121,7 +127,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler):
     @classmethod
     def href(cls, book):
         """ Returns an URI for a Book in the API. """
     @classmethod
     def href(cls, book):
         """ Returns an URI for a Book in the API. """
-        return API_BASE + reverse("api_book", args=[book.slug])
+        return API_BASE + reverse("api_book", args=[book.urlid()])
 
     @classmethod
     def url(cls, book):
 
     @classmethod
     def url(cls, book):
@@ -129,6 +135,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler):
 
         return WL_BASE + book.get_absolute_url()
 
 
         return WL_BASE + book.get_absolute_url()
 
+    @piwik_track
     def read(self, request, tags, top_level=False):
         """ Lists all books with given tags.
 
     def read(self, request, tags, top_level=False):
         """ Lists all books with given tags.
 
@@ -200,7 +207,7 @@ def _file_getter(format):
         else:
             return ''
     return get_file
         else:
             return ''
     return get_file
-for format in ('xml', 'txt', 'html', 'epub', 'pdf'):
+for format in Book.formats:
     setattr(BooksHandler, format, _file_getter(format))
 
 
     setattr(BooksHandler, format, _file_getter(format))
 
 
@@ -209,6 +216,7 @@ class TagDetailHandler(BaseHandler):
 
     fields = ['name', 'sort_key', 'description']
 
 
     fields = ['name', 'sort_key', 'description']
 
+    @piwik_track
     def read(self, request, category, slug):
         """ Returns details of a tag, identified by category and slug. """
 
     def read(self, request, category, slug):
         """ Returns details of a tag, identified by category and slug. """
 
@@ -234,6 +242,7 @@ class TagsHandler(BaseHandler):
     model = Tag
     fields = ['name', 'href']
 
     model = Tag
     fields = ['name', 'href']
 
+    @piwik_track
     def read(self, request, category):
         """ Lists all tags in the category (eg. all themes). """
 
     def read(self, request, category):
         """ Lists all tags in the category (eg. all themes). """
 
@@ -242,9 +251,8 @@ class TagsHandler(BaseHandler):
         except KeyError, e:
             return rc.NOT_FOUND
 
         except KeyError, e:
             return rc.NOT_FOUND
 
-        tags = Tag.objects.filter(category=category_sng)
-        tags = [t for t in tags if t.get_count() > 0]
-        if tags:
+        tags = Tag.objects.filter(category=category_sng).exclude(book_count=0)
+        if tags.exists():
             return tags
         else:
             return rc.NOT_FOUND
             return tags
         else:
             return rc.NOT_FOUND
@@ -260,11 +268,19 @@ class TagsHandler(BaseHandler):
 class FragmentDetailHandler(BaseHandler):
     fields = ['book', 'anchor', 'text', 'url', 'themes']
 
 class FragmentDetailHandler(BaseHandler):
     fields = ['book', 'anchor', 'text', 'url', 'themes']
 
-    def read(self, request, slug, anchor):
+    @piwik_track
+    def read(self, request, book, anchor):
         """ Returns details of a fragment, identified by book slug and anchor. """
         """ Returns details of a fragment, identified by book slug and anchor. """
+        kwargs = Book.split_urlid(book)
+        if not kwargs:
+            return rc.NOT_FOUND
+
+        fragment_kwargs = {}
+        for field, value in kwargs.items():
+            fragment_kwargs['book__' + field] = value
 
         try:
 
         try:
-            return Fragment.objects.get(book__slug=slug, anchor=anchor)
+            return Fragment.objects.get(anchor=anchor, **fragment_kwargs)
         except Fragment.DoesNotExist:
             return rc.NOT_FOUND
 
         except Fragment.DoesNotExist:
             return rc.NOT_FOUND
 
@@ -282,6 +298,7 @@ class FragmentsHandler(BaseHandler):
 
     categories = set(['author', 'epoch', 'kind', 'genre', 'book', 'theme'])
 
 
     categories = set(['author', 'epoch', 'kind', 'genre', 'book', 'theme'])
 
+    @piwik_track
     def read(self, request, tags):
         """ Lists all fragments with given book, tags, themes.
 
     def read(self, request, tags):
         """ Lists all fragments with given book, tags, themes.
 
@@ -300,7 +317,7 @@ class FragmentsHandler(BaseHandler):
     def href(cls, fragment):
         """ Returns URI in the API for the fragment. """
 
     def href(cls, fragment):
         """ Returns URI in the API for the fragment. """
 
-        return API_BASE + reverse("api_fragment", args=[fragment.book.slug, fragment.anchor])
+        return API_BASE + reverse("api_fragment", args=[fragment.book.urlid(), fragment.anchor])
 
     @classmethod
     def url(cls, fragment):
 
     @classmethod
     def url(cls, fragment):
@@ -346,16 +363,15 @@ class CatalogueHandler(BaseHandler):
 
     @staticmethod
     def book_dict(book, fields=None):
 
     @staticmethod
     def book_dict(book, fields=None):
-        all_fields = ('url', 'title', 'description',
+        all_fields = ['url', 'title', 'description',
                       'gazeta_link', 'wiki_link',
                       'gazeta_link', 'wiki_link',
-                      'xml', 'epub', 'txt', 'pdf', 'html',
-                      'mp3', 'ogg', 'daisy',
+                      ] + Book.formats + BookMedia.formats + [
                       'parent', 'parent_number',
                       'tags',
                       'license', 'license_description', 'source_name',
                       'technical_editors', 'editors',
                       'author', 'sort_key',
                       'parent', 'parent_number',
                       'tags',
                       'license', 'license_description', 'source_name',
                       'technical_editors', 'editors',
                       'author', 'sort_key',
-                     )
+                     ]
         if fields:
             fields = (f for f in fields if f in all_fields)
         else:
         if fields:
             fields = (f for f in fields if f in all_fields)
         else:
@@ -366,7 +382,7 @@ class CatalogueHandler(BaseHandler):
         obj = {}
         for field in fields:
 
         obj = {}
         for field in fields:
 
-            if field in ('xml', 'epub', 'txt', 'pdf', 'html'):
+            if field in Book.formats:
                 f = getattr(book, field+'_file')
                 if f:
                     obj[field] = {
                 f = getattr(book, field+'_file')
                 if f:
                     obj[field] = {
@@ -374,7 +390,7 @@ class CatalogueHandler(BaseHandler):
                         'size': f.size,
                     }
 
                         'size': f.size,
                     }
 
-            elif field in ('mp3', 'ogg', 'daisy'):
+            elif field in BookMedia.formats:
                 media = []
                 for m in book.media.filter(type=field):
                     media.append({
                 media = []
                 for m in book.media.filter(type=field):
                     media.append({
@@ -503,7 +519,7 @@ class CatalogueHandler(BaseHandler):
                     changed_at__gte=since,
                     changed_at__lt=until):
             # only serve non-empty tags
                     changed_at__gte=since,
                     changed_at__lt=until):
             # only serve non-empty tags
-            if tag.get_count():
+            if tag.book_count:
                 tag_d = cls.tag_dict(tag, fields)
                 updated.append(tag_d)
             elif tag.created_at < since:
                 tag_d = cls.tag_dict(tag, fields)
                 updated.append(tag_d)
             elif tag.created_at < since:
@@ -547,6 +563,7 @@ class CatalogueHandler(BaseHandler):
 class BookChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
 class BookChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
+    @piwik_track
     def read(self, request, since):
         return self.book_changes(request, since)
 
     def read(self, request, since):
         return self.book_changes(request, since)
 
@@ -554,6 +571,7 @@ class BookChangesHandler(CatalogueHandler):
 class TagChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
 class TagChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
+    @piwik_track
     def read(self, request, since):
         return self.tag_changes(request, since)
 
     def read(self, request, since):
         return self.tag_changes(request, since)
 
@@ -561,5 +579,24 @@ class TagChangesHandler(CatalogueHandler):
 class ChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
 class ChangesHandler(CatalogueHandler):
     allowed_methods = ('GET',)
 
+    @piwik_track
     def read(self, request, since):
         return self.changes(request, since)
     def read(self, request, since):
         return self.changes(request, since)
+
+
+class PictureHandler(BaseHandler):
+    model = Picture
+    fields = ('slug', 'title')
+    allowed_methods = ('POST',)
+
+    def create(self, request):
+        if not request.user.has_perm('picture.add_picture'):
+            return rc.FORBIDDEN
+
+        data = json.loads(request.POST.get('data'))
+        form = PictureImportForm(data)
+        if form.is_valid():
+            form.save()
+            return rc.CREATED
+        else:
+            return rc.NOT_FOUND