fix media overwriting,
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 12 Aug 2011 16:02:13 +0000 (18:02 +0200)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 12 Aug 2011 16:02:13 +0000 (18:02 +0200)
django 1.2 compatibility fix,
some tests

apps/catalogue/fields.py
apps/catalogue/models.py
apps/catalogue/tests/bookmedia.py
wolnelektury/templates/catalogue/book_detail.html

index e2d94b9..4de2e7c 100644 (file)
@@ -3,9 +3,11 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import datetime
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import datetime
+from functools import wraps
 
 from django.conf import settings
 from django.db import models
 
 from django.conf import settings
 from django.db import models
+from django.db.models.fields.files import FieldFile
 from django.db.models import signals
 from django import forms
 from django.forms.widgets import flatatt
 from django.db.models import signals
 from django import forms
 from django.forms.widgets import flatatt
@@ -124,3 +126,20 @@ try:
     ), ], ["^catalogue\.fields\.JSONField"])
 except ImportError:
     pass
     ), ], ["^catalogue\.fields\.JSONField"])
 except ImportError:
     pass
+
+
+class OverwritingFieldFile(FieldFile):
+    """
+        Deletes the old file before saving the new one.
+    """
+
+    def save(self, *args, **kwargs):
+        leave = kwargs.pop('leave', None)
+        if not leave and self:
+            self.delete(save=False)
+        return super(OverwritingFieldFile, self).save(*args, **kwargs)
+
+
+class OverwritingFileField(models.FileField):
+    attr_class = OverwritingFieldFile
+
index 6291d97..df7a79e 100644 (file)
@@ -17,7 +17,7 @@ from django.conf import settings
 
 from newtagging.models import TagBase, tags_updated
 from newtagging import managers
 
 from newtagging.models import TagBase, tags_updated
 from newtagging import managers
-from catalogue.fields import JSONField
+from catalogue.fields import JSONField, OverwritingFileField
 from catalogue.utils import ExistingFile
 
 from librarian import dcparser, html, epub, NoDublinCore
 from catalogue.utils import ExistingFile
 
 from librarian import dcparser, html, epub, NoDublinCore
@@ -184,7 +184,7 @@ def book_upload_path(ext=None, maxlen=100):
 class BookMedia(models.Model):
     type        = models.CharField(_('type'), choices=MEDIA_FORMATS, max_length="100")
     name        = models.CharField(_('name'), max_length="100")
 class BookMedia(models.Model):
     type        = models.CharField(_('type'), choices=MEDIA_FORMATS, max_length="100")
     name        = models.CharField(_('name'), max_length="100")
-    file        = models.FileField(_('file'), upload_to=book_upload_path())
+    file        = OverwritingFileField(_('file'), upload_to=book_upload_path())
     uploaded_at = models.DateTimeField(_('creation date'), auto_now_add=True, editable=False)
     extra_info  = JSONField(_('extra information'), default='{}', editable=False)
     book = models.ForeignKey('Book', related_name='media')
     uploaded_at = models.DateTimeField(_('creation date'), auto_now_add=True, editable=False)
     extra_info  = JSONField(_('extra information'), default='{}', editable=False)
     book = models.ForeignKey('Book', related_name='media')
@@ -200,16 +200,13 @@ class BookMedia(models.Model):
 
     def save(self, *args, **kwargs):
         try:
 
     def save(self, *args, **kwargs):
         try:
-            b = BookMedia.objects.get(pk=self.pk)
+            old = BookMedia.objects.get(pk=self.pk)
         except BookMedia.DoesNotExist, e:
             pass
         else:
         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
             # if name changed, change the file name, too
-            elif self.name != b.name:
-                self.file.save(None, ExistingFile(self.file.path))
+            if self.name != old.name:
+                self.file.save(None, ExistingFile(self.file.path), save=False, leave=True)
 
         super(BookMedia, self).save(*args, **kwargs)
         extra_info = self.get_extra_info_value()
 
         super(BookMedia, self).save(*args, **kwargs)
         extra_info = self.get_extra_info_value()
index 72fb030..0578ecd 100644 (file)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
-
+from os.path import basename
 from django.core.files.base import ContentFile
 
 from catalogue.test_utils import *
 from django.core.files.base import ContentFile
 
 from catalogue.test_utils import *
