Я новичок в веб-разработке и работаю над базовым приложением для создания галереи изображений (учебное упражнение) с использованием Django.Я настроил его так, чтобы я мог загрузить zip-архив с изображениями сразу, чтобы создать новый альбом.Кажется, все это работает нормально, но я получаю ошибку HTTP 504, когда загружаемый файл особенно велик.
Я получаю (пожалуйста, исправьте меня, если я ошибаюсь), эта ошибка означает, что мое приложение слишком медленно для возвратаHTTP-ответ.Я предполагаю, что это потому, что требуется много времени, чтобы распаковать и обработать (создать объект Pic в БД и создать миниатюры) всех изображений.
Есть ли способ вернуть ответ (скажем, некоторому промежуточномустраница), пока еще выполняем обработку в фоновом режиме - возможно, с использованием потоков?Как правильно справиться с этим?Не пора ли мне начать изучать Javascript / AJAX?
Спасибо!
Модели:
from django.db import models
from blog.models import Post
class Album(models.Model):
title = models.CharField(max_length=128)
slug = models.SlugField()
description = models.TextField()
parent = models.ForeignKey('self', null=True, blank=True)
pub = models.BooleanField()
date_created = models.DateTimeField(auto_now_add=True)
date_published = models.DateTimeField(null=True, blank=True)
date_modified = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.title
class Pic(models.Model):
image = models.ImageField(upload_to='pics/%Y/%m')
title = models.CharField(max_length=128)
caption = models.TextField(blank=True, null=True)
albums = models.ManyToManyField('Album', null=True, blank=True)
posts = models.ManyToManyField(Post, blank=True, null=True)
date_taken = models.DateTimeField(null=True, blank=True)
date_uploaded = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.title
Просмотр:
Я делаю это вручную, потому что я не впал в администрацию Django, когда начал.Я думаю, что было бы лучше использовать настройку администратора здесь.
def new_album(request):
if request.method == "POST":
form = AlbumForm(request.POST, request.FILES)
if form.is_valid():
from gallery.pic_handlers import handle_uploaded_album
pics = handle_uploaded_album(request.FILES['pic_archive'])
a = form.save()
a.slug = slugify(a.title)
a.save()
for pic in pics:
pic.albums.add(a)
return HttpResponseRedirect('/gallery/album/%s/' % a.slug)
else:
form = AlbumForm()
return render_to_response('new_album.html', {
'form' : form,
}, context_instance = RequestContext(request))
Дополнительная обработка:
def handle_uploaded_album(pic_archive):
destination = open(join(settings.MEDIA_ROOT,pic_archive.name), 'wb+')
for chunk in pic_archive.chunks():
destination.write(chunk)
destination.close()
today = datetime.date.today()
save_path = 'pics/{0}/{1:02}/'.format(today.year, today.month)
tmp_path = 'tmp/'
z = zipfile.ZipFile(join(settings.MEDIA_ROOT,pic_archive.name), 'r')
pics = []
for member in z.namelist():
if '/' in member or '\\' in member:
# don't deal with any directories inside the zip
# this also solves the '__MACOSX' issue
continue
if splitext(member)[1] in IMG_EXT:
z.extract(member,join(settings.MEDIA_ROOT,tmp_path))
im = File(open(join(settings.MEDIA_ROOT,tmp_path,member), 'rb'))
# create a Pic from this file
pic = Pic()
pic.title = member
pic.image.save(
join(save_path, member),
im,
True)
create_thumbnails(pic)
im.close()
# remove extracted images
remove(join(settings.MEDIA_ROOT,tmp_path,member))
# TODO: save date taken if available
pics.append(pic)
z.close()
remove(join(settings.MEDIA_ROOT,pic_archive.name))
return pics
def create_thumbnails(pic):
fname, ext = splitext(pic.image.path)
img = Image.open(pic.image.path)
img.thumbnail((512,512), Image.ANTIALIAS)
img.save(fname + '_m' + ext)
img.thumbnail((128,128), Image.ANTIALIAS)
img.save(fname + '_s' + ext)