diff options
Diffstat (limited to 'app/photos')
45 files changed, 0 insertions, 2785 deletions
diff --git a/app/photos/__init__.py b/app/photos/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/app/photos/__init__.py +++ /dev/null diff --git a/app/photos/admin.py b/app/photos/admin.py deleted file mode 100644 index e77e50b..0000000 --- a/app/photos/admin.py +++ /dev/null @@ -1,184 +0,0 @@ -from django.contrib import admin -from django import forms -from django.contrib.gis.admin import OSMGeoAdmin -from django.conf.urls import url -from django.utils.translation import ungettext, ugettext_lazy as _ -from photos.models import Photo, PhotoGallery, LuxImage, LuxGallery, LuxImageSize, LuxVideo -from django.shortcuts import render -from django.contrib.admin import helpers -from django.http import HttpResponseRedirect - - -from .forms import UploadZipForm, GalleryForm - - -class LuxImageSizeAdmin(OSMGeoAdmin): - list_display = ('name', 'width', 'height', 'quality') - pass - - -admin.site.register(LuxImageSize, LuxImageSizeAdmin) - - -@admin.register(LuxVideo) -class LuxVideoAdmin(OSMGeoAdmin): - pass - - -class LuxImageAdmin(OSMGeoAdmin): - list_display = ('pk', 'admin_thumbnail', 'pub_date', 'caption', 'location') - list_filter = ('pub_date', 'location') - search_fields = ['title', 'caption', 'alt'] - list_editable = ('location',) - # Options for OSM map Using custom ESRI topo map - default_lon = -9285175 - default_lat = 4025046 - default_zoom = 6 - units = True - scrollable = False - map_width = 700 - map_height = 425 - map_template = 'gis/admin/osm.html' - openlayers_url = '/static/admin/js/OpenLayers.js' - - fieldsets = ( - (None, { - 'fields': ('title', ('image'), 'pub_date', 'sizes', 'alt', 'caption', 'point', ('is_public'), ('photo_credit_source', 'photo_credit_url')) - }), - ('Exif Data', { - 'classes': ('collapse',), - 'fields': ('exif_raw', 'exif_aperture', 'exif_make', 'exif_model', 'exif_exposure', 'exif_iso', 'exif_focal_length', 'exif_lens', 'exif_date', 'height', 'width'), - }), - ) - - class Media: - js = ('image-preview.js', 'next-prev-links.js') - - -admin.site.register(LuxImage, LuxImageAdmin) - - -class LuxGalleryAdmin(OSMGeoAdmin): - form = GalleryForm - list_display = ('title', 'location', 'pub_date') - list_filter = ('location',) - - # Options for OSM map Using custom ESRI topo map - default_lon = -9285175 - default_lat = 4025046 - default_zoom = 6 - units = True - scrollable = False - map_width = 700 - map_height = 425 - map_template = 'gis/admin/osm.html' - openlayers_url = '/static/admin/js/OpenLayers.js' - - def get_urls(self): - urls = super(LuxGalleryAdmin, self).get_urls() - custom_urls = [ - url( - r'upload_zip/$', - self.admin_site.admin_view(self.upload_zip), - name='upload_zip' - ) - ] - return custom_urls + urls - - def upload_zip(self, request): - context = { - 'title': _('Upload a zip archive of photos'), - 'app_label': self.model._meta.app_label, - 'opts': self.model._meta, - 'has_change_permission': self.has_change_permission(request) - } - - # Handle form request - if request.method == 'POST': - form = UploadZipForm(request.POST, request.FILES) - if form.is_valid(): - form.save(request=request) - return HttpResponseRedirect('..') - else: - form = UploadZipForm() - context['form'] = form - context['adminform'] = helpers.AdminForm(form, - list([(None, {'fields': form.base_fields})]), - {}) - return render(request, 'admin/upload_zip.html', context) - -admin.site.register(LuxGallery, LuxGalleryAdmin) - - -class PhotoAdmin(OSMGeoAdmin): - list_display = ('title', 'admin_thumbnail', 'flickr_id', 'pub_date',) - list_filter = ('pub_date',) - search_fields = ['title', 'description'] - fieldsets = ( - (None, { - 'fields': ( - ('title', 'description'), - 'pub_date', - ('lat', 'lon') - ) - }), - ('Exif Data', { - 'fields': ( - 'exif_aperture', - 'exif_exposure', - 'exif_iso', - 'exif_focal_length', - 'exif_lens', - 'exif_date', - 'exif_make', - 'exif_model' - ), - 'classes': ('collapse') - }), - ('Flickr Data', { - 'fields': ( - 'flickr_id', - 'flickr_owner', - 'flickr_farm', - 'flickr_server', - 'flickr_secret', - 'flickr_originalsecret' - ), - 'classes': ('collapse') - }), - ) - - # Options for OSM map Using custom ESRI topo map - default_lon = -9285175 - default_lat = 4025046 - default_zoom = 6 - units = True - scrollable = False - map_width = 700 - map_height = 425 - map_template = 'gis/admin/osm.html' - openlayers_url = '/static/admin/js/OpenLayers.js' - - -admin.site.register(Photo, PhotoAdmin) - - -class PhotoGalleryAdmin(OSMGeoAdmin): - list_display = ('set_title', 'region', 'location', 'pub_date') - list_filter = ('region', 'location') - fieldsets = ( - (None, { - 'fields': ( - ('set_id', 'set_title', 'set_desc'), - 'set_slug', - 'primary', - 'location', - 'region', - 'photos', - 'pub_date' - ) - }), - ) - - -admin.site.register(PhotoGallery, PhotoGalleryAdmin) diff --git a/app/photos/build.py b/app/photos/build.py deleted file mode 100644 index e95cbfc..0000000 --- a/app/photos/build.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -from django.urls import reverse -from builder.base import BuildNew - -from .models import LuxImage - - -class BuildLuxPhotos(BuildNew): - - def build(self): - self.build_detail_view() - self.build_daily_photo() - - def get_model_queryset(self): - return self.model.objects.all() - - def build_daily_photo(self): - ''' - build out images that I post daily, found by title prefix daily_ - ''' - self.build_list_view( - base_path=reverse("photos:daily_photo_list"), - qs=LuxImage.objects.filter(is_public=True, title__startswith="daily_"), - paginate_by=10 - ) - - def build_detail_view(self): - ''' - write out all the expenses for each trip - ''' - for obj in self.get_model_queryset(): - url = obj.get_absolute_url() - path, slug = os.path.split(url) - path = '%s/' % path - # write html - response = self.client.get(url) - print(path, slug) - self.write_file(path, response.content, filename=slug) - - -def dailybuilder(): - j = BuildLuxPhotos("photos", "LuxImage") - j.build_daily_photo() - - -def builder(): - j = BuildLuxPhotos("photos", "LuxGallery") - j.build() diff --git a/app/photos/detail_urls.py b/app/photos/detail_urls.py deleted file mode 100644 index 0ab94f6..0000000 --- a/app/photos/detail_urls.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.conf.urls import url -from django.views.generic.detail import DetailView -from photos.models import Photo - -urlpatterns = [ - url( - r'^(?P<object_id>\d+)/$', - DetailView.as_view(model=Photo, template_name='details/photo.html') - ), -] diff --git a/app/photos/flickrauth b/app/photos/flickrauth deleted file mode 100644 index 0fe7407..0000000 --- a/app/photos/flickrauth +++ /dev/null @@ -1,2 +0,0 @@ -72157629224829547-04c4f099c2550cd8 -812f6c53e5b122f4
\ No newline at end of file diff --git a/app/photos/forms.py b/app/photos/forms.py deleted file mode 100644 index 6ee7bde..0000000 --- a/app/photos/forms.py +++ /dev/null @@ -1,179 +0,0 @@ -import zipfile -from zipfile import BadZipFile -import logging -import datetime -import os -from io import BytesIO -try: - import Image -except ImportError: - from PIL import Image - -from django import forms -from django.utils.translation import ugettext_lazy as _ -from django.utils.safestring import mark_safe -from django.contrib import messages -from django.core.files.base import ContentFile -from django.contrib.admin import widgets -from django.conf import settings - -from photos.models import LuxImage, LuxGallery, LuxImageSize - -from .utils import resize_image -from .readexif import readexif - -logger = logging.getLogger('photos.forms') - - -class GalleryForm(forms.ModelForm): - class Meta: - fields = '__all__' - widgets = { - 'images': forms.SelectMultiple, - } - - def __init__(self, *args, **kwargs): - super(GalleryForm, self).__init__(*args, **kwargs) - self.fields['images'].choices = [(image.id, mark_safe('%sqq%sqq%s' % (image.title, image.get_image_by_size('tn'), image.pk))) for image in LuxImage.objects.all()[:40]] - self.fields['images'].allow_tags = True - - -from django.utils.safestring import mark_safe - -class ImageChoiceField(forms.ModelMultipleChoiceField): - - def label_from_instance(self, obj): - - return mark_safe('%sqq%sqq%s' % (obj.title, obj.get_image_by_size('tn'), obj.pk)) - - - -class FKGalleryForm(forms.ModelForm): - class Meta: - fields = '__all__' - widgets = { - 'image': ImageChoiceField(queryset=LuxImage.objects.all()), - } - - def __init__(self, *args, **kwargs): - super(FKGalleryForm, self).__init__(*args, **kwargs) - self.fields['image'].choices = [(o.id, str(o.image.url)) for o in LuxImage.objects.all()] - self.fields['image'].allow_tags = True - -class UploadZipForm(forms.Form): - """ - Handles the uploading of a gallery of photos packed in a .zip file - Creates Gallery object, adds photos with all metadata that's available - """ - zip_file = forms.FileField() - title = forms.CharField(label=_('Gallery Title'), max_length=250) - slug = forms.SlugField(label=_('Gallery Slug')) - desc = forms.CharField(label=_('Gallery Caption'), widget=forms.Textarea, required=False) - date = forms.SplitDateTimeField(label=_('Date'), widget=widgets.AdminSplitDateTime) - is_public = forms.BooleanField(label=_('Is public'), initial=True, required=False, help_text=_('Show on site')) - - def clean_zip_file(self): - """Open the zip file a first time, to check that it is a valid zip archive. - We'll open it again in a moment, so we have some duplication, but let's focus - on keeping the code easier to read! - """ - zip_file = self.cleaned_data['zip_file'] - try: - zip = zipfile.ZipFile(zip_file) - except BadZipFile as e: - raise forms.ValidationError(str(e)) - bad_file = zip.testzip() - if bad_file: - zip.close() - raise forms.ValidationError('"%s" in the .zip archive is corrupt.' % bad_file) - zip.close() # Close file in all cases. - return zip_file - - def clean_title(self): - title = self.cleaned_data['title'] - if title and LuxGallery.objects.filter(title=title).exists(): - raise forms.ValidationError(_('A gallery with that title already exists.')) - return title - - def clean(self): - cleaned_data = super(UploadZipForm, self).clean() - if not self['title'].errors: - # If there's already an error in the title, no need to add another - # error related to the same field. - if not cleaned_data.get('title', None) and not cleaned_data['gallery']: - raise forms.ValidationError( - _('Select an existing gallery, or enter a title for a new gallery.')) - return cleaned_data - - def save(self, request=None, zip_file=None): - if not zip_file: - zip_file = self.cleaned_data['zip_file'] - - gallery, created = LuxGallery.objects.get_or_create( - title=self.cleaned_data['title'], - description=self.cleaned_data['desc'], - slug=self.cleaned_data['slug'], - pub_date=self.cleaned_data['date'], - is_public=self.cleaned_data['is_public'] - ) - zipper = zipfile.ZipFile(zip_file) - count = 1 - for filename in sorted(zipper.namelist()): - f, file_extension = os.path.splitext(filename) - logger.debug('Reading file "{0}".'.format(filename)) - if filename.startswith('__') or filename.startswith('.'): - logger.debug('Ignoring file "{0}".'.format(filename)) - continue - if os.path.dirname(filename): - logger.warning('Ignoring file "{0}" as it is in a subfolder; all images should be in the top ' - 'folder of the zip.'.format(filename)) - if request: - messages.warning(request, - _('Ignoring file "{filename}" as it is in a subfolder').format(filename=filename), fail_silently=True) - continue - data = zipper.read(filename) - - if not len(data): - logger.debug('File "{0}" is empty.'.format(filename)) - continue - - fn, file_extension = os.path.splitext(filename) - if file_extension != ".mp4": - # Basic check that we have a valid image. - try: - file = BytesIO(data) - opened = Image.open(file) - opened.verify() - except Exception: - # Pillow (or PIL) doesn't recognize it as an image. - # If a "bad" file is found we just skip it. - # But we do flag this both in the logs and to the user. - logger.error('Could not process file "{0}" in the .zip archive.'.format(filename)) - if request: - messages.warning(request, - _('Could not process file "{0}" in the .zip archive.').format( - filename), - fail_silently=True) - continue - image = LuxImage( - pub_date=datetime.datetime.now() - ) - contentfile = ContentFile(data) - image.image.save(filename, contentfile) - if file_extension != ".mp4": - img = Image.open(image.image.path) - if img.size[0] > img.size[1]: - image.sizes.add(LuxImageSize.objects.get(width=2560)) - image.sizes.add(LuxImageSize.objects.get(width=1170)) - image.sizes.add(LuxImageSize.objects.get(width=720)) - if img.size[1] > img.size[0]: - image.sizes.add(LuxImageSize.objects.get(height=1600)) - image.sizes.add(LuxImageSize.objects.get(height=800)) - image.sizes.add(LuxImageSize.objects.get(height=460)) - image.save() - gallery.images.add(image) - - zipper.close() - - if request: - messages.success(request, _('The photos have been uploaded')) diff --git a/app/photos/migrations/0001_initial.py b/app/photos/migrations/0001_initial.py deleted file mode 100644 index 711af1d..0000000 --- a/app/photos/migrations/0001_initial.py +++ /dev/null @@ -1,137 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2015-12-11 19:33 -from __future__ import unicode_literals - -import django.contrib.gis.db.models.fields -from django.db import migrations, models -import django.db.models.deletion -import photos.models -import taggit.managers - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('taggit', '0002_auto_20150616_2121'), - #('locations', '__first__'), - ] - - operations = [ - migrations.CreateModel( - name='LuxGallery', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(blank=True, max_length=300)), - ('description', models.TextField(blank=True, null=True)), - ('slug', models.CharField(blank=True, max_length=300)), - ('thumb', models.CharField(blank=True, max_length=300)), - ('pub_date', models.DateTimeField(null=True)), - ('point', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)), - ('is_public', models.BooleanField(default=True)), - ], - options={ - 'verbose_name_plural': 'Galleries', - 'get_latest_by': 'pub_date', - 'ordering': ('-pub_date', 'id'), - }, - ), - migrations.CreateModel( - name='LuxImage', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('image', models.FileField(blank=True, null=True, upload_to=photos.models.get_upload_path)), - ('title', models.CharField(blank=True, max_length=300, null=True)), - ('caption', models.TextField(blank=True, null=True)), - ('pub_date', models.DateTimeField()), - ('exif_raw', models.TextField(blank=True, null=True)), - ('exif_aperture', models.CharField(blank=True, max_length=50, null=True)), - ('exif_make', models.CharField(blank=True, max_length=50, null=True)), - ('exif_model', models.CharField(blank=True, max_length=50, null=True)), - ('exif_exposure', models.CharField(blank=True, max_length=50, null=True)), - ('exif_iso', models.CharField(blank=True, max_length=50, null=True)), - ('exif_focal_length', models.CharField(blank=True, max_length=50, null=True)), - ('exif_lens', models.CharField(blank=True, max_length=50, null=True)), - ('exif_date', models.DateTimeField(blank=True, null=True)), - ('height', models.CharField(blank=True, max_length=6, null=True)), - ('width', models.CharField(blank=True, max_length=6, null=True)), - ('point', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)), - ('is_public', models.BooleanField(default=True)), - ('is_video', models.BooleanField(default=False)), - ('flickr_id', models.CharField(blank=True, max_length=80, null=True)), - ('location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location')), - ], - options={ - 'verbose_name_plural': 'Images', - 'get_latest_by': 'pub_date', - 'ordering': ('-pub_date', 'id'), - }, - ), - migrations.CreateModel( - name='Photo', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.TextField(blank=True, null=True)), - ('title', models.CharField(blank=True, max_length=300)), - ('pub_date', models.DateTimeField()), - ('exif_aperture', models.CharField(blank=True, max_length=50, null=True)), - ('exif_make', models.CharField(blank=True, max_length=50, null=True)), - ('exif_model', models.CharField(blank=True, max_length=50, null=True)), - ('exif_exposure', models.CharField(blank=True, max_length=50, null=True)), - ('exif_iso', models.CharField(blank=True, max_length=50, null=True)), - ('exif_focal_length', models.CharField(blank=True, max_length=50, null=True)), - ('exif_lens', models.CharField(blank=True, max_length=50, null=True)), - ('exif_date', models.DateTimeField()), - ('flickr_id', models.CharField(max_length=300)), - ('flickr_owner', models.CharField(max_length=20)), - ('flickr_server', models.IntegerField()), - ('flickr_farm', models.IntegerField()), - ('flickr_secret', models.CharField(max_length=50)), - ('flickr_originalsecret', models.CharField(max_length=50)), - ('lon', models.FloatField(help_text='Longitude of centerpoint', null=True, verbose_name='Longitude')), - ('lat', models.FloatField(help_text='Latitude of centerpoint', null=True, verbose_name='Latitude')), - ('slideshowimage_width', models.CharField(blank=True, max_length=4, null=True)), - ('slideshowimage_height', models.CharField(blank=True, max_length=4, null=True)), - ('slideshowimage_margintop', models.CharField(blank=True, max_length=4, null=True)), - ('slideshowimage_marginleft', models.CharField(blank=True, max_length=4, null=True)), - ('is_public', models.BooleanField(default=True)), - ('location', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location')), - ('region', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Region')), - ('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), - ], - options={ - 'ordering': ('-pub_date',), - }, - ), - migrations.CreateModel( - name='PhotoGallery', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('set_id', models.CharField(blank=True, max_length=300)), - ('set_title', models.CharField(blank=True, max_length=300)), - ('set_desc', models.TextField(blank=True, null=True)), - ('set_slug', models.CharField(blank=True, max_length=300)), - ('primary', models.CharField(blank=True, max_length=300)), - ('pub_date', models.DateTimeField(null=True)), - ('location', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location')), - ('photos', models.ManyToManyField(to='photos.Photo')), - ('region', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Region')), - ], - options={ - 'verbose_name_plural': 'Photo Galleries', - 'get_latest_by': 'pub_date', - 'ordering': ('-pub_date', 'id'), - }, - ), - migrations.AddField( - model_name='luxgallery', - name='image', - field=models.ManyToManyField(to='photos.LuxImage'), - ), - migrations.AddField( - model_name='luxgallery', - name='location', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location'), - ), - ] diff --git a/app/photos/migrations/0002_auto_20151216_1958.py b/app/photos/migrations/0002_auto_20151216_1958.py deleted file mode 100644 index 2a2bffb..0000000 --- a/app/photos/migrations/0002_auto_20151216_1958.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2015-12-16 19:58 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0001_initial'), - ] - - operations = [ - migrations.RenameField( - model_name='luxgallery', - old_name='image', - new_name='images', - ), - migrations.AlterField( - model_name='luxgallery', - name='thumb', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='gallery_thumb', to='photos.LuxImage'), - ), - ] diff --git a/app/photos/migrations/0003_luxgallery_caption_style.py b/app/photos/migrations/0003_luxgallery_caption_style.py deleted file mode 100644 index b46f970..0000000 --- a/app/photos/migrations/0003_luxgallery_caption_style.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2015-12-17 11:01 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0002_auto_20151216_1958'), - ] - - operations = [ - migrations.AddField( - model_name='luxgallery', - name='caption_style', - field=models.CharField(blank=True, max_length=400, null=True), - ), - ] diff --git a/app/photos/migrations/0004_luximage_alt.py b/app/photos/migrations/0004_luximage_alt.py deleted file mode 100644 index ecbaf56..0000000 --- a/app/photos/migrations/0004_luximage_alt.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-16 22:45 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0003_luxgallery_caption_style'), - ] - - operations = [ - migrations.AddField( - model_name='luximage', - name='alt', - field=models.CharField(blank=True, max_length=300, null=True), - ), - ] diff --git a/app/photos/migrations/0005_auto_20160318_1244.py b/app/photos/migrations/0005_auto_20160318_1244.py deleted file mode 100644 index 584714e..0000000 --- a/app/photos/migrations/0005_auto_20160318_1244.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-18 12:44 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0004_luximage_alt'), - ] - - operations = [ - migrations.AddField( - model_name='luximage', - name='photo_credit_source', - field=models.CharField(blank=True, max_length=300, null=True), - ), - migrations.AddField( - model_name='luximage', - name='photo_credit_url', - field=models.CharField(blank=True, max_length=300, null=True), - ), - ] diff --git a/app/photos/migrations/0006_auto_20160318_2047.py b/app/photos/migrations/0006_auto_20160318_2047.py deleted file mode 100644 index 7cf0a4f..0000000 --- a/app/photos/migrations/0006_auto_20160318_2047.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-18 20:47 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0005_auto_20160318_1244'), - ] - - operations = [ - migrations.CreateModel( - name='LuxImageSize', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('size', models.IntegerField(max_length=5)), - ], - options={ - 'verbose_name_plural': 'Image Sizes', - }, - ), - migrations.AddField( - model_name='luximage', - name='sizes', - field=models.ManyToManyField(to='photos.LuxImageSize'), - ), - ] diff --git a/app/photos/migrations/0007_auto_20160320_0802.py b/app/photos/migrations/0007_auto_20160320_0802.py deleted file mode 100644 index 474bd42..0000000 --- a/app/photos/migrations/0007_auto_20160320_0802.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-20 08:02 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0006_auto_20160318_2047'), - ] - - operations = [ - migrations.AlterField( - model_name='luximagesize', - name='size', - field=models.IntegerField(), - ), - ] diff --git a/app/photos/migrations/0008_luximagesize_quality.py b/app/photos/migrations/0008_luximagesize_quality.py deleted file mode 100644 index 06dc0cc..0000000 --- a/app/photos/migrations/0008_luximagesize_quality.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-20 08:47 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0007_auto_20160320_0802'), - ] - - operations = [ - migrations.AddField( - model_name='luximagesize', - name='quality', - field=models.IntegerField(default=65), - preserve_default=False, - ), - ] diff --git a/app/photos/migrations/0009_auto_20160320_0907.py b/app/photos/migrations/0009_auto_20160320_0907.py deleted file mode 100644 index ccfebf5..0000000 --- a/app/photos/migrations/0009_auto_20160320_0907.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-03-20 09:07 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0008_luximagesize_quality'), - ] - - operations = [ - migrations.RenameField( - model_name='luximagesize', - old_name='size', - new_name='width', - ), - ] diff --git a/app/photos/migrations/0010_auto_20160517_0906.py b/app/photos/migrations/0010_auto_20160517_0906.py deleted file mode 100644 index 0adf4ff..0000000 --- a/app/photos/migrations/0010_auto_20160517_0906.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-05-17 09:06 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0009_auto_20160320_0907'), - ] - - operations = [ - migrations.AddField( - model_name='luximage', - name='facebook_link', - field=models.CharField(blank=True, max_length=300, null=True), - ), - migrations.AddField( - model_name='luximage', - name='twitter_link', - field=models.CharField(blank=True, max_length=300, null=True), - ), - migrations.AlterField( - model_name='luximage', - name='sizes', - field=models.ManyToManyField(blank=True, to='photos.LuxImageSize'), - ), - ] diff --git a/app/photos/migrations/0011_luximagesize_name.py b/app/photos/migrations/0011_luximagesize_name.py deleted file mode 100644 index 49d046b..0000000 --- a/app/photos/migrations/0011_luximagesize_name.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-21 08:46 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0010_auto_20160517_0906'), - ] - - operations = [ - migrations.AddField( - model_name='luximagesize', - name='name', - field=models.CharField(blank=True, max_length=30, null=True), - ), - ] diff --git a/app/photos/migrations/0012_luximagesize_is_portrait.py b/app/photos/migrations/0012_luximagesize_is_portrait.py deleted file mode 100644 index a2c2e3a..0000000 --- a/app/photos/migrations/0012_luximagesize_is_portrait.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-22 13:46 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0011_luximagesize_name'), - ] - - operations = [ - migrations.AddField( - model_name='luximagesize', - name='is_portrait', - field=models.BooleanField(default=False), - ), - ] diff --git a/app/photos/migrations/0013_auto_20161022_1348.py b/app/photos/migrations/0013_auto_20161022_1348.py deleted file mode 100644 index 8dfbf98..0000000 --- a/app/photos/migrations/0013_auto_20161022_1348.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-22 13:48 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0012_luximagesize_is_portrait'), - ] - - operations = [ - migrations.RenameField( - model_name='luximagesize', - old_name='width', - new_name='long_edge', - ), - ] diff --git a/app/photos/migrations/0014_remove_luximagesize_is_portrait.py b/app/photos/migrations/0014_remove_luximagesize_is_portrait.py deleted file mode 100644 index b8e0aa8..0000000 --- a/app/photos/migrations/0014_remove_luximagesize_is_portrait.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-22 14:11 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0013_auto_20161022_1348'), - ] - - operations = [ - migrations.RemoveField( - model_name='luximagesize', - name='is_portrait', - ), - ] diff --git a/app/photos/migrations/0015_auto_20161022_1411.py b/app/photos/migrations/0015_auto_20161022_1411.py deleted file mode 100644 index d380b52..0000000 --- a/app/photos/migrations/0015_auto_20161022_1411.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-22 14:11 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0014_remove_luximagesize_is_portrait'), - ] - - operations = [ - migrations.RenameField( - model_name='luximagesize', - old_name='long_edge', - new_name='width', - ), - ] diff --git a/app/photos/migrations/0016_auto_20161022_1411.py b/app/photos/migrations/0016_auto_20161022_1411.py deleted file mode 100644 index 54b84d7..0000000 --- a/app/photos/migrations/0016_auto_20161022_1411.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-10-22 14:11 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0015_auto_20161022_1411'), - ] - - operations = [ - migrations.AddField( - model_name='luximagesize', - name='height', - field=models.IntegerField(blank=True, null=True), - ), - migrations.AlterField( - model_name='luximagesize', - name='width', - field=models.IntegerField(blank=True, null=True), - ), - ] diff --git a/app/photos/migrations/0017_auto_20161130_1218.py b/app/photos/migrations/0017_auto_20161130_1218.py deleted file mode 100644 index 8d5a496..0000000 --- a/app/photos/migrations/0017_auto_20161130_1218.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-11-30 12:18 -from __future__ import unicode_literals - -import datetime -from django.db import migrations, models -import photos.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0016_auto_20161022_1411'), - ] - - operations = [ - migrations.CreateModel( - name='LuxVideo', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('video_mp4', models.FileField(blank=True, null=True, upload_to=photos.models.get_vid_upload_path)), - ('video_webm', models.FileField(blank=True, null=True, upload_to=photos.models.get_vid_upload_path)), - ('video_poster', models.FileField(blank=True, null=True, upload_to=photos.models.get_vid_upload_path)), - ('title', models.CharField(blank=True, max_length=300, null=True)), - ('pub_date', models.DateTimeField(default=datetime.datetime.now)), - ], - options={ - 'verbose_name_plural': 'Videos', - 'ordering': ('-pub_date', 'id'), - 'get_latest_by': 'pub_date', - }, - ), - migrations.AlterField( - model_name='luximage', - name='pub_date', - field=models.DateTimeField(default=datetime.datetime.now), - ), - ] diff --git a/app/photos/migrations/0018_auto_20161130_1218.py b/app/photos/migrations/0018_auto_20161130_1218.py deleted file mode 100644 index 784175a..0000000 --- a/app/photos/migrations/0018_auto_20161130_1218.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-11-30 12:18 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0017_auto_20161130_1218'), - ] - - operations = [ - migrations.RemoveField( - model_name='luximage', - name='is_video', - ), - migrations.AddField( - model_name='luxvideo', - name='vimeo_url', - field=models.CharField(blank=True, max_length=300, null=True), - ), - migrations.AddField( - model_name='luxvideo', - name='youtube_url', - field=models.CharField(blank=True, max_length=80, null=True), - ), - ] diff --git a/app/photos/migrations/0019_auto_20190704_0903.py b/app/photos/migrations/0019_auto_20190704_0903.py deleted file mode 100644 index 833ee69..0000000 --- a/app/photos/migrations/0019_auto_20190704_0903.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-04 09:03 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0018_auto_20161130_1218'), - ] - - operations = [ - migrations.AlterModelOptions( - name='luximagesize', - options={'ordering': ('-name', 'id'), 'verbose_name_plural': 'Image Sizes'}, - ), - ] diff --git a/app/photos/migrations/0020_auto_20201201_2116.py b/app/photos/migrations/0020_auto_20201201_2116.py deleted file mode 100644 index 39d4fd9..0000000 --- a/app/photos/migrations/0020_auto_20201201_2116.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.1 on 2020-12-01 21:16 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('locations', '0028_auto_20200308_1152'), - ('photos', '0019_auto_20190704_0903'), - ] - - operations = [ - migrations.AlterField( - model_name='luximage', - name='location', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='locations.location'), - ), - ] diff --git a/app/photos/migrations/0021_auto_20201201_2118.py b/app/photos/migrations/0021_auto_20201201_2118.py deleted file mode 100644 index 25e4f8f..0000000 --- a/app/photos/migrations/0021_auto_20201201_2118.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-12-01 21:18 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photos', '0020_auto_20201201_2116'), - ] - - operations = [ - migrations.AlterField( - model_name='luximage', - name='sizes', - field=models.ManyToManyField(blank=True, related_name='_luximage_sizes_+', to='photos.LuxImageSize'), - ), - ] diff --git a/app/photos/migrations/__init__.py b/app/photos/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/app/photos/migrations/__init__.py +++ /dev/null diff --git a/app/photos/models.py b/app/photos/models.py deleted file mode 100644 index 24a218f..0000000 --- a/app/photos/models.py +++ /dev/null @@ -1,555 +0,0 @@ -import os.path -import io -import datetime -from PIL import Image - -from django.core.exceptions import ValidationError -from django.contrib.gis.db import models -from django.contrib.sitemaps import Sitemap -from django.utils.encoding import force_text -from django.utils.functional import cached_property -from django.urls import reverse -from django.apps import apps -from django.utils.html import format_html -from django.utils.text import slugify -from django.conf import settings -from django import forms - -from taggit.managers import TaggableManager - -from resizeimage.imageexceptions import ImageSizeError - -from .utils import resize_image -from .readexif import readexif -from django.db.models.signals import post_save -from django.dispatch import receiver -from django.db.models.signals import m2m_changed - - -def get_upload_path(self, filename): - return "images/original/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) - -def get_vid_upload_path(self, filename): - return "images/videos/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) - -class LuxImageSize(models.Model): - name = models.CharField(null=True, blank=True, max_length=30) - width = models.IntegerField(null=True, blank=True) - height = models.IntegerField(null=True, blank=True) - quality = models.IntegerField() - - class Meta: - ordering = ('-name', 'id') - verbose_name_plural = 'Image Sizes' - - def __str__(self): - if self.width: - size = self.width - if self.height: - size = self.height - return "%s - %s" %(self.name, str(size)) - - -class LuxImage(models.Model): - image = models.FileField(blank=True, null=True, upload_to=get_upload_path) - title = models.CharField(null=True, blank=True, max_length=300) - alt = models.CharField(null=True, blank=True, max_length=300) - photo_credit_source = models.CharField(null=True, blank=True, max_length=300) - photo_credit_url = models.CharField(null=True, blank=True, max_length=300) - caption = models.TextField(blank=True, null=True) - pub_date = models.DateTimeField(default=datetime.datetime.now) - exif_raw = models.TextField(blank=True, null=True) - exif_aperture = models.CharField(max_length=50, blank=True, null=True) - exif_make = models.CharField(max_length=50, blank=True, null=True) - exif_model = models.CharField(max_length=50, blank=True, null=True) - exif_exposure = models.CharField(max_length=50, blank=True, null=True) - exif_iso = models.CharField(max_length=50, blank=True, null=True) - exif_focal_length = models.CharField(max_length=50, blank=True, null=True) - exif_lens = models.CharField(max_length=50, blank=True, null=True) - exif_date = models.DateTimeField(blank=True, null=True) - height = models.CharField(max_length=6, blank=True, null=True) - width = models.CharField(max_length=6, blank=True, null=True) - point = models.PointField(null=True, blank=True) - location = models.ForeignKey("locations.Location", on_delete=models.CASCADE, null=True, blank=True, related_name="+") - is_public = models.BooleanField(default=True) - sizes = models.ManyToManyField(LuxImageSize, blank=True, related_name="+") - flickr_id = models.CharField(null=True, blank=True, max_length=80) - twitter_link = models.CharField(null=True, blank=True, max_length=300) - facebook_link = models.CharField(null=True, blank=True, max_length=300) - - class Meta: - ordering = ('-pub_date', 'id') - verbose_name_plural = 'Images' - get_latest_by = 'pub_date' - - def __str__(self): - if self.title: - return "%s" % self.title - else: - return "%s" % self.pk - - def get_type(self): - return str(self.__class__.__name__) - - def get_admin_image(self): - for size in self.sizes.all(): - if size.width and size.width <= 820 or size.height and size.height <= 800: - return self.get_image_by_size(size.name) - - def get_admin_insert(self): - return "/media/images/%s/%s_tn.%s" % (self.pub_date.strftime("%Y"), self.get_image_name(), self.get_image_ext()) - - def get_largest_image(self): - t = [] - for size in self.sizes.all(): - t.append(size.width) - t.sort(key=float) - t.reverse() - return self.get_image_path_by_size(t[0]) - - def get_image_name(self): - return self.image.url.split("original/")[1][5:-4] - - def get_image_name_new(self): - return os.path.basename(self.image.path)[:-4] - - def get_image_ext(self): - return self.image.url[-3:] - - @cached_property - def get_featured_jrnl(self): - ''' cached version of getting the primary image for archive page''' - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'featured_jrnl', self.get_image_ext()) - - @cached_property - def get_picwide_sm(self): - ''' cached version of getting the second image for archive page''' - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'picwide-sm', self.get_image_ext()) - - @cached_property - def get_srcset(self): - srcset = "" - length = len(self.sizes.all()) - print(length) - loopnum = 1 - for size in self.sizes.all(): - srcset += "%s%s/%s_%s.%s %sw" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), size.name, self.get_image_ext(), size.width) - if loopnum < length: - srcset += ", " - loopnum = loopnum+1 - return srcset - - @cached_property - def get_src(self): - src = "" - if self.sizes.all().count() > 1: - src += "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), 'picwide-med', self.get_image_ext()) - else: - src += "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.get_image_name(), [size.name for size in self.sizes.all()], self.get_image_ext()) - return src - - def get_image_by_size(self, size="original"): - base = self.get_image_name() - if size == "admin_insert": - return "images/%s/%s.%s" % (self.pub_date.strftime("%Y"), base, self.get_image_ext()) - if size == "original": - return "%soriginal/%s/%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, self.get_image_ext()) - else: - if size != 'tn': - try: - self.sizes.filter(name=size) - except DoesNotExist: - print("new size is "+s.name) - self.sizes.add(s) - return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, size, self.get_image_ext()) - - def get_image_path_by_size(self, size="original"): - base = self.get_image_name() - if size == "original": - return "%s/original/%s/%s.%s" % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), base, self.get_image_ext()) - else: - return "%s/%s/%s_%s.%s" % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), base, size, self.get_image_ext()) - - def get_thumbnail_url(self): - return self.get_image_by_size("tn") - - def admin_thumbnail(self): - return format_html('<a href="%s"><img src="%s"></a>' % (self.get_image_by_size(), self.get_image_by_size("tn"))) - admin_thumbnail.short_description = 'Thumbnail' - - def get_sizes(self): - return self.sizes.all() - - @property - def latitude(self): - return self.point.y - - @property - def longitude(self): - return self.point.x - - @property - def get_previous_published(self): - return self.get_previous_by_pub_date() - - @property - def get_next_published(self): - return self.get_next_by_pub_date() - - @property - def get_previous_admin_url(self): - n = self.get_previous_by_pub_date() - return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[n.id] ) - - @property - def get_next_admin_url(self): - model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name) - try: - return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[self.get_next_by_pub_date().pk] ) - except model.DoesNotExist: - return '' - - @property - def is_portait(self): - if int(self.height) > int(self.width): - return True - else: - return False - - def save(self, *args, **kwargs): - if not self.point: - self.point = LuxImage.objects.latest().point - try: - self.location = apps.get_model('locations', 'Location').objects.filter( - geometry__contains=self.point - ).get() - except apps.get_model('locations', 'Location').DoesNotExist: - raise forms.ValidationError("There is no location associated with that point, add it: %sadmin/locations/location/add/" % (settings.BASE_URL)) - super(LuxImage, self).save() - - -@receiver(post_save, sender=LuxImage) -def post_save_events(sender, update_fields, created, instance, **kwargs): - if instance.exif_raw == '': - filename, file_extension = os.path.splitext(instance.image.path) - if file_extension != ".mp4": - img = Image.open(instance.image.path) - instance.height = img.height - instance.width = img.width - instance = readexif(instance) - post_save.disconnect(post_save_events, sender=LuxImage) - instance.save() - post_save.connect(post_save_events, sender=LuxImage) - - -@receiver(m2m_changed, sender=LuxImage.sizes.through) -def update_photo_sizes(sender, instance, **kwargs): - base_path = "%s/%s/" % (settings.IMAGES_ROOT, instance.pub_date.strftime("%Y")) - filename, file_extension = os.path.splitext(instance.image.path) - if file_extension != ".mp4": - img = Image.open(instance.image.path) - resize_image(img, 160, None, 78, base_path, "%s_tn.%s" % (instance.get_image_name(), instance.get_image_ext())) - for size in instance.sizes.all(): - if size.width: - print("Image width is:"+str(img.width)) - try: - if size.width <= img.width: - resize_image(img, size.width, None, size.quality, base_path, "%s_%s.%s" % (instance.get_image_name(), slugify(size.name), instance.get_image_ext())) - else: - raise ValidationError({'items': ["Size is larger than source image"]}) - except ImageSizeError: - m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) - instance.sizes.remove(size) - m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) - if size.height: - try: - if size.height <= img.height: - resize_image(img, None, size.height, size.quality, base_path, "%s_%s.%s" % (instance.get_image_name(), slugify(size.name), instance.get_image_ext())) - - else: - pass - except ImageSizeError: - m2m_changed.disconnect(update_photo_sizes, sender=LuxImage.sizes.through) - instance.sizes.remove(size) - m2m_changed.connect(update_photo_sizes, sender=LuxImage.sizes.through) - - -class LuxGallery(models.Model): - title = models.CharField(blank=True, max_length=300) - description = models.TextField(blank=True, null=True) - slug = models.CharField(blank=True, max_length=300) - thumb = models.ForeignKey(LuxImage, on_delete=models.CASCADE, related_name="gallery_thumb", null=True, blank=True) - images = models.ManyToManyField(LuxImage) - pub_date = models.DateTimeField(null=True) - point = models.PointField(null=True, blank=True) - location = models.ForeignKey("locations.Location", on_delete=models.CASCADE, null=True, blank=True) - is_public = models.BooleanField(default=True) - caption_style = models.CharField(blank=True, null=True, max_length=400) - - class Meta: - ordering = ('-pub_date', 'id') - verbose_name_plural = 'Galleries' - get_latest_by = 'pub_date' - - def __str__(self): - return self.title - - def get_main_image(self): - return "%sgallery_thumbs/%s.jpg" % (settings.IMAGES_URL, self.id) - - def get_absolute_url(self): - if self.is_public: - return "/photos/galleries/%s" % (self.slug) - else: - return "/photos/galleries/private/%s" % (self.slug) - - def latitude(self): - if self.point: - return self.point.y - - def longitude(self): - if self.point: - return self.point.x - - def thumbs(self): - lst = [x.image.name for x in self.images.all()] - lst = ["<a href='/media/%s'>%s</a>" % (x, x.split('/')[-1]) for x in lst] - return ', '.join(item for item in lst if item) - thumbs.allow_tags = True - - -class LuxVideo(models.Model): - video_mp4 = models.FileField(blank=True, null=True, upload_to=get_vid_upload_path) - video_webm = models.FileField(blank=True, null=True, upload_to=get_vid_upload_path) - video_poster = models.FileField(blank=True, null=True, upload_to=get_vid_upload_path) - title = models.CharField(null=True, blank=True, max_length=300) - pub_date = models.DateTimeField(default=datetime.datetime.now) - youtube_url = models.CharField(null=True, blank=True, max_length=80) - vimeo_url = models.CharField(null=True, blank=True, max_length=300) - - def __str__(self): - if self.title: - return self.title - else: - return str(self.pk) - - def get_type(self): - return str(self.__class__.__name__) - - class Meta: - ordering = ('-pub_date', 'id') - verbose_name_plural = 'Videos' - get_latest_by = 'pub_date' - -class Photo(models.Model): - description = models.TextField(blank=True, null=True) - title = models.CharField(blank=True, max_length=300) - pub_date = models.DateTimeField() - tags = TaggableManager(blank=True) - exif_aperture = models.CharField(max_length=50, blank=True, null=True) - exif_make = models.CharField(max_length=50, blank=True, null=True) - exif_model = models.CharField(max_length=50, blank=True, null=True) - exif_exposure = models.CharField(max_length=50, blank=True, null=True) - exif_iso = models.CharField(max_length=50, blank=True, null=True) - exif_focal_length = models.CharField(max_length=50, blank=True, null=True) - exif_lens = models.CharField(max_length=50, blank=True, null=True) - exif_date = models.DateTimeField() - """Flickr Specific Stuff""" - # Vlickr id is varchar since Flickr ids are larger than than integerfield can handle and BigIntegerField gets weird in Postgres. - flickr_id = models.CharField(max_length=300) - flickr_owner = models.CharField(max_length=20) - flickr_server = models.IntegerField() - flickr_farm = models.IntegerField() - flickr_secret = models.CharField(max_length=50) - flickr_originalsecret = models.CharField(max_length=50) - lon = models.FloatField('Longitude', help_text="Longitude of centerpoint", null=True) - lat = models.FloatField('Latitude', help_text="Latitude of centerpoint", null=True) - location = models.ForeignKey("locations.Location", on_delete=models.CASCADE, null=True) - region = models.ForeignKey("locations.Region", on_delete=models.CASCADE, null=True) - slideshowimage_width = models.CharField(max_length=4, blank=True, null=True) - slideshowimage_height = models.CharField(max_length=4, blank=True, null=True) - slideshowimage_margintop = models.CharField(max_length=4, blank=True, null=True) - slideshowimage_marginleft = models.CharField(max_length=4, blank=True, null=True) - is_public = models.BooleanField(default=True) - - class Meta: - ordering = ('-pub_date',) - - def admin_thumbnail(self): - return force_text('<a href="%s"><img src="%s"></a>' % (self.get_absolute_url(), self.get_small_square_url())) - admin_thumbnail.allow_tags = True - admin_thumbnail.short_description = 'Thumbnail' - - def get_local_medium_url(self): - return '%sflickr/med/%s/%s.jpg' % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.flickr_id) - - def get_local_orig_url(self): - return '%s/flickr/full/%s/%s.jpg' % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), self.flickr_id) - - def get_local_slideshow_url(self): - return '%sslideshow/%s/%s.jpg' % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.flickr_id) - - def __str__(self): - return self.title - - def get_absolute_url(self): - return "/photo/%s/" % (self.id) - - def get_model_name(self): - return 'photo' - - def get_small_square_url(self): - return self.get_pic_url(size="small_square") - - def get_large_url(self): - return self.get_pic_url(size="large") - - def get_small_url(self): - return self.get_pic_url(size="small") - - def get_medium_url(self): - return self.get_pic_url(size="medium") - - def get_original_url(self): - # return self.get_pic_url(size="original") - return "http://farm%s.static.flickr.com/%s/%s_%s_o.jpg" % (self.flickr_farm, self.flickr_server, self.flickr_id, self.flickr_originalsecret) - - def get_retina_slideshow_url(self): - return '%sslideshow/%s/%sx2.jpg' % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.flickr_id) - - def has_retina(self): - return os.path.isfile('%s/slideshow/%s/%sx2.jpg' % (settings.IMAGES_ROOT, self.pub_date.strftime("%Y"), self.flickr_id)) - - @property - def get_height(self): - im = Image.open('%s/slideshow/%s/%s.jpg' % (settings.IMAGES_ROOT, - self.pub_date.strftime("%Y"), self.flickr_id)) - xsize, ysize = im.size - return ysize - - @property - def get_width(self): - im = Image.open('%s/slideshow/%s/%s.jpg' % (settings.IMAGES_ROOT, - self.pub_date.strftime("%Y"), self.flickr_id)) - xsize, ysize = im.size - return xsize - - @property - def get_margin_top(self): - im = Image.open('%s/slideshow/%s/%s.jpg' % (settings.IMAGES_ROOT, - self.pub_date.strftime("%Y"), self.flickr_id)) - xsize, ysize = im.size - mtop = 340 - (ysize / 2) - return mtop - - @property - def get_margin_left(self): - im = Image.open('%s/slideshow/%s/%s.jpg' % (settings.IMAGES_ROOT, - self.pub_date.strftime("%Y"), self.flickr_id)) - xsize, ysize = im.size - mtop = 500 - (xsize / 2) - return mtop - - @property - def flickr_link(self): - return '%s%s/' % ('http://www.flickr.com/photos/luxagraf/', self.flickr_id) - - @property - def is_portait(self): - if int(self.slideshowimage_height) > int(self.slideshowimage_width): - return True - else: - return False - - def get_pic_url(self, size='small'): - # small_square=75x75 - # thumb=100 on longest side - # small=240 on longest side - # medium=500 on longest side - # large=1024 on longest side - # original=duh - base_url = "http://static.flickr.com" - size_char = 's' # default to small_square - if size == 'small_square': - size_char = '_s' - elif size == 'thumb': - size_char = '_t' - elif size == 'small': - size_char = '_m' - elif size == 'medium': - size_char = '' - elif size == 'large': - size_char = '_b' - elif size == 'original': - size_char = '_o' - - return "http://farm%s.static.flickr.com/%s/%s_%s%s.jpg" % (self.flickr_farm, self.flickr_server, self.flickr_id, self.flickr_secret, size_char) - - def get_tumble_image(self): - return "%s/crops/%s/%s.jpg" % (settings.IMAGES_URL, self.pub_date.strftime("%Y/%b").lower(), self.id) - - def get_previous_published(self): - return self.get_previous_by_pub_date() - - def get_next_published(self): - return self.get_next_by_pub_date() - - def comment_period_open(self): - return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date - - def save(self, *args, **kwargs): - super(Photo, self).save() - - -class PhotoGallery(models.Model): - set_id = models.CharField(blank=True, max_length=300) - set_title = models.CharField(blank=True, max_length=300) - set_desc = models.TextField(blank=True, null=True) - set_slug = models.CharField(blank=True, max_length=300) - primary = models.CharField(blank=True, max_length=300) - photos = models.ManyToManyField(Photo) - location = models.ForeignKey("locations.Location", on_delete=models.CASCADE, null=True) - region = models.ForeignKey("locations.Region", on_delete=models.CASCADE, null=True) - pub_date = models.DateTimeField(null=True) - - class Meta: - ordering = ('-pub_date', 'id') - verbose_name_plural = 'Photo Galleries' - get_latest_by = 'pub_date' - - def __str__(self): - return self.set_title - - def get_main_image(self): - return "%sgallery_thumbs/%s.jpg" % (settings.IMAGES_URL, self.id) - - def get_absolute_url(self): - return "/photos/galleries/%s/" % (self.set_slug) - - -class PhotoGallerySitemap(Sitemap): - changefreq = "never" - priority = 0.7 - protocol = "https" - - def items(self): - return PhotoGallery.objects.all() - - def lastmod(self, obj): - return obj.pub_date - - -def resize_luximage(self, image): - image.save() - img = Image.open(image.image.path) - base_path = "%s/galleries/" % settings.IMAGES_ROOT - if img.size[0] > img.size[1]: - resize_image(img, 2280, None, 65, base_path+'large/', image.get_image_name()) - resize_image(img, 1140, None, 72, base_path+'medium/', image.get_image_name()) - resize_image(img, 720, None, 68, base_path+'small/', image.get_image_name()) - if img.size[1] > img.size[0]: - resize_image(img, None, 1600, 65, base_path+'large/', image.get_image_name()) - resize_image(img, None, 800, 72, base_path+'medium/', image.get_image_name()) - resize_image(img, None, 460, 60, base_path+'small/', image.get_image_name()) - - resize_image(img, 160, None, 68, base_path+'thumb/', image.get_image_name()) diff --git a/app/photos/photos.js b/app/photos/photos.js deleted file mode 100644 index b93467a..0000000 --- a/app/photos/photos.js +++ /dev/null @@ -1,71 +0,0 @@ -//Utility functions for map info window -function mapit(obj) { - lat = parseFloat(obj.attr('data-latitude')); - lon = parseFloat(obj.attr('data-longitude')); - elid= obj.attr('data-imgid'); - map = L.map(document.getElementById("mw-"+elid)); - centerCoord = new L.LatLng(lat, lon); - zoom = 8; - L.tileLayer.provider('Esri.WorldTopoMap', {maxZoom: 18, attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Tiles © Esri and the GIS User Community'}).addTo(map); - map.setView(centerCoord, zoom); - L.marker([lat, lon]).addTo(map); -} - //########## utility functions to create/remove map container ############ -function create_map(obj) { - //find id of this image caption: - var imgid = obj.attr('data-imgid'); - //create container divs - $('<div class="map-container" id="mc-'+imgid+'">').insertBefore($(obj).parent().parent()); - //$(obj).parent().parent().parent().prepend('<div class="map-container" id="mc-'+imgid+'">'); - $('#mc-'+imgid).append('<div class="map-wrapper" id="mw-'+imgid+'">'); - //deal with the variable height of div.legend - $('#mc-'+imgid).css({ - bottom: function(index, value) { - return parseFloat($(obj).parent().parent().height())+20; - } - }); - - mapit(obj); -} -function remove_map(imgid) { - $('#mc-'+imgid).remove(); -} - -//############ Document.ready events ############## -$(document).ready(function(){ - - //set up click events for map button - $('.map-link').click( function() { - imgid = $(this).attr('data-imgid'); - if ($('#mc-'+imgid).is(":visible")) { - remove_map(imgid); - } else { - create_map($(this)); - } - return false; - - }); - var $ele = $('#slides').children(); - var $curr = 0; - $(document).bind('keydown', function (e) { - var code = e.which; - switch (code) { - case 39: - if ($curr <= $ele.size()) { - $.scrollTo($ele[$curr], 800 ); - $curr++; - } - break; - case 37: - if ($curr > 0) { - $curr--; - var $now = $curr; - $now--; - $.scrollTo($ele[$now], 800 ); - } - break; - } - return; - }); -}); - diff --git a/app/photos/readexif.py b/app/photos/readexif.py deleted file mode 100644 index 70a6987..0000000 --- a/app/photos/readexif.py +++ /dev/null @@ -1,78 +0,0 @@ -import time -from fractions import Fraction - -from django.contrib.gis.geos import Point - -import exiftool - -from locations.models import Location - - -def readexif(image): - """ - takes an image and fills in all the exif data tracked in the image model - - """ - with exiftool.ExifTool() as et: - meta = et.get_metadata(image.image.path) - et.terminate() - image.exif_raw = meta - try: - image.title = meta["EXIF:ImageDescription"] - except: - try: - image.title = meta["XMP:Title"] - except: - pass - try: - image.caption = meta["EXIF:UserComment"] - except: - pass - try: - image.exif_lens = meta["MakerNotes:LensType"] - except: - try: - image.exif_lens = meta["XMP:Lens"] - except: - pass - try: - image.exif_aperture = meta["EXIF:FNumber"] - except: - pass - try: - image.exif_make = meta["EXIF:Make"] - except: - pass - try: - image.exif_model = meta["EXIF:Model"] - except: - pass - try: - image.exif_exposure = str(Fraction(float(meta["EXIF:ExposureTime"])).limit_denominator()) - except: - pass - try: - image.exif_iso = meta["EXIF:ISO"] - except: - pass - try: - image.exif_focal_length = meta["EXIF:FocalLength"] - except: - pass - try: - fmt_date = time.strptime(meta["EXIF:DateTimeOriginal"], "%Y:%m:%d %H:%M:%S") - except: - pass - try: - image.exif_date = time.strftime("%Y-%m-%d %H:%M:%S", fmt_date) - except: - pass - try: - image.height = meta["File:ImageHeight"] - except: - pass - try: - image.width = meta["File:ImageWidth"] - except: - pass - return image diff --git a/app/photos/resize.py b/app/photos/resize.py deleted file mode 100644 index 13c0151..0000000 --- a/app/photos/resize.py +++ /dev/null @@ -1,53 +0,0 @@ -import os -import io - -from django.conf import settings - -try: - import Image - import ImageFile -except ImportError: - try: - from PIL import Image - from PIL import ImageFile - except ImportError: - raise ImportError("Could not import the Python Imaging Library.") - -ImageFile.MAXBLOCK = 1000000 - - -def make_local_copies(self,photo): - orig_dir = settings.IMAGES_ROOT + '/flickr/full/' + photo.pub_date.strftime("%Y") - if not os.path.isdir(orig_dir): - os.makedirs(orig_dir) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - local_full = '%s/%s.jpg' % (orig_dir, photo.flickr_id) - img.save(local_full) - - #calculate crop: - cur_width, cur_height = img.size - new_width, new_height = 291, 350 - ratio = max(float(new_width) / cur_width, float(new_height) / cur_height) - x = (cur_width * ratio) - y = (cur_height * ratio) - xd = abs(new_width - x) - yd = abs(new_height - y) - x_diff = int(xd / 2) - y_diff = int(yd / 2) - box = (int(x_diff), int(y_diff), int(x_diff + new_width), int(y_diff + new_height)) - - # create resized file - resized = img.resize((int(x), int(y)), Image.ANTIALIAS).crop(box) - # save resized file - resized_filename = '%s/%s.jpg' % (crop_dir, set.id) - try: - if img.format == 'JPEG': - resized.save(resized_filename, 'JPEG', quality=95, optimize=True) - else: - resized.save(resized_filename) - except IOError as e: - if os.path.isfile(resized_filename): - os.unlink(resized_filename) - raise e - os.unlink(img) diff --git a/app/photos/retriever.py b/app/photos/retriever.py deleted file mode 100644 index f5cae68..0000000 --- a/app/photos/retriever.py +++ /dev/null @@ -1,323 +0,0 @@ -import json -import datetime -import os -import io -import urllib.request -import urllib.parse -import urllib.error - -from django.template.defaultfilters import slugify -from django.core.exceptions import ObjectDoesNotExist -from django.utils.encoding import force_text -from django.conf import settings - -from photos.models import Photo, PhotoGallery - -# from https://github.com/alexis-mignon/python-flickr-api -# terribly documented, but offers a good clean OOP approach if you're willing to figure it out... -import flickr_api -import flickrapi - -# Required PIL classes may or may not be available from the root namespace depending on the installation -try: - import Image - import ImageFile -except ImportError: - try: - from PIL import Image - from PIL import ImageFile - except ImportError: - raise ImportError("Could not import the Python Imaging Library.") - -ImageFile.MAXBLOCK = 1000000 - -EXIF_PARAMS = { - "FNumber": 'f/2.8', - "Make": 'Apple', - "Model": 'iPhone', - "ExposureTime": '', - "ISO": '', - "FocalLength": '', - "LensModel": '', - 'DateTimeOriginal': '2013:09:03 22:44:25' -} - -class SyncFlickr(): - - def __init__(self): - self.flickr = flickrapi.FlickrAPI(settings.FLICKR_API_KEY, settings.FLICKR_API_SECRET,format='parsed-json') - - - def sync_sets(self, *args, **kwargs): - p = self.flickr.photosets.getList(user_id='85322932@N00') - disregard = [ - 'POTD 2008', - 'Snow Day', - 'Wedding', - 'Some random stuff', - 'Lilah & Olivia', - '6 months+', - '6-9 months', - '9-18 months', - ] - for photoset in p['photosets']['photoset']: - if photoset['title']['_content'] in disregard: - pass - else: - try: - row = PhotoGallery.objects.get(set_id__exact=photoset['id']) - print(('%s %s %s' % ('already have', row.set_title, 'moving on...'))) - # okay it already exists, but is it up-to-date? - self.get_photos_in_set(photoset['id'],row) - except ObjectDoesNotExist: - s = PhotoGallery.objects.get_or_create( - set_id=force_text(photoset['id']), - set_title=force_text(photoset['title']['_content']), - set_desc=force_text(photoset['description']['_content']), - set_slug=slugify(force_text(photoset['title']['_content'])[:40]), - primary=force_text(photoset['primary']), - pub_date=datetime.datetime.fromtimestamp(float(photoset['date_create'])) - ) - - #get_photos_in_set(photoset, s) - #create the gallery thumbnail image: - #photo = Photo.objects.get(flickr_id__exact=str(photoset['primary'])) - #make_gallery_thumb(photo, s) - - - - def get_photos_in_set(self, flickr_id, photoset): - photos = self.flickr.photosets.getPhotos(photoset_id=flickr_id) - for photo in photos['photoset']['photo']: - try: - p = Photo.objects.get(flickr_id__exact=str(photo['id'])) - except ObjectDoesNotExist: - p = self.get_photo(photo['id']) - if p.is_public: - pass #photoset.photos.add(p) - #slideshow_image(p, 1000, 800, 95) - print(p) - - def get_photo(self, photo_id): - photo = self.flickr.photos.getInfo(photo_id=photo_id) - info = photo['photo'] - try: - geo = self.flickr.photos.geo.getLocation(photo_id=photo_id) - location, region = self.get_geo(float(geo['photo']['location']['latitude']), float(geo['photo']['location']['longitude'])) - except KeyError: - print("no effing geodata asshat") - exif = self.exif_handler(self.flickr.photos.getExif(photo_id=photo_id)['photo']['exif']) - p, created = Photo.objects.get_or_create( - title=info['title']['_content'], - flickr_id=info['id'], - flickr_owner=info['owner']['nsid'], - flickr_server=info['server'], - flickr_secret=info['secret'], - flickr_originalsecret=info['originalsecret'], - flickr_farm=info['farm'], - pub_date=self.flickr_datetime_to_datetime(exif["DateTimeOriginal"].replace(':', '-', 2)), - description=info['description']['_content'], - exif_aperture=exif['FNumber'], - exif_make=exif['Make'], - exif_model=exif['Model'], - exif_exposure=exif['ExposureTime'], - exif_iso=exif['ISO'], - exif_lens=exif['LensModel'], - exif_focal_length=exif['FocalLength'], - exif_date=self.flickr_datetime_to_datetime(exif["DateTimeOriginal"].replace(':', '-', 2)), - lat=float(geo['photo']['location']['latitude']), - lon=float(geo['photo']['location']['longitude']), - region=region, - location=location, - ) - if created: - for tag in info['tags']['tag']: - p.tags.add(tag['raw']) - p.save() - - local = FlickrImage() - local.make_local_copies(p) - #retina image: - #slideshow_image(p, 2000, 1600, 75) - #normal image - print("grabbing... "+p.title) - return p - - - def sync_flickr_photos(self, *args, **kwargs): - photos = self.flickr.people.getPhotos(user_id="85322932@N00", extras="date_upload,date_taken,geo") - for photo in photos['photos']['photo']: - try: - row = Photo.objects.get(flickr_id=photo['id'], flickr_secret=photo['secret']) - print('already have ' + photo['id'] + ' moving on') - except ObjectDoesNotExist: - p = self.get_photo(photo['id']) - - - - """ - ################################################ - ## Various meta data and geo helper functions ## - ################################################ - """ - - def exif_handler(self, data): - converted = {} - try: - for t in data: - converted[t['tag']] = t['raw']['_content'] - except: - pass - for k, v in list(EXIF_PARAMS.items()): - if k not in converted: - converted[k] = v - return converted - - - def flickr_datetime_to_datetime(self, fdt): - from datetime import datetime - from time import strptime - date_parts = strptime(fdt, '%Y-%m-%d %H:%M:%S') - return datetime(*date_parts[0:6]) - - - def get_geo(self, lat, lon): - from locations.models import Location, Region - from django.contrib.gis.geos import Point - pnt_wkt = Point(lon, lat) - try: - location = Location.objects.get(geometry__contains=pnt_wkt) - except Location.DoesNotExist: - location = None - try: - region = Region.objects.get(geometry__contains=pnt_wkt) - except Region.DoesNotExist: - region = None - return location, region - - - - - - -class FlickrImage(): - """ - ## Photo retrieval functions to pull down images from Flickr servers ## - """ - - def slideshow_image(self, photo, max_width, max_height, quality): - slide_dir = settings.IMAGES_ROOT + '/slideshow/' + photo.pub_date.strftime("%Y") - if not os.path.isdir(slide_dir): - os.makedirs(slide_dir) - - # Is it a retina image or not? - if max_width >= 1001 or max_height >= 801: - filename = '%s/%sx2.jpg' % (slide_dir, photo.flickr_id) - else: - filename = '%s/%s.jpg' % (slide_dir, photo.flickr_id) - - flickr_photo = photo.get_original_url() - fname = urllib.request.urlopen(flickr_photo) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - cur_width, cur_height = img.size - #if image landscape - if cur_width > cur_height: - new_width = max_width - #check to make sure we aren't upsizing - if cur_width > new_width: - ratio = float(new_width) / cur_width - x = (cur_width * ratio) - y = (cur_height * ratio) - resized = img.resize((int(x), int(y)), Image.ANTIALIAS) - resized.save(filename, 'JPEG', quality=quality, optimize=True) - else: - img.save(filename) - else: - #image portrait - new_height = max_height - #check to make sure we aren't upsizing - if cur_height > new_height: - ratio = float(new_height) / cur_height - x = (cur_width * ratio) - y = (cur_height * ratio) - resized = img.resize((int(x), int(y)), Image.ANTIALIAS) - resized.save(filename, 'JPEG', quality=quality, optimize=True) - else: - img.save(filename) - photo.slideshowimage_width = photo.get_width - photo.slideshowimage_height = photo.get_height - photo.slideshowimage_margintop = photo.get_margin_top - photo.slideshowimage_marginleft = photo.get_margin_left - photo.save() - #now resize the local copy - - - def make_local_copies(self,photo): - orig_dir = settings.IMAGES_ROOT + '/flickr/full/' + photo.pub_date.strftime("%Y") - if not os.path.isdir(orig_dir): - os.makedirs(orig_dir) - full = photo.get_original_url() - fname = urllib.request.urlopen(full) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - local_full = '%s/%s.jpg' % (orig_dir, photo.flickr_id) - img.save(local_full) - #save large size - large_dir = settings.IMAGES_ROOT + '/flickr/large/' + photo.pub_date.strftime("%Y") - if not os.path.isdir(large_dir): - os.makedirs(large_dir) - large = photo.get_large_url() - fname = urllib.request.urlopen(large) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - local_large = '%s/%s.jpg' % (large_dir, photo.flickr_id) - if img.format == 'JPEG': - img.save(local_large) - #save medium size - med_dir = settings.IMAGES_ROOT + '/flickr/med/' + photo.pub_date.strftime("%Y") - if not os.path.isdir(med_dir): - os.makedirs(med_dir) - med = photo.get_medium_url() - fname = urllib.request.urlopen(med) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - local_med = '%s/%s.jpg' % (med_dir, photo.flickr_id) - img.save(local_med) - - - def make_gallery_thumb(self, photo, set): - crop_dir = settings.IMAGES_ROOT + '/gallery_thumbs/' - if not os.path.isdir(crop_dir): - os.makedirs(crop_dir) - remote = photo.get_original_url() - print(remote) - fname = urllib.request.urlopen(remote) - im = io.StringIO(fname.read().decode('UTF-8')) # constructs a StringIO holding the image - img = Image.open(im) - #calculate crop: - cur_width, cur_height = img.size - new_width, new_height = 291, 350 - ratio = max(float(new_width) / cur_width, float(new_height) / cur_height) - x = (cur_width * ratio) - y = (cur_height * ratio) - xd = abs(new_width - x) - yd = abs(new_height - y) - x_diff = int(xd / 2) - y_diff = int(yd / 2) - box = (int(x_diff), int(y_diff), int(x_diff + new_width), int(y_diff + new_height)) - - # create resized file - resized = img.resize((int(x), int(y)), Image.ANTIALIAS).crop(box) - # save resized file - resized_filename = '%s/%s.jpg' % (crop_dir, set.id) - try: - if img.format == 'JPEG': - resized.save(resized_filename, 'JPEG', quality=95, optimize=True) - else: - resized.save(resized_filename) - except IOError as e: - if os.path.isfile(resized_filename): - os.unlink(resized_filename) - raise e - os.unlink(img) diff --git a/app/photos/retriever.py.bak b/app/photos/retriever.py.bak deleted file mode 100644 index d3c572a..0000000 --- a/app/photos/retriever.py.bak +++ /dev/null @@ -1,314 +0,0 @@ -from __future__ import division -import datetime -import os -import cStringIO -import urllib - -from django.template.defaultfilters import slugify -from django.core.exceptions import ObjectDoesNotExist -from django.utils.encoding import force_unicode -from django.conf import settings - -# Required PIL classes may or may not be available from the root namespace -# depending on the installation -try: - import Image - import ImageFile -except ImportError: - try: - from PIL import Image - from PIL import ImageFile - except ImportError: - raise ImportError("Could not import the Python Imaging Library.") - -ImageFile.MAXBLOCK = 1000000 - -from photos.models import Photo, PhotoGallery - -# from https://github.com/alexis-mignon/python-flickr-api -# terribly documented, but offers a good clean OOP approach if you're willing to figure it out... -import flickr_api - -EXIF_PARAMS = { - "FNumber": 'f/2.8', - "Make": 'Apple', - "Model": 'iPhone', - "ExposureTime": '', - "ISO": '', - "FocalLength": '', - "LensModel": '', - 'DateTimeOriginal': '2013:09:03 22:44:25' -} - - -def sync_flickr_photos(*args, **kwargs): - flickr_api.set_keys(api_key=settings.FLICKR_API_KEY, api_secret=settings.FLICKR_API_SECRET) - flickr_api.set_auth_handler("app/photos/flickrauth") - user = flickr_api.test.login() - photos = user.getPhotos(extras="date_upload,date_taken,geo") - # reverse! reverse! - photos.reverse() - for photo in photos: - info = photo.getInfo() - try: - row = Photo.objects.get(flickr_id=info['id'], flickr_secret=info['secret']) - print('already have ' + info['id'] + ' moving on') - except ObjectDoesNotExist: - get_photo(photo) - - -def get_photo(photo): - info = photo.getInfo() - geo = photo.getLocation() - location, region = get_geo(float(geo['latitude']), float(geo['longitude'])) - exif = exif_handler(photo.getExif()) - p, created = Photo.objects.get_or_create( - title=info['title'], - flickr_id=info['id'], - flickr_owner=info['owner']['id'], - flickr_server=info['server'], - flickr_secret=info['secret'], - flickr_originalsecret=info['originalsecret'], - flickr_farm=info['farm'], - pub_date=flickr_datetime_to_datetime(info['taken']), - description=info['description'], - exif_aperture=exif['FNumber'], - exif_make=exif['Make'], - exif_model=exif['Model'], - exif_exposure=exif['ExposureTime'], - exif_iso=exif['ISO'], - exif_lens=exif['LensModel'], - exif_focal_length=exif['FocalLength'], - exif_date=flickr_datetime_to_datetime(exif["DateTimeOriginal"].replace(':', '-', 2)), - lat=float(geo['latitude']), - lon=float(geo['longitude']), - region=region, - location=location, - ) - if created: - for tag in info['tags']: - p.tags.add(tag['raw']) - p.save() - make_local_copies(p) - #retina image: - #slideshow_image(p, 2000, 1600, 75) - #normal image - print(p.title) - return p - - -def sync_sets(*args, **kwargs): - flickr_api.set_keys(api_key=settings.FLICKR_API_KEY, api_secret=settings.FLICKR_API_SECRET) - flickr_api.set_auth_handler("app/photos/flickrauth") - user = flickr_api.test.login() - photosets = user.getPhotosets() - # reverse! reverse! - photosets.reverse() - disregard = [ - 'POTD 2008', - 'Snow Day', - 'Wedding', - 'Some random stuff', - 'Lilah & Olivia', - '6 months+', - '6-9 months', - '9-18 months', - ] - for photoset in photosets: - if photoset['title'] in disregard: - pass - else: - try: - row = PhotoGallery.objects.get(set_id__exact=photoset['id']) - print('%s %s %s' % ('already have', row.set_title, 'moving on...')) - # okay it already exists, but is it up-to-date? - #get_photos_in_set(row,set.id) - except ObjectDoesNotExist: - s = PhotoGallery.objects.create( - set_id=force_unicode(photoset['id']), - set_title=force_unicode(photoset['title']), - set_desc=force_unicode(photoset['description']), - set_slug=slugify(force_unicode(photoset['title'])), - primary=force_unicode(photoset['primary']), - pub_date=datetime.datetime.fromtimestamp(float(photoset['date_create'])) - ) - - get_photos_in_set(photoset, s) - #create the gallery thumbnail image: - photo = Photo.objects.get(flickr_id__exact=str(photoset['primary'])) - make_gallery_thumb(photo, s) - - -def get_photos_in_set(flickr_photoset, photoset): - for photo in flickr_photoset.getPhotos(): - try: - p = Photo.objects.get(flickr_id__exact=str(photo['id'])) - except ObjectDoesNotExist: - p = get_photo(photo) - if p.is_public: - photoset.photos.add(p) - slideshow_image(p, 1000, 800, 95) - - -################################################ -## Various meta data and geo helper functions ## -################################################ - - -def exif_handler(data): - converted = {} - try: - for t in data: - converted[t['tag']] = t['raw'] - except: - pass - for k, v in EXIF_PARAMS.items(): - if not converted.has_key(k): - converted[k] = v - return converted - - -def flickr_datetime_to_datetime(fdt): - from datetime import datetime - from time import strptime - date_parts = strptime(fdt, '%Y-%m-%d %H:%M:%S') - return datetime(*date_parts[0:6]) - -def get_geo(lat,lon): - from locations.models import Location, Region - from django.contrib.gis.geos import Point - pnt_wkt = Point(lon, lat) - try: - location = Location.objects.get(geometry__contains=pnt_wkt) - except Location.DoesNotExist: - location = None - try: - region = Region.objects.get(geometry__contains=pnt_wkt) - except Region.DoesNotExist: - region = None - return location, region - -####################################################################### -## Photo retrieval functions to pull down images from Flickr servers ## -####################################################################### - -def slideshow_image(photo,max_width, max_height, quality): - slide_dir = settings.IMAGES_ROOT + '/slideshow/'+ photo.pub_date.strftime("%Y") - if not os.path.isdir(slide_dir): - os.makedirs(slide_dir) - - # Is it a retina image or not? - if max_width >= 1001 or max_height >= 801: - filename = '%s/%sx2.jpg' %(slide_dir, photo.flickr_id) - else: - filename = '%s/%s.jpg' %(slide_dir, photo.flickr_id) - - flickr_photo = photo.get_original_url() - fname = urllib.urlopen(flickr_photo) - im = cStringIO.StringIO(fname.read()) # constructs a StringIO holding the image - img = Image.open(im) - cur_width, cur_height = img.size - #if image landscape - if cur_width > cur_height: - new_width = max_width - #check to make sure we aren't upsizing - if cur_width > new_width: - ratio = float(new_width)/cur_width - x = (cur_width * ratio) - y = (cur_height * ratio) - resized = img.resize((int(x), int(y)), Image.ANTIALIAS) - resized.save(filename, 'JPEG', quality=quality, optimize=True) - else: - img.save(filename) - else: - #image portrait - new_height = max_height - #check to make sure we aren't upsizing - if cur_height > new_height: - ratio = float(new_height)/cur_height - x = (cur_width * ratio) - y = (cur_height * ratio) - resized = img.resize((int(x), int(y)), Image.ANTIALIAS) - resized.save(filename, 'JPEG', quality=quality, optimize=True) - else: - img.save(filename) - photo.slideshowimage_width = photo.get_width - photo.slideshowimage_height = photo.get_height - photo.slideshowimage_margintop = photo.get_margin_top - photo.slideshowimage_marginleft = photo.get_margin_left - photo.save() - #now resize the local copy - - - -def make_local_copies(photo): - orig_dir = settings.IMAGES_ROOT + '/flickr/full/'+ photo.pub_date.strftime("%Y") - if not os.path.isdir(orig_dir): - os.makedirs(orig_dir) - full = photo.get_original_url() - fname = urllib.urlopen(full) - im = cStringIO.StringIO(fname.read()) # constructs a StringIO holding the image - img = Image.open(im) - local_full = '%s/%s.jpg' %(orig_dir, photo.flickr_id) - img.save(local_full) - #save large size - large_dir = settings.IMAGES_ROOT + '/flickr/large/'+ photo.pub_date.strftime("%Y") - if not os.path.isdir(large_dir): - os.makedirs(large_dir) - large = photo.get_large_url() - fname = urllib.urlopen(large) - im = cStringIO.StringIO(fname.read()) # constructs a StringIO holding the image - img = Image.open(im) - local_large = '%s/%s.jpg' %(large_dir, photo.flickr_id) - if img.format == 'JPEG': - img.save(local_large) - #save medium size - med_dir = settings.IMAGES_ROOT + '/flickr/med/'+ photo.pub_date.strftime("%Y") - if not os.path.isdir(med_dir): - os.makedirs(med_dir) - med = photo.get_medium_url() - fname = urllib.urlopen(med) - im = cStringIO.StringIO(fname.read()) # constructs a StringIO holding the image - img = Image.open(im) - local_med = '%s/%s.jpg' %(med_dir, photo.flickr_id) - img.save(local_med) - -def make_gallery_thumb(photo,set): - crop_dir = settings.IMAGES_ROOT + '/gallery_thumbs/' - if not os.path.isdir(crop_dir): - os.makedirs(crop_dir) - remote = photo.get_original_url() - print(remote) - fname = urllib.urlopen(remote) - im = cStringIO.StringIO(fname.read()) # constructs a StringIO holding the image - img = Image.open(im) - - #calculate crop: - cur_width, cur_height = img.size - new_width, new_height = 291, 350 - ratio = max(float(new_width)/cur_width,float(new_height)/cur_height) - x = (cur_width * ratio) - y = (cur_height * ratio) - xd = abs(new_width - x) - yd = abs(new_height - y) - x_diff = int(xd / 2) - y_diff = int(yd / 2) - box = (int(x_diff), int(y_diff), int(x_diff+new_width), int(y_diff+new_height)) - - #create resized file - resized = img.resize((int(x), int(y)), Image.ANTIALIAS).crop(box) - # save resized file - resized_filename = '%s/%s.jpg' %(crop_dir, set.id) - try: - if img.format == 'JPEG': - resized.save(resized_filename, 'JPEG', quality=95, optimize=True) - else: - resized.save(resized_filename) - except IOError, e: - if os.path.isfile(resized_filename): - os.unlink(resized_filename) - raise e - #os.unlink(img) - - - diff --git a/app/photos/static/image-preview.js b/app/photos/static/image-preview.js deleted file mode 100644 index b8fead5..0000000 --- a/app/photos/static/image-preview.js +++ /dev/null @@ -1,42 +0,0 @@ -function build_image_preview () { - var url = window.location.href - var cur = url.split('/')[6]; - if (cur) { - var container = document.createElement("div"); - container.className = "form-row field-image"; - var wrapper = document.createElement("div"); - var label = document.createElement("label"); - label.textContent = "Image:"; - var pwrap = document.createElement("p"); - var img = document.createElement("img"); - - var request = new XMLHttpRequest(); - request.open('GET', '/photos/luximage/data/admin/preview/'+cur+'/', true); - request.onload = function() { - if (request.status >= 200 && request.status < 400) { - var data = JSON.parse(request.responseText); - //console.log(data); - img.src = data['url']; - } else { - console.log("server error"); - } - }; - request.onerror = function() { - console.log("error on request"); - }; - request.send(); - pwrap.appendChild(img); - wrapper.appendChild(label); - wrapper.appendChild(pwrap); - container.appendChild(wrapper); - parent = document.getElementById("luximage_form"); - node = parent.children[1].children[0]; - node.parentNode.insertBefore(container, node.previousSibling); - } else { - return; - } -} - -document.addEventListener("DOMContentLoaded", function(event) { - build_image_preview(); -}); diff --git a/app/photos/static/my_styles.css b/app/photos/static/my_styles.css deleted file mode 100644 index d13c8e4..0000000 --- a/app/photos/static/my_styles.css +++ /dev/null @@ -1,40 +0,0 @@ - -/*o.v.*/ - -#id_featured_image { - /*style the "box" in its minimzed state*/ - border:1px solid black; width:230px; overflow:hidden; - height:300px; overflow-y:scroll; - /*animate collapsing the dropdown from open to closed state (v. fast)*/ -} -#id_featured_image input { - /*hide the nasty default radio buttons. like, completely!*/ - position:absolute;top:0;left:0;opacity:0; -} - - -#id_featured_image label { - /*style the labels to look like dropdown options, kinda*/ - color: #000; - display:block; - margin: 2px 2px 2px 10px; - height:102px; - opacity:.6; - background-repeat: no-repeat; -} -#id_featured_image:hover label{ - /*this is how labels render in the "expanded" state. we want to see only the selected radio button in the collapsed menu, and all of them when expanded*/ -} -#id_featured_image label:hover { - opacity:.8; -} -#id_featured_image input:checked + label { - /*tricky! labels immediately following a checked radio button (with our markup they are semantically related) should be fully opaque regardless of hover, and they should always be visible (i.e. even in the collapsed menu*/ - opacity:1 !important; - display:block; - background: #333; -} - -/*pfft, nothing as cool here, just the value trace*/ -#trace {margin:0 0 20px;} -#id_featured_image li:first-child { display: none;} diff --git a/app/photos/sync_photo_sets.py b/app/photos/sync_photo_sets.py deleted file mode 100644 index e31d6e4..0000000 --- a/app/photos/sync_photo_sets.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys -import os -from os.path import dirname, abspath -PROJECT_ROOT = abspath(dirname(dirname(dirname(__file__)))) + '/' -# PROJECT_ROOT = abspath(dirname(dirname(__file__))) -print PROJECT_ROOT -sys.path.append(PROJECT_ROOT) -sys.path.append(PROJECT_ROOT + '/app') -sys.path.append(PROJECT_ROOT + '/app/lib') -sys.path.append(PROJECT_ROOT + '/config') -sys.path.append('/home/luxagraf/apps/venv/bin/python2.7/') -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings.settings' -from photos import retriever -retriever.sync_sets() diff --git a/app/photos/sync_photos.py b/app/photos/sync_photos.py deleted file mode 100644 index 886d221..0000000 --- a/app/photos/sync_photos.py +++ /dev/null @@ -1,13 +0,0 @@ -import sys -import os -from os.path import dirname, abspath -PROJECT_ROOT = abspath(dirname(dirname(dirname(__file__)))) + '/' -# PROJECT_ROOT = abspath(dirname(dirname(__file__))) -sys.path.append(PROJECT_ROOT) -sys.path.append(PROJECT_ROOT + '/app') -sys.path.append(PROJECT_ROOT + '/app/lib') -sys.path.append(PROJECT_ROOT + '/config') -sys.path.append('/home/luxagraf/apps/venv/bin/python2.7/') -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings.settings' -from photos import retriever -retriever.sync_flickr_photos() diff --git a/app/photos/templatetags/__init__.py b/app/photos/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/app/photos/templatetags/__init__.py +++ /dev/null diff --git a/app/photos/templatetags/get_image_by_size.py b/app/photos/templatetags/get_image_by_size.py deleted file mode 100644 index c56c44e..0000000 --- a/app/photos/templatetags/get_image_by_size.py +++ /dev/null @@ -1,8 +0,0 @@ -from django import template - -register = template.Library() - -@register.simple_tag -def get_image_by_size(obj, *args): - method = getattr(obj, "get_image_by_size") - return method(*args) diff --git a/app/photos/templatetags/get_image_width.py b/app/photos/templatetags/get_image_width.py deleted file mode 100644 index ac39184..0000000 --- a/app/photos/templatetags/get_image_width.py +++ /dev/null @@ -1,9 +0,0 @@ -from math import floor -from django import template - -register = template.Library() - -@register.simple_tag -def get_image_width(obj, size, *args): - ratio = floor(int(size)*100/int(obj.height))/100 - return floor(ratio*int(obj.height)) diff --git a/app/photos/templatetags/get_size_by_name.py b/app/photos/templatetags/get_size_by_name.py deleted file mode 100644 index fc64a61..0000000 --- a/app/photos/templatetags/get_size_by_name.py +++ /dev/null @@ -1,8 +0,0 @@ -from django import template - -register = template.Library() - -@register.simple_tag -def get_size_by_name(obj, *args): - method = getattr(obj, "get_size_by_name") - return method(*args) diff --git a/app/photos/urls.py b/app/photos/urls.py deleted file mode 100644 index 6673135..0000000 --- a/app/photos/urls.py +++ /dev/null @@ -1,74 +0,0 @@ -from django.urls import path, re_path -from django.views.generic.base import RedirectView - -from . import views - -app_name = "photos" - -urlpatterns = [ - path( - r'daily/<int:page>', - views.DailyPhotoList.as_view(), - name="daily_photo_list" - ), - path( - r'daily/', - views.DailyPhotoList.as_view(), - {'page': 1}, - name="daily_photo_list" - ), - path( - r'data/(<str:slug>/', - views.photo_json - ), - re_path( - r'data/admin/preview/(?P<pk>\d+)/$', - views.photo_preview_json, - name="admin_image_preview" - ), - re_path( - r'data/admin/tn/(?P<pk>\d+)/$', - views.thumb_preview_json, - name="admin_thumb_preview" - ), - re_path( - r'galleries/private/(?P<slug>[-\w]+)$', - views.PrivateGallery.as_view(), - name="private" - ), - re_path( - r'galleries/private/(?P<page>\d+)/$', - views.PrivateGalleryList.as_view(), - name="private_list" - ), - re_path( - r'galleries/private/$', - RedirectView.as_view(url="/photos/galleries/private/1/", permanent=False) - ), - re_path( - r'galleries/(?P<slug>[-\w]+)$', - views.Gallery.as_view(), - name="private" - ), - re_path( - r'galleries/(?P<page>\d+)/$', - views.GalleryList.as_view(), - name="private_list" - ), - re_path( - r'galleries/$', - RedirectView.as_view(url="/photos/galleries/1/", permanent=False) - ), - re_path( - r'(?P<page>\d+)/$', - views.gallery_list, - ), - re_path( - r'(?P<slug>[-\w]+)/$', - RedirectView.as_view(url="/photos/%(slug)s/1/", permanent=False) - ), - re_path( - r'', - RedirectView.as_view(url="/photos/1/", permanent=False) - ), -] diff --git a/app/photos/utils.py b/app/photos/utils.py deleted file mode 100644 index 84e72f5..0000000 --- a/app/photos/utils.py +++ /dev/null @@ -1,28 +0,0 @@ -import os -import re -import subprocess - -from django.apps import apps -from django.conf import settings - -from PIL import ImageFile -from bs4 import BeautifulSoup -# pip install python-resize-image -from resizeimage import resizeimage - - -def resize_image(img, width=None, height=None, quality=72, base_path="", filename=""): - if width and height: - newimg = resizeimage.resize_cover(img, [width, height]) - if width and not height: - newimg = resizeimage.resize_width(img, width) - if height and not width: - newimg = resizeimage.resize_height(img, height) - if not os.path.isdir(base_path): - os.makedirs(base_path) - path = "%s%s" % (base_path, filename) - ImageFile.MAXBLOCK = img.size[0] * img.size[1] * 4 - newimg.save(path, newimg.format, quality=quality) - subprocess.call(["jpegoptim", "%s" % path]) - - diff --git a/app/photos/views.py b/app/photos/views.py deleted file mode 100644 index 070b40d..0000000 --- a/app/photos/views.py +++ /dev/null @@ -1,137 +0,0 @@ -import json -from django.shortcuts import render -from django.template import RequestContext -from django.http import Http404, HttpResponse -from django.core import serializers - -from .models import Photo, PhotoGallery, LuxGallery, LuxImage -from locations.models import Country, Region - -from utils.views import PaginatedListView -from django.views.generic import ListView -from django.views.generic.detail import DetailView - - -class PrivateGallery(DetailView): - model = LuxGallery - slug_field = "slug" - template_name = "details/photo_gallery.html" - - -class PrivateGalleryList(PaginatedListView): - template_name = 'archives/gallery_list.html' - - def get_queryset(self): - return LuxGallery.objects.filter(is_public=False) - - def get_context_data(self, **kwargs): - # Call the base implementation first to get a context - context = super(PrivateGalleryList, self).get_context_data(**kwargs) - context['is_private'] = True - return context - - -class Gallery(DetailView): - model = LuxGallery - slug_field = "slug" - template_name = "details/photo_gallery.html" - - -class GalleryList(PaginatedListView): - template_name = 'archives/gallery_list.html' - - def get_queryset(self): - return LuxGallery.objects.filter(is_public=True) - - def get_context_data(self, **kwargs): - # Call the base implementation first to get a context - context = super(GalleryList, self).get_context_data(**kwargs) - context['is_private'] = False - return context - - -class OldGalleryList(PaginatedListView): - template_name = 'archives/gallery_list.html' - model = PhotoGallery - - def get_queryset(self): - return PhotoGallery.objects.filter(is_public=True) - - def get_context_data(self, **kwargs): - # Call the base implementation first to get a context - context = super(OldGalleryList, self).get_context_data(**kwargs) - return context - - -class DailyPhotoList(PaginatedListView): - model=LuxImage - template_name = 'archives/photo_daily_list.html' - - def get_queryset(self): - return LuxImage.objects.filter(is_public=True, title__startswith="daily_") - - def get_context_data(self, **kwargs): - # Call the base implementation first to get a context - context = super(DailyPhotoList, self).get_context_data(**kwargs) - context['breadcrumbs'] = ['daily',] - return context - - -def gallery_list(request, page): - request.page_url = '/photos/%d/' - request.page = int(page) - context = { - 'object_list': PhotoGallery.objects.all(), - 'page': page, - } - return render(request, "archives/photos.html", context) - - -def gallery(request, slug): - context = { - 'object': PhotoGallery.objects.get(set_slug=slug) - } - return render(request, 'details/photo_galleries.html', context) - - -def photo_json(request, slug): - p = PhotoGallery.objects.filter(set_slug=slug) - return HttpResponse(serializers.serialize('json', p), mimetype='application/json') - - -def photo_preview_json(request, pk): - p = LuxImage.objects.get(pk=pk) - data = {} - data['url'] = p.get_admin_image() - data = json.dumps(data) - return HttpResponse(data) - - -def thumb_preview_json(request, pk): - p = LuxImage.objects.get(pk=pk) - data = {} - data['url'] = p.get_admin_insert() - data = json.dumps(data) - return HttpResponse(data) - - -def gallery_list_by_area(request, slug, page): - """Grabs entries by region or country""" - request.page_url = '/photos/' + slug + '/%d/' - request.page = int(page) - try: - region = Region.objects.get(slug__exact=slug) - qs = PhotoGallery.objects.filter(region=region).order_by('-id') - except: - region = Country.objects.get(slug__exact=slug) - qs = PhotoGallery.objects.filter(location__state__country=region).order_by('-id') - if not region: - raise Http404 - context = { - 'object_list': qs, - 'country_list': Country.objects.filter(visited=True), - 'region_list': Region.objects.all(), - 'region': region, - 'page': page - } - return render(request, "archives/photos.html", context) |