summaryrefslogtreecommitdiff
path: root/bak/unused_apps/photos
diff options
context:
space:
mode:
Diffstat (limited to 'bak/unused_apps/photos')
-rw-r--r--bak/unused_apps/photos/__init__.py0
-rw-r--r--bak/unused_apps/photos/admin.py184
-rw-r--r--bak/unused_apps/photos/build.py48
-rw-r--r--bak/unused_apps/photos/detail_urls.py10
-rw-r--r--bak/unused_apps/photos/flickrauth2
-rw-r--r--bak/unused_apps/photos/forms.py179
-rw-r--r--bak/unused_apps/photos/migrations/0001_initial.py137
-rw-r--r--bak/unused_apps/photos/migrations/0002_auto_20151216_1958.py26
-rw-r--r--bak/unused_apps/photos/migrations/0003_luxgallery_caption_style.py20
-rw-r--r--bak/unused_apps/photos/migrations/0004_luximage_alt.py20
-rw-r--r--bak/unused_apps/photos/migrations/0005_auto_20160318_1244.py25
-rw-r--r--bak/unused_apps/photos/migrations/0006_auto_20160318_2047.py30
-rw-r--r--bak/unused_apps/photos/migrations/0007_auto_20160320_0802.py20
-rw-r--r--bak/unused_apps/photos/migrations/0008_luximagesize_quality.py21
-rw-r--r--bak/unused_apps/photos/migrations/0009_auto_20160320_0907.py20
-rw-r--r--bak/unused_apps/photos/migrations/0010_auto_20160517_0906.py30
-rw-r--r--bak/unused_apps/photos/migrations/0011_luximagesize_name.py20
-rw-r--r--bak/unused_apps/photos/migrations/0012_luximagesize_is_portrait.py20
-rw-r--r--bak/unused_apps/photos/migrations/0013_auto_20161022_1348.py20
-rw-r--r--bak/unused_apps/photos/migrations/0014_remove_luximagesize_is_portrait.py19
-rw-r--r--bak/unused_apps/photos/migrations/0015_auto_20161022_1411.py20
-rw-r--r--bak/unused_apps/photos/migrations/0016_auto_20161022_1411.py25
-rw-r--r--bak/unused_apps/photos/migrations/0017_auto_20161130_1218.py38
-rw-r--r--bak/unused_apps/photos/migrations/0018_auto_20161130_1218.py29
-rw-r--r--bak/unused_apps/photos/migrations/0019_auto_20190704_0903.py17
-rw-r--r--bak/unused_apps/photos/migrations/0020_auto_20201201_2116.py20
-rw-r--r--bak/unused_apps/photos/migrations/0021_auto_20201201_2118.py18
-rw-r--r--bak/unused_apps/photos/migrations/__init__.py0
-rw-r--r--bak/unused_apps/photos/models.py555
-rw-r--r--bak/unused_apps/photos/photos.js71
-rw-r--r--bak/unused_apps/photos/readexif.py78
-rw-r--r--bak/unused_apps/photos/resize.py53
-rw-r--r--bak/unused_apps/photos/retriever.py323
-rw-r--r--bak/unused_apps/photos/retriever.py.bak314
-rw-r--r--bak/unused_apps/photos/static/image-preview.js42
-rw-r--r--bak/unused_apps/photos/static/my_styles.css1
-rw-r--r--bak/unused_apps/photos/static/my_styles.uncompressed.css40
-rw-r--r--bak/unused_apps/photos/sync_photo_sets.py14
-rw-r--r--bak/unused_apps/photos/sync_photos.py13
-rw-r--r--bak/unused_apps/photos/templatetags/__init__.py0
-rw-r--r--bak/unused_apps/photos/templatetags/get_image_by_size.py8
-rw-r--r--bak/unused_apps/photos/templatetags/get_image_width.py9
-rw-r--r--bak/unused_apps/photos/templatetags/get_size_by_name.py8
-rw-r--r--bak/unused_apps/photos/urls.py74
-rw-r--r--bak/unused_apps/photos/utils.py28
-rw-r--r--bak/unused_apps/photos/views.py137
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 &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Tiles &copy; 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)