Unverified Commit 042c2400 authored by Joost Rijneveld's avatar Joost Rijneveld
Browse files

Refactor to store Photo in a database model

parent 0422f974
from django.contrib import admin
from django import forms
from django.conf import settings
from django.core.files.base import ContentFile
from .models import Album
from .models import Album, Photo
import os
import shutil
from zipfile import ZipFile
class AlbumForm(forms.ModelForm):
album_archive = forms.FileField()
album_archive = forms.FileField(
required=False,
help_text="Uploading a zip file adds all contained images as photos.",
)
class Meta:
exclude = ['dirname']
......@@ -23,8 +26,10 @@ class AlbumAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.save()
archive = form.cleaned_data.get('album_archive', None)
path = os.path.join(settings.MEDIA_ROOT, 'photos', obj.dirname)
if archive is None:
return
with ZipFile(archive) as zip_file:
path = os.path.join(settings.MEDIA_ROOT, 'photos', obj.dirname)
os.makedirs(path, exist_ok=True)
# Notably, this can also be used to add photos to existing albums
for photo in zip_file.namelist():
......@@ -36,9 +41,11 @@ class AlbumAdmin(admin.ModelAdmin):
if not photo_filename:
continue
# Cannot use .extract as that would recreate directory paths
source = zip_file.open(photo)
target = open(os.path.join(path, photo_filename), "wb")
with source, target:
shutil.copyfileobj(source, target)
photo_obj = Photo()
photo_obj.album = obj
with zip_file.open(photo) as f:
photo_obj.file.save(photo_filename, ContentFile(f.read()))
photo_obj.save()
admin.site.register(Album, AlbumAdmin)
admin.site.register(Photo)
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-09 15:55
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import photos.models
class Migration(migrations.Migration):
dependencies = [
('photos', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Photo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.ImageField(upload_to=photos.models.photo_uploadto)),
('rotation', models.IntegerField(default=0)),
('album', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='photos.Album')),
],
),
migrations.AddField(
model_name='album',
name='_cover',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='covered_album', to='photos.Photo'),
),
]
......@@ -9,32 +9,38 @@ import random
COVER_FILENAME = 'cover.jpg'
def photo_uploadto(instance, filename):
return os.path.join(Album.photosdir, instance.album.dirname, filename)
class Photo(models.Model):
album = models.ForeignKey('Album', on_delete=models.CASCADE)
file = models.ImageField(upload_to=photo_uploadto)
rotation = models.IntegerField(default=0)
def __str__(self):
return self.file.name
class Album(models.Model):
title = models.CharField(max_length=200)
dirname = models.CharField(max_length=200)
date = models.DateField()
slug = models.SlugField()
_cover = models.OneToOneField(Photo, on_delete=models.SET_NULL, blank=True,
null=True, related_name='covered_album')
photosdir = 'photos'
photospath = os.path.join(settings.MEDIA_ROOT, photosdir)
@property
def path(self):
return os.path.join(Album.photospath, self.dirname)
@cached_property
def cover(self):
if os.path.isfile(os.path.join(self.path, COVER_FILENAME)):
cover = COVER_FILENAME
if self._cover is not None:
return self._cover
else:
random.seed(self.dirname)
cover = random.choice(os.listdir(self.path))
return os.path.join(Album.photosdir, self.dirname, cover)
@cached_property
def photos(self):
return [os.path.join(Album.photosdir, self.dirname, photo)
for photo in os.listdir(self.path) if photo != COVER_FILENAME]
cover = random.choice(self.photo_set.all())
return cover
def __str__(self):
return '{} {}'.format(self.date.strftime('%Y-%m-%d'), self.title)
......
......@@ -8,12 +8,12 @@
<h2>{{ album.date|date:"d-m-Y" }}</h2>
<div class="gallery">
<ul class="gallery-photos row">
{% for photo in album.photos %}
{% for photo in album.photo_set.all %}
<li class="post gallery-photo span3 has-overlay {% if forloop.counter0|divisibleby:4 %}first-child{% endif %}">
<a class="gallery-box" rel="gallery" data-download="{% url 'photos:download' photo %}" href="{% thumbnail photo '1024x768' fit=False %}">
<a class="gallery-box" rel="gallery" data-download="{% url 'photos:download' photo.file %}" href="{% thumbnail photo.file '1024x768' fit=False %}">
<span class="post-inner">
<span class="inner-img">
<img src="{% thumbnail photo '220x220' %}" alt="" />
<img src="{% thumbnail photo.file '220x220' %}" alt="" />
</span>
<span class="post-overlay">
</span>
......
......@@ -13,7 +13,7 @@
<a href="{% url 'photos:album' album.slug %}">
<span class="post-inner">
<span class="inner-img">
<img src="{% thumbnail album.cover '220x220' %}" alt="" />
<img src="{% thumbnail album.cover.file '220x220' %}" alt="" />
</span>
<span class="post-overlay">
<span class="post-overlay-meta">
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment