Added Attachment model
This commit is contained in:
parent
11e5412de6
commit
acb4e22739
|
@ -1,5 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from .models import Entry, Tag
|
||||
from .models import Entry, Tag, Attachment
|
||||
from ckeditor.widgets import CKEditorWidget
|
||||
from django.utils.translation import ugettext as _
|
||||
from reversion.admin import VersionAdmin
|
||||
|
@ -15,6 +15,7 @@ class EntryAdminForm(forms.ModelForm):
|
|||
model = Entry
|
||||
fields = ('title', 'slug', 'draft', 'date', 'tags', 'content')
|
||||
|
||||
|
||||
#
|
||||
# ENTRY
|
||||
#
|
||||
|
@ -80,3 +81,12 @@ class TagAdmin(VersionAdmin):
|
|||
pass
|
||||
|
||||
admin.site.register(Tag, TagAdmin)
|
||||
|
||||
|
||||
#
|
||||
# ATTACHMENT
|
||||
#
|
||||
class AttachmentAdmin(VersionAdmin):
|
||||
pass
|
||||
|
||||
admin.site.register(Attachment, AttachmentAdmin)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-03-21 19:29
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import fmartingrcom.apps.blog.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0002_auto_20160313_1051'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Attachment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('filename', models.CharField(max_length=256)),
|
||||
('sha1', models.CharField(max_length=40)),
|
||||
('mimetype', models.CharField(blank=True, max_length=256, null=True)),
|
||||
('file', models.FileField(upload_to=fmartingrcom.apps.blog.models.attachment_upload_to)),
|
||||
('creation_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modification_date', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Attachment',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,12 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.core.files import File
|
||||
from django.utils.timezone import utc
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.dispatch.dispatcher import receiver
|
||||
from django.db.models.signals import pre_delete
|
||||
|
||||
from fmartingrcom.utils import sha1_checksum
|
||||
|
||||
import mistune
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
#
|
||||
# ENTRY
|
||||
|
@ -76,3 +90,106 @@ class Tag(models.Model):
|
|||
class Meta:
|
||||
app_label = 'blog'
|
||||
ordering = ['name']
|
||||
|
||||
|
||||
#
|
||||
# ATTACHMENT
|
||||
#
|
||||
def attachment_upload_to(instance, filename):
|
||||
return os.path.join('{}_.{}'.format(
|
||||
instance.media_path, instance.extension
|
||||
))
|
||||
|
||||
|
||||
class Attachment(models.Model):
|
||||
filename = models.CharField(max_length=256)
|
||||
sha1 = models.CharField(max_length=40)
|
||||
mimetype = models.CharField(max_length=256, blank=True, null=True)
|
||||
file = models.FileField(upload_to=attachment_upload_to)
|
||||
|
||||
creation_date = models.DateTimeField(auto_now_add=True)
|
||||
modification_date = models.DateTimeField(auto_now=True)
|
||||
|
||||
@property
|
||||
def extension(self):
|
||||
return self.file.url.split('.')[-1]
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return self.file.url
|
||||
|
||||
@property
|
||||
def media_path(self):
|
||||
p1 = self.sha1[0:2]
|
||||
p2 = self.sha1[2:4]
|
||||
return 'attachment/{}/{}/{}/'.format(p1, p2, self.sha1)
|
||||
|
||||
@staticmethod
|
||||
def upload_file(handler, filename=None):
|
||||
"""
|
||||
Given a certain file handler returns an `Image` objects
|
||||
handler can be:
|
||||
+ django.core.files.File instance __or subclass of__ (UploadedFile)
|
||||
+ string with an absolute path to an image
|
||||
"""
|
||||
FLAGS = 'rw+'
|
||||
|
||||
# File Path
|
||||
if isinstance(handler, str):
|
||||
f = File(open(handler, FLAGS))
|
||||
elif issubclass(handler.__class__, File) or isinstance(handler, File):
|
||||
# Re-read with correct flags
|
||||
f = handler
|
||||
f.mode = FLAGS
|
||||
else:
|
||||
# I give up!
|
||||
f = handler
|
||||
|
||||
if not filename:
|
||||
filename = f.name.split('/')[-1]
|
||||
|
||||
sha1 = sha1_checksum(f)
|
||||
|
||||
# Check if file exists
|
||||
try:
|
||||
obj = Attachment.objects.get(sha1=sha1)
|
||||
except Attachment.DoesNotExist:
|
||||
obj = Attachment()
|
||||
obj.file = f
|
||||
obj.sha1 = sha1
|
||||
obj.filename = filename
|
||||
obj.mimetype = Attachment.get_mimetype(f, obj.filename)
|
||||
obj.save()
|
||||
|
||||
return obj
|
||||
|
||||
@staticmethod
|
||||
def get_mimetype(handler, filename):
|
||||
re_mime_validate = re.compile('\w+/\w+(; \w+=[^;]+)*')
|
||||
|
||||
# subprocess
|
||||
p = subprocess.Popen(('file', '--brief', '--mime-type', '-'),
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate(handler.read())
|
||||
if re_mime_validate.match(stdout):
|
||||
mimetype = stdout.split()[0]
|
||||
else:
|
||||
# by python
|
||||
mime, encoding = mimetypes.guess_type(filename)
|
||||
mimetype = mime if mime else None
|
||||
|
||||
# rewind file descriptor
|
||||
handler.file.seek(0)
|
||||
|
||||
return mimetype
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Attachment'
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=Attachment)
|
||||
def clean_files_on_delete(sender, instance, **kwargs):
|
||||
try:
|
||||
shutil.rmtree('/'.join(instance.file.path.split('/')[:-1]))
|
||||
except Exception as error:
|
||||
logger.warning(error, exc_info=True)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import hashlib
|
||||
|
||||
|
||||
def sha1_checksum(handler):
|
||||
f = open(handler.file.name, 'rb')
|
||||
checksum = hashlib.sha1(f.read())
|
||||
return checksum.hexdigest()
|
Loading…
Reference in New Issue