diff options
Diffstat (limited to 'bak/unused_apps/photos')
46 files changed, 2786 insertions, 0 deletions
diff --git a/bak/unused_apps/photos/__init__.py b/bak/unused_apps/photos/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bak/unused_apps/photos/__init__.py diff --git a/bak/unused_apps/photos/admin.py b/bak/unused_apps/photos/admin.py new file mode 100644 index 0000000..e77e50b --- /dev/null +++ b/bak/unused_apps/photos/admin.py @@ -0,0 +1,184 @@ +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/bak/unused_apps/photos/build.py b/bak/unused_apps/photos/build.py new file mode 100644 index 0000000..e95cbfc --- /dev/null +++ b/bak/unused_apps/photos/build.py @@ -0,0 +1,48 @@ +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/bak/unused_apps/photos/detail_urls.py b/bak/unused_apps/photos/detail_urls.py new file mode 100644 index 0000000..0ab94f6 --- /dev/null +++ b/bak/unused_apps/photos/detail_urls.py @@ -0,0 +1,10 @@ +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/bak/unused_apps/photos/flickrauth b/bak/unused_apps/photos/flickrauth new file mode 100644 index 0000000..0fe7407 --- /dev/null +++ b/bak/unused_apps/photos/flickrauth @@ -0,0 +1,2 @@ +72157629224829547-04c4f099c2550cd8 +812f6c53e5b122f4
\ No newline at end of file diff --git a/bak/unused_apps/photos/forms.py b/bak/unused_apps/photos/forms.py new file mode 100644 index 0000000..6ee7bde --- /dev/null +++ b/bak/unused_apps/photos/forms.py @@ -0,0 +1,179 @@ +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/bak/unused_apps/photos/migrations/0001_initial.py b/bak/unused_apps/photos/migrations/0001_initial.py new file mode 100644 index 0000000..711af1d --- /dev/null +++ b/bak/unused_apps/photos/migrations/0001_initial.py @@ -0,0 +1,137 @@ +# -*- 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/bak/unused_apps/photos/migrations/0002_auto_20151216_1958.py b/bak/unused_apps/photos/migrations/0002_auto_20151216_1958.py new file mode 100644 index 0000000..2a2bffb --- /dev/null +++ b/bak/unused_apps/photos/migrations/0002_auto_20151216_1958.py @@ -0,0 +1,26 @@ +# -*- 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/bak/unused_apps/photos/migrations/0003_luxgallery_caption_style.py b/bak/unused_apps/photos/migrations/0003_luxgallery_caption_style.py new file mode 100644 index 0000000..b46f970 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0003_luxgallery_caption_style.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0004_luximage_alt.py b/bak/unused_apps/photos/migrations/0004_luximage_alt.py new file mode 100644 index 0000000..ecbaf56 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0004_luximage_alt.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0005_auto_20160318_1244.py b/bak/unused_apps/photos/migrations/0005_auto_20160318_1244.py new file mode 100644 index 0000000..584714e --- /dev/null +++ b/bak/unused_apps/photos/migrations/0005_auto_20160318_1244.py @@ -0,0 +1,25 @@ +# -*- 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/bak/unused_apps/photos/migrations/0006_auto_20160318_2047.py b/bak/unused_apps/photos/migrations/0006_auto_20160318_2047.py new file mode 100644 index 0000000..7cf0a4f --- /dev/null +++ b/bak/unused_apps/photos/migrations/0006_auto_20160318_2047.py @@ -0,0 +1,30 @@ +# -*- 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/bak/unused_apps/photos/migrations/0007_auto_20160320_0802.py b/bak/unused_apps/photos/migrations/0007_auto_20160320_0802.py new file mode 100644 index 0000000..474bd42 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0007_auto_20160320_0802.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0008_luximagesize_quality.py b/bak/unused_apps/photos/migrations/0008_luximagesize_quality.py new file mode 100644 index 0000000..06dc0cc --- /dev/null +++ b/bak/unused_apps/photos/migrations/0008_luximagesize_quality.py @@ -0,0 +1,21 @@ +# -*- 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/bak/unused_apps/photos/migrations/0009_auto_20160320_0907.py b/bak/unused_apps/photos/migrations/0009_auto_20160320_0907.py new file mode 100644 index 0000000..ccfebf5 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0009_auto_20160320_0907.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0010_auto_20160517_0906.py b/bak/unused_apps/photos/migrations/0010_auto_20160517_0906.py new file mode 100644 index 0000000..0adf4ff --- /dev/null +++ b/bak/unused_apps/photos/migrations/0010_auto_20160517_0906.py @@ -0,0 +1,30 @@ +# -*- 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/bak/unused_apps/photos/migrations/0011_luximagesize_name.py b/bak/unused_apps/photos/migrations/0011_luximagesize_name.py new file mode 100644 index 0000000..49d046b --- /dev/null +++ b/bak/unused_apps/photos/migrations/0011_luximagesize_name.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0012_luximagesize_is_portrait.py b/bak/unused_apps/photos/migrations/0012_luximagesize_is_portrait.py new file mode 100644 index 0000000..a2c2e3a --- /dev/null +++ b/bak/unused_apps/photos/migrations/0012_luximagesize_is_portrait.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0013_auto_20161022_1348.py b/bak/unused_apps/photos/migrations/0013_auto_20161022_1348.py new file mode 100644 index 0000000..8dfbf98 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0013_auto_20161022_1348.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0014_remove_luximagesize_is_portrait.py b/bak/unused_apps/photos/migrations/0014_remove_luximagesize_is_portrait.py new file mode 100644 index 0000000..b8e0aa8 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0014_remove_luximagesize_is_portrait.py @@ -0,0 +1,19 @@ +# -*- 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/bak/unused_apps/photos/migrations/0015_auto_20161022_1411.py b/bak/unused_apps/photos/migrations/0015_auto_20161022_1411.py new file mode 100644 index 0000000..d380b52 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0015_auto_20161022_1411.py @@ -0,0 +1,20 @@ +# -*- 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/bak/unused_apps/photos/migrations/0016_auto_20161022_1411.py b/bak/unused_apps/photos/migrations/0016_auto_20161022_1411.py new file mode 100644 index 0000000..54b84d7 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0016_auto_20161022_1411.py @@ -0,0 +1,25 @@ +# -*- 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/bak/unused_apps/photos/migrations/0017_auto_20161130_1218.py b/bak/unused_apps/photos/migrations/0017_auto_20161130_1218.py new file mode 100644 index 0000000..8d5a496 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0017_auto_20161130_1218.py @@ -0,0 +1,38 @@ +# -*- 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/bak/unused_apps/photos/migrations/0018_auto_20161130_1218.py b/bak/unused_apps/photos/migrations/0018_auto_20161130_1218.py new file mode 100644 index 0000000..784175a --- /dev/null +++ b/bak/unused_apps/photos/migrations/0018_auto_20161130_1218.py @@ -0,0 +1,29 @@ +# -*- 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/bak/unused_apps/photos/migrations/0019_auto_20190704_0903.py b/bak/unused_apps/photos/migrations/0019_auto_20190704_0903.py new file mode 100644 index 0000000..833ee69 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0019_auto_20190704_0903.py @@ -0,0 +1,17 @@ +# 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/bak/unused_apps/photos/migrations/0020_auto_20201201_2116.py b/bak/unused_apps/photos/migrations/0020_auto_20201201_2116.py new file mode 100644 index 0000000..39d4fd9 --- /dev/null +++ b/bak/unused_apps/photos/migrations/0020_auto_20201201_2116.py @@ -0,0 +1,20 @@ +# 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/bak/unused_apps/photos/migrations/0021_auto_20201201_2118.py b/bak/unused_apps/photos/migrations/0021_auto_20201201_2118.py new file mode 100644 index 0000000..25e4f8f --- /dev/null +++ b/bak/unused_apps/photos/migrations/0021_auto_20201201_2118.py @@ -0,0 +1,18 @@ +# 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/bak/unused_apps/photos/migrations/__init__.py b/bak/unused_apps/photos/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bak/unused_apps/photos/migrations/__init__.py diff --git a/bak/unused_apps/photos/models.py b/bak/unused_apps/photos/models.py new file mode 100644 index 0000000..24a218f --- /dev/null +++ b/bak/unused_apps/photos/models.py @@ -0,0 +1,555 @@ +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/bak/unused_apps/photos/photos.js b/bak/unused_apps/photos/photos.js new file mode 100644 index 0000000..b93467a --- /dev/null +++ b/bak/unused_apps/photos/photos.js @@ -0,0 +1,71 @@ +//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/bak/unused_apps/photos/readexif.py b/bak/unused_apps/photos/readexif.py new file mode 100644 index 0000000..70a6987 --- /dev/null +++ b/bak/unused_apps/photos/readexif.py @@ -0,0 +1,78 @@ +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/bak/unused_apps/photos/resize.py b/bak/unused_apps/photos/resize.py new file mode 100644 index 0000000..13c0151 --- /dev/null +++ b/bak/unused_apps/photos/resize.py @@ -0,0 +1,53 @@ +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/bak/unused_apps/photos/retriever.py b/bak/unused_apps/photos/retriever.py new file mode 100644 index 0000000..f5cae68 --- /dev/null +++ b/bak/unused_apps/photos/retriever.py @@ -0,0 +1,323 @@ +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/bak/unused_apps/photos/retriever.py.bak b/bak/unused_apps/photos/retriever.py.bak new file mode 100644 index 0000000..d3c572a --- /dev/null +++ b/bak/unused_apps/photos/retriever.py.bak @@ -0,0 +1,314 @@ +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/bak/unused_apps/photos/static/image-preview.js b/bak/unused_apps/photos/static/image-preview.js new file mode 100644 index 0000000..b8fead5 --- /dev/null +++ b/bak/unused_apps/photos/static/image-preview.js @@ -0,0 +1,42 @@ +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/bak/unused_apps/photos/static/my_styles.css b/bak/unused_apps/photos/static/my_styles.css new file mode 100644 index 0000000..65005c8 --- /dev/null +++ b/bak/unused_apps/photos/static/my_styles.css @@ -0,0 +1 @@ + #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;}#trace {margin:0 0 20px;}#id_featured_image li:first-child {display:none;}
\ No newline at end of file diff --git a/bak/unused_apps/photos/static/my_styles.uncompressed.css b/bak/unused_apps/photos/static/my_styles.uncompressed.css new file mode 100644 index 0000000..d13c8e4 --- /dev/null +++ b/bak/unused_apps/photos/static/my_styles.uncompressed.css @@ -0,0 +1,40 @@ + +/*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/bak/unused_apps/photos/sync_photo_sets.py b/bak/unused_apps/photos/sync_photo_sets.py new file mode 100644 index 0000000..e31d6e4 --- /dev/null +++ b/bak/unused_apps/photos/sync_photo_sets.py @@ -0,0 +1,14 @@ +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/bak/unused_apps/photos/sync_photos.py b/bak/unused_apps/photos/sync_photos.py new file mode 100644 index 0000000..886d221 --- /dev/null +++ b/bak/unused_apps/photos/sync_photos.py @@ -0,0 +1,13 @@ +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/bak/unused_apps/photos/templatetags/__init__.py b/bak/unused_apps/photos/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/bak/unused_apps/photos/templatetags/__init__.py diff --git a/bak/unused_apps/photos/templatetags/get_image_by_size.py b/bak/unused_apps/photos/templatetags/get_image_by_size.py new file mode 100644 index 0000000..c56c44e --- /dev/null +++ b/bak/unused_apps/photos/templatetags/get_image_by_size.py @@ -0,0 +1,8 @@ +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/bak/unused_apps/photos/templatetags/get_image_width.py b/bak/unused_apps/photos/templatetags/get_image_width.py new file mode 100644 index 0000000..ac39184 --- /dev/null +++ b/bak/unused_apps/photos/templatetags/get_image_width.py @@ -0,0 +1,9 @@ +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/bak/unused_apps/photos/templatetags/get_size_by_name.py b/bak/unused_apps/photos/templatetags/get_size_by_name.py new file mode 100644 index 0000000..fc64a61 --- /dev/null +++ b/bak/unused_apps/photos/templatetags/get_size_by_name.py @@ -0,0 +1,8 @@ +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/bak/unused_apps/photos/urls.py b/bak/unused_apps/photos/urls.py new file mode 100644 index 0000000..6673135 --- /dev/null +++ b/bak/unused_apps/photos/urls.py @@ -0,0 +1,74 @@ +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/bak/unused_apps/photos/utils.py b/bak/unused_apps/photos/utils.py new file mode 100644 index 0000000..84e72f5 --- /dev/null +++ b/bak/unused_apps/photos/utils.py @@ -0,0 +1,28 @@ +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/bak/unused_apps/photos/views.py b/bak/unused_apps/photos/views.py new file mode 100644 index 0000000..070b40d --- /dev/null +++ b/bak/unused_apps/photos/views.py @@ -0,0 +1,137 @@ +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) |