@@ -10,24 +10,77 @@ class BookMediaTests(WLTestCase):
     def setUp(self):
         WLTestCase.setUp(self)
         self.file = ContentFile('X')
     def setUp(self):
         WLTestCase.setUp(self)
         self.file = ContentFile('X')
+        self.file2 = ContentFile('Y')
+        self.book = models.Book.objects.create(slug='test-book')
 
     def test_diacritics(self):
 
     def test_diacritics(self):
-        bm = models.BookMedia.objects.create(type="ogg", 
-                    name="Zażółć gęślą jaźń")
-        bm.file.save(bm.name, self.file)
-        self.assertEqual(bm.file.name.rsplit('/', 1)[-1], 'zazolc-gesla-jazn.ogg')
-
+        bm = models.BookMedia(book=self.book, type="ogg", 
+                    name=u"Zażółć gęślą jaźń")
+        bm.file.save(None, self.file)
+        self.assertEqual(basename(bm.file.name), 'zazolc-gesla-jazn.ogg')
 
     def test_long_name(self):
 
     def test_long_name(self):
-        bm = models.BookMedia.objects.create(type="ogg", 
+        bm = models.BookMedia(book=self.book, type="ogg", 
                     name="Some very very very very very very very very very very very very very very very very long file name")
                     name="Some very very very very very very very very very very very very very very very very long file name")
-
-        # save twice so Django adds some stuff
         bm.file.save(bm.name, self.file)
         bm.file.save(bm.name, self.file)
-        bm.file.save(bm.name, self.file)
-        bm.save()
 
         # reload to see what was really saved
         bm = models.BookMedia.objects.get(pk=bm.pk)
         self.assertEqual(bm.file.size, 1)
 
 
         # reload to see what was really saved
         bm = models.BookMedia.objects.get(pk=bm.pk)
         self.assertEqual(bm.file.size, 1)
 
+    def test_overwrite(self):
+        """
+            File gets overwritten with same filename on update.
+        """
+
+        bm = models.BookMedia(book=self.book, type='ogg',
+                    name="Some media")
+        bm.file.save(None, self.file)
+        bm.file.save(None, self.file2)
+
+        self.assertEqual(bm.file.read(), 'Y')
+        self.assertEqual(basename(bm.file.name), 'some-media.ogg')
+
+    def test_no_clobber(self):
+        """
+            File save doesn't clobber some other media with similar name.
+        """
+
+        bm = models.BookMedia(book=self.book, type='ogg',
+            name="Tytul")
+        bm.file.save(None, self.file)
+        bm2 = models.BookMedia(book=self.book, type='ogg',
+            name="Tytuł")
+        bm2.file.save(None, self.file2)
+        self.assertEqual(basename(bm.file.name), 'tytul.ogg')
+        self.assertNotEqual(basename(bm2.file.name), 'tytul.ogg')
+        self.assertEqual(bm.file.read(), 'X')
+        self.assertEqual(bm2.file.read(), 'Y')
+
+    def test_change_name(self):
+        """
+            File name reflects name change.
+        """
+
+        bm = models.BookMedia(book=self.book, type='ogg', name="Title")
+        bm.file.save(None, self.file)
+        bm.name = "Other Title"
+        bm.save()
+        self.assertEqual(basename(bm.file.name), 'other-title.ogg')
+        self.assertEqual(bm.file.read(), 'X')
+
+    def test_change_name_no_clobber(self):
+        """
+            File name after change won't clobber some other file
+            with similar name.
+        """
+
+        bm = models.BookMedia(book=self.book, type='ogg', name="Title")
+        bm.file.save(None, self.file)
+        bm2 = models.BookMedia(book=self.book, type='ogg', name="Other title")
+        bm2.file.save(None, self.file2)
+        bm2.name = "Title"
+        bm2.save()
+        self.assertNotEqual(basename(bm2.file.name), 'title.ogg')
+        self.assertEqual(bm.file.read(), 'X')
+        self.assertEqual(bm2.file.read(), 'Y')
index e6cc0f4..7d0adcb 100644 (file)
                         </ul>
                     {% else %}
                         <p>
                         </ul>
                     {% else %}
                         <p>
-                        {% with cs=projects.0.0 fb=projects.0.1 %}
+                        {% with projects.0.0 as cs %}
+                        {% with projects.0.1 as fb %}
                             {% 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 %}
                             {% 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 %}
+                        {% endwith %}
                         </p>
                     {% endif %}
                 {% endif %}
                         </p>
                     {% endif %}
                 {% endif %}