Display audiobook project and sponsors info from metadata,
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 12 Aug 2011 12:23:41 +0000 (14:23 +0200)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 12 Aug 2011 12:23:41 +0000 (14:23 +0200)
Keep BookMedia filenames tied to media names (keep filename when updating the file, update on name change), which means overwriting the replaced files,
Split book files into dirs by type,
savemedia: update name on media replace, don't need to slugify though (BookMedia does it anyway)

apps/catalogue/management/commands/savemedia.py
apps/catalogue/models.py
apps/catalogue/views.py
wolnelektury/templates/catalogue/book_detail.html
wolnelektury/templates/catalogue/counters.html

index fdc25cb..49f1d48 100755 (executable)
@@ -6,7 +6,6 @@ import os.path
 
 from django.core.management.base import BaseCommand
 from django.core.files import File
-from slughifi import slughifi
 
 from catalogue.models import Book, BookMedia
 from catalogue.utils import ExistingFile
@@ -40,11 +39,12 @@ class Command(BaseCommand):
         try:
             assert source_sha1
             bm = book.media.get(type=ext, source_sha1=source_sha1)
-            print "Replacing media: %s (%s)" % (bm.name, ext)
+            print "Replacing media: %s (%s)" % (bm.name.encode('utf-8'), ext)
         except (AssertionError, BookMedia.DoesNotExist):
-            bm = BookMedia(book=book, type=ext, name=name)
+            bm = BookMedia(book=book, type=ext)
             print "Creating new media"
-        bm.file.save(slughifi(name), ExistingFile(path))
+        bm.name = name
+        bm.file.save(None, ExistingFile(path))
         bm.save()
         transaction.commit()
         transaction.leave_transaction_management()
index 84bcfd3..6291d97 100644 (file)
@@ -18,6 +18,7 @@ from django.conf import settings
 from newtagging.models import TagBase, tags_updated
 from newtagging import managers
 from catalogue.fields import JSONField
+from catalogue.utils import ExistingFile
 
 from librarian import dcparser, html, epub, NoDublinCore
 import mutagen
@@ -176,7 +177,7 @@ def book_upload_path(ext=None, maxlen=100):
             name = slughifi(filename.split(".")[0])
         else:
             name = slughifi(media.name)
-        return 'lektura/%s.%s' % (name[:maxlen-len('lektura/.%s' % ext)-4], ext)
+        return 'book/%s/%s.%s' % (ext, name[:maxlen-len('book/%s/.%s' % (ext, ext))-4], ext)
     return get_dynamic_path
 
 
@@ -198,6 +199,18 @@ class BookMedia(models.Model):
         verbose_name_plural = _('book media')
 
     def save(self, *args, **kwargs):
+        try:
+            b = BookMedia.objects.get(pk=self.pk)
+        except BookMedia.DoesNotExist, e:
+            pass
+        else:
+            # if file is replaced, delete the old one
+            if self.file.path != b.file.path:
+                b.file.delete(save=False)
+            # if name changed, change the file name, too
+            elif self.name != b.name:
+                self.file.save(None, ExistingFile(self.file.path))
+
         super(BookMedia, self).save(*args, **kwargs)
         extra_info = self.get_extra_info_value()
         extra_info.update(self.read_meta())
