def delete_file_if_needed(instance, filefield_name): """Delete file from database only if needed. When editing and the filefield is a new file, deletes the previous file (if any) from the database. Call this function immediately BEFORE saving the instance. """ if instance.pk: model_class = type(instance) # Check if there is a file for the instance in the database if model_class.objects.filter(pk=instance.pk).exclude( **{ '%s__isnull' % filefield_name: True }).exclude(**{ '%s__exact' % filefield_name: '' }).exists(): old_file = getattr( model_class.objects.only(filefield_name).get(pk=instance.pk), filefield_name) else: old_file = None # If there is a file, delete it if needed if old_file: # When editing and NOT changing the file, # old_file.name == getattr(instance, filefield_name) # returns True. In this case, the file must NOT be deleted. # If the file IS being changed, the comparison returns False. # In this case, the old file MUST be deleted. if (old_file.name == getattr(instance, filefield_name)) is False: DatabaseFileStorage().delete(old_file.name)
class GalleryEntry(models.Model): title = models.CharField(max_length=255) title_slug = models.CharField(max_length=255, null=True) section = models.ForeignKey(GallerySection, on_delete=models.DO_NOTHING, related_name='entries') content = models.TextField(help_text="markdown-formatted text") image = models.ImageField( # this looks wonky, but it seems like it's the way it's supposed to be. Each of these slash delimited fields # specifies the name of the field in CMSPicture which stores that information. Uploading 'whatever.jpg' yields # the file name 'capweb.CMSPicture/bytes/filename/mimetype/whatever.jpg'... the fields are not replaced with # their values upload_to='capweb.CMSPicture/bytes/filename/mimetype', storage=DatabaseFileStorage(), blank=True, null=True) page_link = models.CharField(max_length=255, blank=True, null=True) repo_link = models.CharField(max_length=255, blank=True, null=True) order = models.IntegerField(default=10) featured = models.BooleanField(default=True, null=False) def save(self, *args, generate_slug=True, **kwargs): if not self.title_slug or generate_slug: self.title_slug = slugify(self.title) return super().save(*args, **kwargs) else: return super().save(*args, **kwargs) def __str__(self): return self.title
def delete_file(instance, filefield_name): """Delete the file (if any) from the database. Call this function immediately AFTER deleting the instance. """ file_instance = getattr(instance, filefield_name) if file_instance: DatabaseFileStorage().delete(file_instance.name)
# django from wsgiref.util import FileWrapper from django.http import HttpResponse, HttpResponseBadRequest from django.utils.translation import ugettext as _ # project from db_file_storage.storage import DatabaseFileStorage storage = DatabaseFileStorage() def get_file(request, add_attachment_headers): name = request.GET.get('name') try: _file = storage.open(name) except Exception: return HttpResponseBadRequest(_('Invalid request')) response = HttpResponse(FileWrapper(_file), content_type=_file.mimetype) if add_attachment_headers: response['Content-Disposition'] = \ 'attachment; filename=%(name)s' % {'name': _file.filename} return response
def _get_unique_filename(self, model_cls, filename_field, filename): return DatabaseFileStorage._get_unique_filename(self, model_cls, filename_field, normpath(filename))
def _get_storage_attributes(self, name): return DatabaseFileStorage._get_storage_attributes(self, normpath(name))
def database_storage(): """Returns storage backend used by `FileProxy.file` to store files in the database.""" return DatabaseFileStorage()
class Migration(migrations.Migration): initial = True dependencies = [] operations = [ migrations.CreateModel( name='CMSPicture', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('bytes', models.TextField()), ('filename', models.CharField(max_length=255)), ('mimetype', models.CharField(max_length=50)), ], ), migrations.CreateModel( name='GallerySection', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=255)), ('order', models.IntegerField(default=10)), ], ), migrations.CreateModel( name='GalleryEntry', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('section', models.ForeignKey( on_delete=django.db.models.deletion.DO_NOTHING, related_name='entries', to='capweb.GallerySection')), ('title', models.CharField(max_length=255)), ('content', models.TextField()), ('page_link', models.CharField(blank=True, max_length=255, null=True)), ('repo_link', models.CharField(blank=True, max_length=255, null=True)), ('order', models.IntegerField(default=10)), ('image', models.ImageField( blank=True, null=True, storage=DatabaseFileStorage(), upload_to='capweb.CMSPicture/bytes/filename/mimetype')), ], ), ]