diff options
Diffstat (limited to 'app/photos')
-rw-r--r-- | app/photos/admin.py | 108 | ||||
-rw-r--r-- | app/photos/detail_urls.py | 7 | ||||
-rw-r--r-- | app/photos/models.py | 131 | ||||
-rw-r--r-- | app/photos/retriever.py | 231 | ||||
-rw-r--r-- | app/photos/retriever.py.bak | 314 | ||||
-rw-r--r-- | app/photos/sync_photo_sets.py | 13 | ||||
-rw-r--r-- | app/photos/sync_photos.py | 13 | ||||
-rw-r--r-- | app/photos/views.py | 43 |
8 files changed, 597 insertions, 263 deletions
diff --git a/app/photos/admin.py b/app/photos/admin.py index 29f5dbf..241401a 100644 --- a/app/photos/admin.py +++ b/app/photos/admin.py @@ -1,67 +1,77 @@ from django.contrib import admin from django.contrib.gis.admin import OSMGeoAdmin -from django.contrib.gis.maps.google import GoogleMap -from django.conf import settings +from photos.models import Photo, PhotoGallery -from photos.models import Photo,PhotoGallery - -GMAP = GoogleMap(key=settings.GOOGLE_MAPS_API_KEY) class PhotoAdmin(OSMGeoAdmin): - list_display = ('title','admin_thumbnail', 'flickr_id', 'pub_date',) + list_display = ('title', 'admin_thumbnail', 'flickr_id', 'pub_date',) list_filter = ('pub_date',) search_fields = ['title', 'description'] fieldsets = ( - (None, {'fields': (('title', 'description'),'pub_date', 'tags',('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')}), + (None, { + 'fields': ( + ('title', 'description'), + 'pub_date', + 'tags', + ('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') + }), ) - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - # Default GeoDjango OpenLayers map options - # Uncomment and modify as desired - # To learn more about this jargon visit: - # www.openlayers.org - - #default_lon = 0 - #default_lat = 0 - #default_zoom = 4 - #display_wkt = False - #display_srid = False - #extra_js = [] - #num_zoom = 18 - #max_zoom = False - #min_zoom = False - #units = False - #max_resolution = False - #max_extent = False - #modifiable = True - #mouse_position = True - #scale_text = True - #layerswitcher = True + + # Options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 + default_zoom = 6 + units = True scrollable = False - #admin_media_prefix = settings.ADMIN_MEDIA_PREFIX map_width = 700 - map_height = 325 - #map_srid = 4326 - #map_template = 'gis/admin/openlayers.html' - #openlayers_url = 'http://openlayers.org/api/2.6/OpenLayers.js' - #wms_url = 'http://labs.metacarta.com/wms/vmap0' - #wms_layer = 'basic' - #wms_name = 'OpenLayers WMS' - #debug = False - #widget = OpenLayersWidget + map_height = 425 + map_template = 'gis/admin/osm.html' + admin.site.register(Photo, PhotoAdmin) class PhotoGalleryAdmin(OSMGeoAdmin): - list_display = ('set_title','region','location','pub_date') - list_filter = ('region','location') + 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')}), + (None, { + 'fields': ( + ('set_id', 'set_title', 'set_desc'), + 'set_slug', + 'primary', + 'location', + 'region', + 'photos', + 'pub_date' + ) + }), ) - - - -admin.site.register(PhotoGallery, PhotoGalleryAdmin)
\ No newline at end of file + + +admin.site.register(PhotoGallery, PhotoGalleryAdmin) diff --git a/app/photos/detail_urls.py b/app/photos/detail_urls.py index 7619220..8bdbd79 100644 --- a/app/photos/detail_urls.py +++ b/app/photos/detail_urls.py @@ -1,12 +1,7 @@ from django.conf.urls import * -from django.views.generic.base import RedirectView from django.views.generic.detail import DetailView from photos.models import Photo -detail_dict = { - 'queryset': Photo.objects.all(), -} - urlpatterns = patterns('', - (r'^(?P<object_id>\d+)/$', DetailView.as_view(model=Photo,template_name='details/photo.html')), + (r'^(?P<object_id>\d+)/$', DetailView.as_view(model=Photo, template_name='details/photo.html')), ) diff --git a/app/photos/models.py b/app/photos/models.py index 7daae94..9916085 100644 --- a/app/photos/models.py +++ b/app/photos/models.py @@ -1,16 +1,15 @@ +import os.path import datetime from PIL import Image -import os.path + from django.contrib.gis.db import models from django.contrib.sitemaps import Sitemap -from django.contrib.syndication.views import Feed from django.utils.encoding import force_text from django.conf import settings +from taggit.managers import TaggableManager +from locations.models import Location, Region -from taggit.managers import TaggableManager - -from locations.models import Location,Region class Photo(models.Model): description = models.TextField(blank=True, null=True) @@ -26,14 +25,15 @@ class Photo(models.Model): exif_lens = models.CharField(max_length=50, blank=True, null=True) exif_date = models.DateTimeField() """Flickr Specific Stuff""" - flickr_id = models.CharField(max_length=300) #varchar since Flickr ids are larger than than integerfield can handle and BigIntegerField gets weird in Postgres. + # 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) + 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(Location, null=True) region = models.ForeignKey(Region, null=True) slideshowimage_width = models.CharField(max_length=4, blank=True, null=True) @@ -42,89 +42,96 @@ class Photo(models.Model): 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())) + 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) - + return '%sflickr/med/%s/%s.jpg' % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), self.flickr_id) + def get_local_orig_url(self): - return '%sflickr/full/%s/%s.jpg' %(settings.IMAGES_URL,self.pub_date.strftime("%Y"),self.flickr_id) - + return '%sflickr/full/%s/%s.jpg' % (settings.IMAGES_URL, 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 __unicode__(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) - + 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)) + 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)) + 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)) + im = Image.open('%s/slideshow/%s/%s.jpg' % (settings.IMAGES_ROOT, + self.pub_date.strftime("%Y"), self.flickr_id)) xsize, ysize = im.size - cal = xsize-120 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)) + 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) + 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)) + 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) + mtop = 500 - (xsize / 2) return mtop - + @property def flickr_link(self): - return '%s%s/' %('http://www.flickr.com/photos/luxagraf/', self.flickr_id) - + 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 @@ -132,41 +139,39 @@ class Photo(models.Model): # 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 - + size_char = 's' # default to small_square if size == 'small_square': - size_char='_s' + size_char = '_s' elif size == 'thumb': - size_char='_t' + size_char = '_t' elif size == 'small': - size_char='_m' + size_char = '_m' elif size == 'medium': - size_char='' + size_char = '' elif size == 'large': - size_char='_b' + size_char = '_b' elif size == 'original': - size_char='_o' - + 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) + 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) @@ -177,23 +182,22 @@ class PhotoGallery(models.Model): location = models.ForeignKey(Location, null=True) region = models.ForeignKey(Region, null=True) pub_date = models.DateTimeField(null=True) - + class Meta: - ordering = ('-pub_date','id') + ordering = ('-pub_date', 'id') verbose_name_plural = 'Photo Galleries' get_latest_by = 'pub_date' - - def __unicode__(self): + 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 @@ -203,4 +207,3 @@ class PhotoGallerySitemap(Sitemap): def lastmod(self, obj): return obj.pub_date - diff --git a/app/photos/retriever.py b/app/photos/retriever.py index 4dfbc49..1a0757e 100644 --- a/app/photos/retriever.py +++ b/app/photos/retriever.py @@ -1,88 +1,90 @@ -from __future__ import division import datetime import os -import cStringIO # *much* faster than StringIO -import urllib +import io +import urllib.request +import urllib.parse +import urllib.error - -from django.contrib.contenttypes.models import ContentType from django.template.defaultfilters import slugify from django.core.exceptions import ObjectDoesNotExist -from django.utils.encoding import force_unicode,smart_unicode +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 + # Required PIL classes may or may not be available from the root namespace # depending on the installation try: import Image import ImageFile - import ImageFilter - import ImageEnhance except ImportError: try: from PIL import Image from PIL import ImageFile - from PIL import ImageFilter - from PIL import ImageEnhance except ImportError: raise ImportError("Could not import the Python Imaging Library.") - -ImageFile.MAXBLOCK = 1000000 -from utils.strutils import safestr -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 +ImageFile.MAXBLOCK = 1000000 +EXIF_PARAMS = { + "FNumber": 'f/2.8', + "Make": 'Apple', + "Model": 'iPhone', + "ExposureTime": '', + "ISO": '', + "FocalLength": '', + "LensModel": '', + 'DateTimeOriginal': '2013:09:03 22:44:25' +} -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_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 = 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']) - # If the row exists already, set the dupe flag - dupe = True - print 'already have '+info['id']+' moving on' + 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'])) + 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, + 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']: @@ -92,53 +94,63 @@ def get_photo(photo): #retina image: #slideshow_image(p, 2000, 1600, 75) #normal image - print p.title + 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) + +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 = 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'] + 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...') + 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'])) + except ObjectDoesNotExist: + s = PhotoGallery.objects.create( + set_id=force_text(photoset['id']), + set_title=force_text(photoset['title']), + set_desc=force_text(photoset['description']), + set_slug=slugify(force_text(photoset['title'])), + 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) - + 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 == True: + if p.is_public: photoset.photos.add(p) slideshow_image(p, 1000, 800, 95) - + ################################################ ## Various meta data and geo helper functions ## ################################################ @@ -151,19 +163,20 @@ def exif_handler(data): converted[t['tag']] = t['raw'] except: pass - for k,v in EXIF_PARAMS.items(): - if not converted.has_key(k): + for k, v in list(EXIF_PARAMS.items()): + if k not in converted: 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): + +def get_geo(lat, lon): from locations.models import Location, Region from django.contrib.gis.geos import Point pnt_wkt = Point(lon, lat) @@ -177,24 +190,26 @@ def get_geo(lat,lon): 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") + +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) + filename = '%s/%sx2.jpg' % (slide_dir, photo.flickr_id) else: - filename = '%s/%s.jpg' %(slide_dir, photo.flickr_id) - + 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 + fname = urllib.request.urlopen(flickr_photo) + im = io.StringIO(fname.read()) # constructs a StringIO holding the image img = Image.open(im) cur_width, cur_height = img.size #if image landscape @@ -202,19 +217,19 @@ def slideshow_image(photo,max_width, max_height, quality): new_width = max_width #check to make sure we aren't upsizing if cur_width > new_width: - ratio = float(new_width)/cur_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: + 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 + ratio = float(new_height) / cur_height x = (cur_width * ratio) y = (cur_height * ratio) resized = img.resize((int(x), int(y)), Image.ANTIALIAS) @@ -227,77 +242,73 @@ def slideshow_image(photo,max_width, max_height, quality): 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") + 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 + fname = urllib.request.urlopen(full) + im = io.StringIO(fname.read()) # constructs a StringIO holding the image img = Image.open(im) - local_full = '%s/%s.jpg' %(orig_dir, photo.flickr_id) + 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") + 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 + fname = urllib.request.urlopen(large) + im = io.StringIO(fname.read()) # constructs a StringIO holding the image img = Image.open(im) - local_large = '%s/%s.jpg' %(large_dir, photo.flickr_id) + 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") + 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 + fname = urllib.request.urlopen(med) + im = io.StringIO(fname.read()) # constructs a StringIO holding the image img = Image.open(im) - local_med = '%s/%s.jpg' %(med_dir, photo.flickr_id) + local_med = '%s/%s.jpg' % (med_dir, photo.flickr_id) img.save(local_med) - -def make_gallery_thumb(photo,set): + + +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 + print(remote) + fname = urllib.request.urlopen(remote) + im = io.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) + 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 + 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) + 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: + except IOError as e: if os.path.isfile(resized_filename): os.unlink(resized_filename) raise e - #os.unlink(img) - - - + # os.unlink(img) diff --git a/app/photos/retriever.py.bak b/app/photos/retriever.py.bak new file mode 100644 index 0000000..d3c572a --- /dev/null +++ b/app/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/app/photos/sync_photo_sets.py b/app/photos/sync_photo_sets.py index beac435..e31d6e4 100644 --- a/app/photos/sync_photo_sets.py +++ b/app/photos/sync_photo_sets.py @@ -1,12 +1,13 @@ -import sys, os +import sys +import os from os.path import dirname, abspath -PROJECT_ROOT = abspath(dirname(dirname(dirname(__file__))))+'/' -#PROJECT_ROOT = abspath(dirname(dirname(__file__))) +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(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 diff --git a/app/photos/sync_photos.py b/app/photos/sync_photos.py index 634a2fc..886d221 100644 --- a/app/photos/sync_photos.py +++ b/app/photos/sync_photos.py @@ -1,11 +1,12 @@ -import sys, os +import sys +import os from os.path import dirname, abspath -PROJECT_ROOT = abspath(dirname(dirname(dirname(__file__))))+'/' -#PROJECT_ROOT = abspath(dirname(dirname(__file__))) +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(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 diff --git a/app/photos/views.py b/app/photos/views.py index 0c413e0..567f329 100644 --- a/app/photos/views.py +++ b/app/photos/views.py @@ -1,45 +1,44 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response from django.template import RequestContext -from django.http import Http404,HttpResponse +from django.http import Http404, HttpResponse from django.core import serializers - -from photos.models import Photo,PhotoGallery +from photos.models import Photo, PhotoGallery from locations.models import Country, Region - - - -def gallery_list(request,page): + + +def gallery_list(request, page): request.page_url = '/photos/%d/' request.page = int(page) context = { 'object_list': PhotoGallery.objects.all(), - 'page':page, - } - return render_to_response("archives/photos.html", context, context_instance = RequestContext(request)) + 'page': page, + } + return render_to_response("archives/photos.html", context, context_instance=RequestContext(request)) -def gallery(request,slug): + +def gallery(request, slug): context = { 'object': PhotoGallery.objects.get(set_slug=slug) - } - return render_to_response('details/photo_galleries.html', context, context_instance = RequestContext(request)) + } + return render_to_response('details/photo_galleries.html', context, context_instance=RequestContext(request)) + def photo_json(request, slug): p = PhotoGallery.objects.filter(set_slug=slug) return HttpResponse(serializers.serialize('json', p), mimetype='application/json') -""" -Grabs entries by region or country -""" -def gallery_list_by_area(request,slug,page): - request.page_url = '/photos/'+slug+'/%d/' + +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') + 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') + qs = PhotoGallery.objects.filter(location__state__country=region).order_by('-id') if not region: raise Http404 context = { @@ -49,4 +48,4 @@ def gallery_list_by_area(request,slug,page): 'region': region, 'page': page } - return render_to_response("archives/photos.html", context, context_instance = RequestContext(request)) + return render_to_response("archives/photos.html", context, context_instance=RequestContext(request)) |