@@ -210,12 +223,16 @@ class BookMedia(models.Model):
             Reads some metadata from the audiobook.
         """
 
-        artist_name = director_name = ''
+        artist_name = director_name = project = funded_by = ''
         if self.type == 'mp3':
             try:
                 audio = id3.ID3(self.file.path)
                 artist_name = ', '.join(', '.join(tag.text) for tag in audio.getall('TPE1'))
                 director_name = ', '.join(', '.join(tag.text) for tag in audio.getall('TPE3'))
+                project = ", ".join([t.data for t in audio.getall('PRIV') 
+                        if t.owner=='wolnelektury.pl?project'])
+                funded_by = ", ".join([t.data for t in audio.getall('PRIV') 
+                        if t.owner=='wolnelektury.pl?funded_by'])
             except:
                 pass
         elif self.type == 'ogg':
@@ -223,11 +240,14 @@ class BookMedia(models.Model):
                 audio = mutagen.File(self.file.path)
                 artist_name = ', '.join(audio.get('artist', []))
                 director_name = ', '.join(audio.get('conductor', []))
+                project = ", ".join(audio.get('project', []))
+                funded_by = ", ".join(audio.get('funded_by', []))
             except:
                 pass
         else:
             return {}
-        return {'artist_name': artist_name, 'director_name': director_name}
+        return {'artist_name': artist_name, 'director_name': director_name,
+                'project': project, 'funded_by': funded_by}
 
     @staticmethod
     def read_source_sha1(filepath, filetype):
@@ -239,7 +259,7 @@ class BookMedia(models.Model):
             try:
                 audio = id3.ID3(filepath)
                 return [t.data for t in audio.getall('PRIV') 
-                        if t.owner=='http://wolnelektury.pl?flac_sha1'][0]
+                        if t.owner=='wolnelektury.pl?flac_sha1'][0]
             except:
                 return None
         elif filetype == 'ogg':
index ac778d4..c5eb0c7 100644 (file)
@@ -129,6 +129,8 @@ def daisy_list(request):
 
 
 def counters(request):
+    form = forms.SearchForm()
+
     books = models.Book.objects.count()
     books_nonempty = models.Book.objects.exclude(html_file='').count()
     books_empty = models.Book.objects.filter(html_file='').count()
@@ -139,7 +141,18 @@ def counters(request):
             annotate(count=Count('type')).\
             order_by('type')
     for mt in media_types:
-        mt['size'] = sum(b.file.size for b in models.BookMedia.objects.filter(type=mt['type']))
+        size = 0
+        deprecated = missing_project = 0
+        for b in models.BookMedia.objects.filter(type=mt['type']):
+            size += b.file.size
+            if b.type in ('mp3', 'ogg'):
+                if not b.source_sha1:
+                    deprecated += 1
+                if not 'project' in b.get_extra_info_value():
+                    missing_project += 1
+        mt['size'] = size
+        mt['deprecated'] = deprecated
+        mt['missing_project'] = missing_project
 
     return render_to_response('catalogue/counters.html',
                 locals(), context_instance=RequestContext(request))
@@ -294,6 +307,18 @@ def book_detail(request, slug):
 
     extra_info = book.get_extra_info_value()
 
+    projects = set()
+    for m in book.media.filter(type='mp3'):
+        # ogg files are always from the same project
+        meta = m.get_extra_info_value()
+        project = meta.get('project')
+        if not project:
+            # temporary fallback
+            project = u'CzytamySłuchając'
+            
+        projects.add((project, meta.get('funded_by')))
+    projects = sorted(projects)
+
     form = forms.SearchForm()
     return render_to_response('catalogue/book_detail.html', locals(),
         context_instance=RequestContext(request))
index 5454800..e6cc0f4 100644 (file)
                             </ul>
                         {% endif %}
                     </div> <!-- /audiobooks -->
-                    <p>{% blocktrans with '<a href="http://czytamysluchajac.pl">CzytamySłuchając</a>' as cs %}Audiobooks were prepared as a part of the {{ cs }} project.{% endblocktrans %}
-                    </p>
+                    {% if projects|length > 1 %}
+                        <p>{% trans "Audiobooks were prepared as a part of the projects:" %}</p>
+                        <ul>
+                        {% for cs, fb in projects %}
+                            <li>
+                            {% if fb %}
+                                {% blocktrans %}{{ cs }}, funded by {{ fb }}{% endblocktrans %}
+                            {% else %}
+                                {{ cs }}
+                            {% endif %}
+                            </li>
+                        {% endfor %}
+                        </ul>
+                    {% else %}
+                        <p>
+                        {% with cs=projects.0.0 fb=projects.0.1 %}
+                            {% if fb %}
+                                {% blocktrans %}Audiobooks were prepared as a part of the {{ cs }} project funded by {{ fb }}.{% endblocktrans %}
+                            {% else %}
+                                {% blocktrans %}Audiobooks were prepared as a part of the {{ cs }} project.{% endblocktrans %}
+                            {% endif %}
+                        {% endwith %}
+                        </p>
+                    {% endif %}
                 {% endif %}
             </div>
         </div>
index 572583c..9262a48 100755 (executable)
@@ -7,14 +7,24 @@
 
 {% block body %}
     <h1>Liczniki</h1>
+    <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
+        <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
+    </form>
 
     <table>
+        <tr><th>Utwory</th></tr>
         <tr><td>Wszystkie utwory:</td><td>{{ books }}</td></tr>
         <tr><td>Utwory z własną treścią:</td><td>{{ books_nonempty }}</td></tr>
         <tr><td>Utwory bez własnej treści:</td><td>{{ books_empty }}</td></tr>
         <tr><td>Niezależne książki:</td><td>{{ books_root }}</td></tr>
+
+        <tr><th>Media</th><th>Liczba</th><th>Rozmiar</th><th>Do wymiany</th></tr>
         {% for mt in media_types %}
-            <tr><td>Media – {{ mt.type }}:</td><td>{{ mt.count }}, {{ mt.size|filesizeformat }}</td></tr>
+            <tr><td>{{ mt.type }}:</td>
+                <td>{{ mt.count }}</td>
+                <td>{{ mt.size|filesizeformat }}</td>
+                <td>{{ mt.deprecated }}</td>
+            </tr>
         {% endfor %}
     </table>