diff options
author | luxagraf <sng@luxagraf.net> | 2014-05-23 11:28:10 -0400 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2014-05-23 11:28:10 -0400 |
commit | 518b2d618bc10f93cfa44a83715593b8358eb9ce (patch) | |
tree | a07993c3ae31bed42f32c0e00788989568790716 | |
parent | 4bae11bb25a8e3c43118891d17fd8e981ecf8dc6 (diff) |
minor refactor to adoipt pep8 and pyflakes coding styles and clean up
some cruft that's been hangin round for years
48 files changed, 1555 insertions, 1465 deletions
diff --git a/app/birds/aba_importer.py b/app/birds/aba_importer.py index e5df528..93f5bef 100644 --- a/app/birds/aba_importer.py +++ b/app/birds/aba_importer.py @@ -1,17 +1,16 @@ for row_index in range(sheet.nrows): - if sheet.cell(row_index,0).value != '': + if sheet.cell(row_index, 0).value != '': sci = sheet.cell(row_index, 0).value.split("(")[1].split(")")[0] bc = BirdClass.objects.get(scientific_name__exact=sci) common_name = sheet.cell(row_index, 1).value sci_name = sheet.cell(row_index, 2).value code = int(sheet.cell(row_index, 3).value) bclass = bc - #create bird here + # create bird here b, created = Bird.objects.get_or_create( - common_name = common_name, - scientific_name = sci_name, - code = code, - bird_class = bc + common_name=common_name, + scientific_name=sci_name, + code=code, + bird_class=bc ) print(b) - diff --git a/app/birds/admin.py b/app/birds/admin.py index a9d60b0..e40baab 100644 --- a/app/birds/admin.py +++ b/app/birds/admin.py @@ -6,14 +6,15 @@ from birds.models import BirdSighting, BirdClass, Bird class BirdClassAdmin(admin.ModelAdmin): list_display = ('common_name', 'scientific_name',) + class BirdAdmin(admin.ModelAdmin): - list_display = ('pk','common_name', 'scientific_name','code','bird_class') + list_display = ('pk', 'common_name', 'scientific_name', 'code', 'bird_class') class BirdSightingAdmin(OSMGeoAdmin): - list_display = ('bird', 'location',) + list_display = ('bird', 'location') list_filter = ('location',) - #options for OSM map Using custom ESRI topo map + # options for OSM map Using custom ESRI topo map default_lon = -9285175 default_lat = 4025046 default_zoom = 6 @@ -22,6 +23,7 @@ class BirdSightingAdmin(OSMGeoAdmin): map_width = 700 map_height = 425 map_template = 'gis/admin/osm.html' + admin.site.register(BirdSighting, BirdSightingAdmin) admin.site.register(BirdClass, BirdClassAdmin) admin.site.register(Bird, BirdAdmin) diff --git a/app/birds/models.py b/app/birds/models.py index 3dd0add..3fb0c0f 100644 --- a/app/birds/models.py +++ b/app/birds/models.py @@ -2,18 +2,19 @@ import datetime from django.contrib.gis.db import models from locations.models import Location + def get_upload_path(self, filename): - return "images/bird-images/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/bird-images/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) -#from http://aba.org/checklist/codes.html +# from http://aba.org/checklist/codes.html ABA_CODES = ( - (1, 'regular occurring - common'), - (2, 'regular occurring - less common'), - (3, 'rare'), - (4, 'casual'), - (5, 'accidental'), - (6, 'Cannot be found'), - ) + (1, 'regular occurring - common'), + (2, 'regular occurring - less common'), + (3, 'rare'), + (4, 'casual'), + (5, 'accidental'), + (6, 'Cannot be found'), +) class BirdClass(models.Model): @@ -22,10 +23,11 @@ class BirdClass(models.Model): class Meta: verbose_name_plural = 'Bird Class' - + def __str__(self): return self.common_name + class Bird(models.Model): common_name = models.CharField(max_length=200) scientific_name = models.CharField(max_length=200) @@ -34,11 +36,11 @@ class Bird(models.Model): def __str__(self): return self.common_name - + + class BirdSighting(models.Model): bird = models.ForeignKey(Bird) point = models.PointField() location = models.ForeignKey(Location) date = models.DateTimeField('Date') - image = models.FileField(upload_to=get_upload_path, null=True,blank=True) - + image = models.FileField(upload_to=get_upload_path, null=True, blank=True) diff --git a/app/blog/admin.py b/app/blog/admin.py index d756b18..0d7a2b7 100644 --- a/app/blog/admin.py +++ b/app/blog/admin.py @@ -3,11 +3,9 @@ from django import forms from blog.models import Entry, PostImage, EntryAside from blog.widgets import AdminImageWidget from django.contrib.gis.admin import OSMGeoAdmin -from django.conf import settings from .models import * - class EntryAsideInline(admin.TabularInline): model = EntryAside extra = 1 @@ -16,32 +14,56 @@ class EntryAsideInline(admin.TabularInline): class EntryAsideAdmin(admin.ModelAdmin): pass + class BlogEntryForm(forms.ModelForm): class Meta: model = Entry widgets = { - 'body_markdown': forms.Textarea(attrs={'rows':50, 'cols':100}), + 'body_markdown': forms.Textarea(attrs={'rows': 50, 'cols': 100}), } - + class EntryAdmin(OSMGeoAdmin): form = BlogEntryForm - inlines = [EntryAsideInline,] + inlines = [EntryAsideInline] + def formfield_for_dbfield(self, db_field, **kwargs): - if db_field.name == 'thumbnail' or db_field.name == 'image' : + if db_field.name == 'thumbnail' or db_field.name == 'image': field = forms.FileField(widget=AdminImageWidget) else: - field = super(EntryAdmin,self).formfield_for_dbfield(db_field,**kwargs) + field = super(EntryAdmin, self).formfield_for_dbfield(db_field, **kwargs) return field - list_display = ('title', 'pub_date','template_name', 'status','region','location','photo_gallery') + + list_display = ('title', 'pub_date', 'template_name', 'status', 'region', 'location', 'photo_gallery') search_fields = ['title', 'body_markdown'] - prepopulated_fields = {"slug" : ('title',)} - list_filter = ('pub_date', 'enable_comments', 'status','location__state__country__lux_region',) + prepopulated_fields = {"slug": ('title',)} + list_filter = ('pub_date', 'enable_comments', 'status', 'location__state__country__lux_region') fieldsets = ( - ('Entry', {'fields': ('title','body_markdown', ('pub_date', 'status'), 'slug','point'), 'classes': ('show','extrapretty','wide')}), - ('Formatting data', {'fields': ('dek','meta_description', ('image','thumbnail',),'template_name'), 'classes': ('grp-collapse grp-closed',)}), + ('Entry', { + 'fields': ( + 'title', + 'body_markdown', + ('pub_date', 'status'), + 'slug', + 'point' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ('Formatting data', { + 'fields': ( + 'dek', + 'meta_description', + ('image', 'thumbnail'), + 'template_name' + ), + }), ) - + class Media: js = ['/media/admin/custom/model.js'] map_template = 'gis/admin/osm.html' @@ -49,7 +71,7 @@ class EntryAdmin(OSMGeoAdmin): # Uncomment and modify as desired # To learn more about this jargon visit: # www.openlayers.org - + default_lon = -9314310 default_lat = 3991847 default_zoom = 6 @@ -81,8 +103,9 @@ class EntryAdmin(OSMGeoAdmin): class PostImageAdmin(admin.ModelAdmin): - list_display = ('title', 'post_image') - -admin.site.register(PostImage, PostImageAdmin) -admin.site.register(EntryAside, EntryAsideAdmin) + list_display = ('title', 'post_image') + + +admin.site.register(PostImage, PostImageAdmin) +admin.site.register(EntryAside, EntryAsideAdmin) admin.site.register(Entry, EntryAdmin) diff --git a/app/blog/fields.py b/app/blog/fields.py index bab8ad3..6239297 100644 --- a/app/blog/fields.py +++ b/app/blog/fields.py @@ -4,4 +4,3 @@ from blog.widgets import AdminImageWidget class FileUploadForm(forms.ModelForm): upload = forms.FileField(widget=AdminImageWidget) - diff --git a/app/blog/models.py b/app/blog/models.py index 1876460..e7f10ab 100644 --- a/app/blog/models.py +++ b/app/blog/models.py @@ -4,68 +4,70 @@ from django.utils.html import format_html from django.conf import settings from django.contrib.syndication.views import Feed from django.contrib.sitemaps import Sitemap -from django.template.defaultfilters import truncatewords_html -from PIL import Image from django import forms - -#http://freewisdom.org/projects/python-markdown/ +# http://freewisdom.org/projects/python-markdown/ import markdown - from photos.models import PhotoGallery -from locations.models import Location,Region +from locations.models import Location + def get_upload_path(self, filename): - return "images/post-images/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/post-images/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + def get_tn_path(self, filename): - return "images/post-thumbnail/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/post-thumbnail/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + def image_url_replace(str): str = str.replace('[[base_url]]', settings.IMAGES_URL) return str -PUB_STATUS = ( - (0, 'Draft'), - (1, 'Published'), - ) - -TEMPLATES = ( - (0, 'single'), - (1, 'double'), - (2, 'single-dark'), - (3, 'double-dark'), - (4, 'bigimg'), - (5, 'bigimg-dark'), - ) class PostImage(models.Model): title = models.CharField(max_length=100) - image = models.ImageField(upload_to="%s/%s" %(settings.IMAGES_ROOT, datetime.datetime.today().strftime("%Y"))) + image = models.ImageField(upload_to="%s/%s" % (settings.IMAGES_ROOT, datetime.datetime.today().strftime("%Y"))) def __unicode__(self): return self.title - + def post_image(self): - return format_html('<img src="%s%s" alt="%s" class="postpic"/>' % \ - (settings.IMAGES_URL, self.image.url.split('images')[1].split('/',1)[1], self.title)) + return format_html('<img src="%s%s" alt="%s" class="postpic"/>' % ( + settings.IMAGES_URL, + self.image.url.split('images')[1].split('/', 1)[1], + self.title) + ) post_image.allow_tags = True + class Entry(models.Model): title = models.CharField(max_length=200) slug = models.SlugField(unique_for_date='pub_date') body_html = models.TextField(blank=True) body_markdown = models.TextField() - dek = models.TextField(null=True,blank=True) + dek = models.TextField(null=True, blank=True) pub_date = models.DateTimeField('Date published') enable_comments = models.BooleanField(default=False) point = models.PointField(null=True, blank=True) location = models.ForeignKey(Location, null=True, blank=True) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) status = models.IntegerField(choices=PUB_STATUS, default=0) photo_gallery = models.ForeignKey(PhotoGallery, blank=True, null=True, verbose_name='photo set') - image = models.FileField(upload_to=get_upload_path, null=True,blank=True) - thumbnail = models.FileField(upload_to=get_tn_path, null=True,blank=True) + image = models.FileField(upload_to=get_upload_path, null=True, blank=True) + thumbnail = models.FileField(upload_to=get_tn_path, null=True, blank=True) meta_description = models.CharField(max_length=256, null=True, blank=True) + TEMPLATES = ( + (0, 'single'), + (1, 'double'), + (2, 'single-dark'), + (3, 'double-dark'), + (4, 'bigimg'), + (5, 'bigimg-dark'), + ) template_name = models.IntegerField(choices=TEMPLATES, default=0) class Meta: @@ -73,35 +75,35 @@ class Entry(models.Model): get_latest_by = 'pub_date' verbose_name_plural = 'entries' - def __unicode__(self): + def __str__(self): return self.title def get_absolute_url(self): return "/%s/%s/" % (self.pub_date.strftime("%Y/%b/%d").lower(), self.slug) - + def comment_period_open(self): return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date - + def get_thumbnail_url(self): image_dir, img = self.thumbnail.url.split('post-thumbnail/')[1].split('/') - return '%spost-thumbnail/%s/%s' %(settings.IMAGES_URL, image_dir, img) - + return '%spost-thumbnail/%s/%s' % (settings.IMAGES_URL, image_dir, img) + def get_image_url(self): image_dir, img = self.image.url.split('post-images/')[1].split('/') - return '%spost-images/%s/%s' %(settings.IMAGES_URL, image_dir, img) + return '%spost-images/%s/%s' % (settings.IMAGES_URL, image_dir, img) @property def state(self): return self.location.state - + @property def country(self): return self.location.state.country - + @property def region(self): return self.location.state.country.lux_region - + @property def longitude(self): '''Get the site's longitude.''' @@ -110,34 +112,33 @@ class Entry(models.Model): @property def latitude(self): '''Get the site's latitude.''' - return self.point.y - + return self.point.y + @property def get_previous_published(self): return self.get_previous_by_pub_date(status__exact=1) - - @property + + @property def get_next_published(self): return self.get_next_by_pub_date(status__exact=1) - - def save(self): + def save(self): md = image_url_replace(self.body_markdown) - self.body_html = markdown.markdown(md, extensions=['extra',], safe_mode = False) - self.dek == markdown.markdown(self.dek, safe_mode = False) + self.body_html = markdown.markdown(md, extensions=['extra'], safe_mode=False) + self.dek == markdown.markdown(self.dek, safe_mode=False) try: self.location = Location.objects.filter(geometry__contains=self.point).get() except Location.DoesNotExist: - raise forms.ValidationError("There is no location associated with that point, add it: %sadmin/locations/location/add/" %(settings.BASE_URL)) + raise forms.ValidationError("There is no location associated with that point, add it: %sadmin/locations/location/add/" % (settings.BASE_URL)) super(Entry, self).save() + class EntryAside(models.Model): title = models.CharField(max_length=200) - body = models.TextField(null=True,blank=True) + body = models.TextField(null=True, blank=True) entry = models.ForeignKey(Entry) - class BlogSitemap(Sitemap): changefreq = "never" priority = 1.0 @@ -148,6 +149,7 @@ class BlogSitemap(Sitemap): def lastmod(self, obj): return obj.pub_date + class LatestFull(Feed): title = "Luxagraf: Topographical Writings" link = "/writing/" diff --git a/app/blog/parse.py b/app/blog/parse.py index 27f5165..a1e3056 100755 --- a/app/blog/parse.py +++ b/app/blog/parse.py @@ -1,12 +1,14 @@ #!/usr/bin/python -import os, datetime +import os +import datetime from dateutil.parser import parse as dateparser -from os.path import abspath,dirname +from os.path import abspath, dirname from django.core.exceptions import ObjectDoesNotExist from blog.models import Entry from django.conf import settings + def parse_file(filepath): data = {} contents = open(filepath).read() @@ -15,13 +17,13 @@ def parse_file(filepath): if line == '---': break else: - k,v = line.split(':', 1) + k, v = line.split(':', 1) data[k.strip()] = v.strip() body = "\n".join(line.strip() for line in raw[1:]) data["body_markdown"] = body.split('---')[1] return data -""" +""" now I need a function to query the db for the title and date if there's no entry then it's new and we add it and publish What about edits though? Crap, edits. That means we need to check lastmod @@ -30,23 +32,25 @@ from blog.parse import * crawl_dir() """ + + def crawl_dir(): file_root = settings.POSTS_DIR file_list = os.listdir(file_root) - file_list = filter(lambda item: not (item.startswith('README') or item.startswith('updategithub.php') or item.startswith('.') or item.endswith('~')),file_list) - for f in file_list: - fpath = file_root+"/"+f + file_list = filter(lambda item: not (item.startswith('README') or item.startswith('updategithub.php') or item.startswith('.') or item.endswith('~')), file_list) + for f in file_list: + fpath = file_root + "/" + f last_mod = datetime.datetime.fromtimestamp(os.path.getmtime(fpath)) - last_run = datetime.datetime.fromtimestamp(os.path.getmtime(abspath(dirname(__file__))+'/last_run')) - if last_mod > last_run: + last_run = datetime.datetime.fromtimestamp(os.path.getmtime(abspath(dirname(__file__)) + '/last_run')) + if last_mod > last_run: print "needs an update" data = parse_file(fpath) date = dateparser(data['pub_date']) try: - row = Entry.objects.get(title=str(data['title']),pub_date=date) + row = Entry.objects.get(title=str(data['title']), pub_date=date) print row.title, date except ObjectDoesNotExist: print data['title'] + str(date) + " = not found" - last_mod_dump = open(abspath(dirname(__file__))+'/last_run','w') + last_mod_dump = open(abspath(dirname(__file__)) + '/last_run', 'w') print last_mod_dump print >> last_mod_dump, str(datetime.datetime.now()) diff --git a/app/blog/urls.py b/app/blog/urls.py index a94eef3..d0a5224 100644 --- a/app/blog/urls.py +++ b/app/blog/urls.py @@ -1,10 +1,8 @@ from django.conf.urls import * from django.views.generic.base import RedirectView -from blog.models import Entry urlpatterns = patterns('', - (r'(?P<slug>[-\w]+)/(?P<page>\d+)/$', 'blog.views.entry_list_by_area'), (r'(?P<page>\d+)/$', 'blog.views.entry_list'), (r'(?P<slug>[-\w]+)/$', RedirectView.as_view(url="/writing/%(slug)s/1/")), diff --git a/app/blog/views.py b/app/blog/views.py index 04564fc..8c86839 100644 --- a/app/blog/views.py +++ b/app/blog/views.py @@ -1,28 +1,28 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.http import Http404 from django.conf import settings -from django.views.generic import ListView +# from django.views.generic import ListView from blog.models import Entry from locations.models import Region, Country -from photos.models import Photo, PhotoGallery +from photos.models import Photo + def home(request): context = { 'object_list': Entry.objects.filter(status__exact=1).select_related()[:4] - } - return render_to_response('archives/homepage.html', context, context_instance = RequestContext(request)) + } + return render_to_response('archives/homepage.html', context, context_instance=RequestContext(request)) def entry_detail(request, year, month, day, slug): obj = get_object_or_404(Entry, slug__exact=slug) photos = {} - #if obj.photo_gallery: + # if obj.photo_gallery: # photos = Photo.objects.filter(set__exact=obj.get().photo_gallery.id)[:9] - extra = {'photos':photos,} - return render_to_response('details/entry.html', {'object': obj,'photos':photos}, context_instance=RequestContext(request)) - + extra = {'photos': photos, } + return render_to_response('details/entry.html', {'object': obj, 'photos': photos}, context_instance=RequestContext(request)) """ List of all writing @@ -39,35 +39,35 @@ class BlogEntryListView(ListView): return context """ -def entry_list(request,page): + + +def entry_list(request, page): request.page_url = '/writing/%d/' request.page = int(page) try: - is_build = request.POST['builder'] - extra_context={ - 'page':page, + extra_context = { + 'page': page, 'MEDIA_URL': settings.BAKED_MEDIA_URL } except: - extra_context={'page':page} + extra_context = {'page': page} context = { 'object_list': Entry.objects.filter(status__exact=1).order_by('-pub_date').select_related(), } return render_to_response("archives/writing.html", context, context_instance=RequestContext(request)) -""" -Grabs entries by region or country -""" -def entry_list_by_area(request,slug,page): - request.page_url = '/writing/'+slug+'/%d/' +def entry_list_by_area(request, slug, page): + """ Grabs entries by region or country""" + request.page_url = '/writing/' + slug + '/%d/' request.page = int(page) try: region = Region.objects.get(slug__exact=slug) - qs = Entry.objects.filter(status__exact=1,region = region).order_by('-pub_date') + qs = Entry.objects.filter(status__exact=1, region=region).order_by('-pub_date') except: region = Country.objects.get(slug__exact=slug) - qs = Entry.objects.filter(status__exact=1,location__state__country = region).order_by('-pub_date') + qs = Entry.objects.filter( + status__exact=1, location__state__country=region).order_by('-pub_date') if not region: raise Http404 context = { @@ -75,13 +75,3 @@ def entry_list_by_area(request,slug,page): 'object_list': qs, } return render_to_response("archives/writing.html", context, context_instance=RequestContext(request)) - -""" -def about(request): - qs = Chunk.objects.filter(key__in=['about_top','about_middle','about_bottom']) - context = { - 'object_list':qs, - 'IMAGES_URL' : settings.IMAGES_URL - } - return render_to_response('details/about.html', context, context_instance=RequestContext(request)) -""" diff --git a/app/blog/widgets.py b/app/blog/widgets.py index 64509c2..ec1bd1d 100644 --- a/app/blog/widgets.py +++ b/app/blog/widgets.py @@ -1,15 +1,15 @@ +import os from django.contrib.admin.widgets import AdminFileWidget -from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe from django.conf import settings -from PIL import Image -import os + def thumbnail(image_path): absolute_url = os.path.join(settings.IMAGES_URL, image_path[7:]) print(absolute_url) return '<img style="max-width: 400px" src="%s" alt="%s" />' % (absolute_url, image_path) + class AdminImageWidget(AdminFileWidget): """ A FileField Widget that displays an image instead of a file path @@ -21,6 +21,6 @@ class AdminImageWidget(AdminFileWidget): if file_name: file_path = '%s' % (file_name) output.append('<a target="_blank" href="%s">%s</a>' % (file_path, thumbnail(file_name))) - + output.append(super(AdminFileWidget, self).render(name, value, attrs)) return mark_safe(''.join(output)) diff --git a/app/books/admin.py b/app/books/admin.py index 0b9b7b7..3f222d8 100644 --- a/app/books/admin.py +++ b/app/books/admin.py @@ -1,11 +1,13 @@ from django.contrib import admin -from .models import Book,BookHighlight +from .models import Book, BookHighlight + class BookAdmin(admin.ModelAdmin): - list_display = ('title', 'isbn', 'author_name', 'read_date') - + list_display = ('title', 'isbn', 'author_name', 'read_date') + + class BookHighlightAdmin(admin.ModelAdmin): - list_display = ('book', 'date_added') - -admin.site.register(Book, BookAdmin) -admin.site.register(BookHighlight, BookHighlightAdmin) + list_display = ('book', 'date_added') + +admin.site.register(Book, BookAdmin) +admin.site.register(BookHighlight, BookHighlightAdmin) diff --git a/app/books/kindleparser.py b/app/books/kindleparser.py index 6b708d9..aaa742f 100644 --- a/app/books/kindleparser.py +++ b/app/books/kindleparser.py @@ -8,6 +8,7 @@ import datetime from django.core.exceptions import ObjectDoesNotExist from books.models import Book, BookHighlight + def parse_kindle_clippings(path): json_data = open(path) data = json.load(json_data) @@ -20,11 +21,11 @@ def parse_kindle_clippings(path): body_markdown = clip['content'] except KeyError: body_markdown = "" - try: + try: location = int(clip['locationRange']) except: location = 0 - try: + try: page = int(clip['pageRange']) except: page = 0 @@ -37,21 +38,23 @@ def parse_kindle_clippings(path): row = Book.objects.get(title=clip['title']) except ObjectDoesNotExist: b, created = Book.objects.get_or_create( - title = clip['title'], - author_name = author_name, - read_date = clip_date + title=clip['title'], + author_name=author_name, + read_date=clip_date ) try: - #see if we already this highlight - row = BookHighlight.objects.get(book__title=clip['title'], date_added=clip_date ) - #if we don't create a new book highlight + #see if we already this highlight + row = BookHighlight.objects.get( + book__title=clip['title'], + date_added=clip_date + ) + #if we don't create a new book highlight except ObjectDoesNotExist: book = Book.objects.get(title=clip['title']) bh, created = BookHighlight.objects.get_or_create( - book = book, - page = page, - location = location, - date_added = clip_date, - body_markdown = body_markdown + book=book, + page=page, + location=location, + date_added=clip_date, + body_markdown=body_markdown ) - diff --git a/app/books/models.py b/app/books/models.py index 173b5f6..7af5d5c 100644 --- a/app/books/models.py +++ b/app/books/models.py @@ -1,6 +1,6 @@ from django.db import models from django.template.defaultfilters import slugify -from taggit.managers import TaggableManager +from taggit.managers import TaggableManager class Book(models.Model): @@ -10,13 +10,13 @@ class Book(models.Model): year_pub = models.CharField(max_length=4, blank=True, null=True) read_date = models.DateTimeField() isbn = models.CharField(max_length=100, blank=True, null=True) - + body_html = models.TextField(null=True, blank=True) - + url = models.CharField(max_length=200, blank=True, null=True) #tags = TaggableManager(blank=True, null=True) - tags = models.CharField(max_length=200,blank=True, null=True) + tags = models.CharField(max_length=200, blank=True, null=True) RATINGS = ( ('1', "1 Star"), ('2', "2 Stars"), @@ -29,14 +29,15 @@ class Book(models.Model): class Meta: ordering = ('-read_date',) - + def __str__(self): return self.title - + def save(self, *args, **kwargs): self.slug = slugify(self.title[:50]) super(Book, self).save() + class BookHighlight(models.Model): book = models.ForeignKey(Book) page = models.PositiveSmallIntegerField(null=True) @@ -48,7 +49,8 @@ class BookHighlight(models.Model): ordering = ('-date_added',) def __str__(self): - return "%s%s" %(self.book.title, self.id) + return "%s%s" % (self.book.title, self.id) + class BookNote(BookHighlight): pass diff --git a/app/builder/admin.py b/app/builder/admin.py index ee6957e..4dccd80 100644 --- a/app/builder/admin.py +++ b/app/builder/admin.py @@ -17,7 +17,7 @@ class EntryAdmin(OSMGeoAdmin): else: field = super(EntryAdmin,self).formfield_for_dbfield(db_field,**kwargs) return field - list_display = ('title', 'pub_date','enable_comments', 'status','region','location','photo_gallery') + list_display = ('title', 'pub_date','enable_comments', 'status','region','location','photo_gallery') search_fields = ['title', 'body_markdown'] prepopulated_fields = {"slug" : ('title',)} list_filter = ('pub_date', 'enable_comments', 'status','region','location') @@ -25,7 +25,7 @@ class EntryAdmin(OSMGeoAdmin): ('Entry', {'fields': ('title','body_markdown', ('location','region'), 'pub_date', ('status','enable_comments'), 'slug','photo_gallery'), 'classes': ('show','extrapretty','wide')}), ('Pub Location', {'fields': ('point',('image','thumbnail',),'dek', 'topics', 'meta_description','template_name'), 'classes': ('collapse', 'wide')}), ) - + class Media: js = ['/media/admin/custom/model.js'] extra_js = [GMAP.api_url + GMAP.key] @@ -35,7 +35,7 @@ class EntryAdmin(OSMGeoAdmin): # Uncomment and modify as desired # To learn more about this jargon visit: # www.openlayers.org - + default_lon = -9314310 default_lat = 3991847 default_zoom = 6 @@ -65,16 +65,16 @@ class EntryAdmin(OSMGeoAdmin): #debug = False #widget = OpenLayersWidget - + class PostImageAdmin(admin.ModelAdmin): list_display = ('title', 'output_tags') - + class TopicAdmin(admin.ModelAdmin): list_display = ('name', 'slug') admin.site.register(Topic, TopicAdmin) -admin.site.register(PostImage, PostImageAdmin) +admin.site.register(PostImage, PostImageAdmin) admin.site.register(Entry, EntryAdmin) diff --git a/app/builder/base.py b/app/builder/base.py index d626505..9cd5af7 100644 --- a/app/builder/base.py +++ b/app/builder/base.py @@ -9,45 +9,46 @@ from django.conf import settings class Build(): - def write_file(self, path, object, ext='html',filename='index'): + def write_file(self, path, text_object, ext='html', filename='index'): """ Given a path and object intended to be a webpage, write the page the disc """ - path = '%s%s' %(settings.FLATFILES_ROOT, path) + path = '%s%s' % (settings.FLATFILES_ROOT, path) if not os.path.isdir(path): os.makedirs(path) - fpath = '%s%s.%s' %(path, filename, ext) - file = open(fpath, 'w') - file.write(object) + fpath = '%s%s.%s' % (path, filename, ext) + file = open(fpath, 'wb') + file.write(text_object) file.close() if ext == 'js': import jsmin - compressed = jsmin.jsmin(object) - fpath = '%s%s.min.%s' %(path, filename, ext) - file = open(fpath, 'w') - file.write(compressed) + compressed = jsmin.jsmin(str(text_object)) + fpath = '%s%s.min.%s' % (path, filename, ext) + file = open(fpath, 'wb') + file.write(bytes(compressed, 'UTF-8')) file.close() def build_archive_pages(self, qs=None, base_path='', paginate_by=10): """ - Archive Page builder that actually crawls the urls + Archive Page builder that actually crawls the urls because we need to be able to pass a request object to the template - + """ - if qs == None: + if qs is None: qs = self.get_model_querset() c = Client() - pages = ceil(Decimal(qs.count())/Decimal(paginate_by)) + pages = ceil(Decimal(qs.count()) / Decimal(paginate_by)) for page in range(int(pages)): - path = '%s%s/' %(base_path, page+1) - url = '/%s%s/' %(base_path, str(page+1)) - page_url = base_path+'%d/' - response = c.post(url, {'page_url': page_url, 'page': int(page), 'builder':True }) + path = '%s%s/' % (base_path, page + 1) + url = '/%s%s/' % (base_path, str(page + 1)) + page_url = base_path + '%d/' + response = c.post(url, {'page_url': page_url, 'page': int(page), 'builder': True}) if page == 0: - self.write_file(base_path,str(response.content)) - self.write_file(path,str(response.content)) - + self.write_file(base_path, response.content) + self.write_file(path, response.content) + + class BuildWriting(Build): def build(self): self.build_detail_pages() @@ -62,55 +63,54 @@ class BuildWriting(Build): model = get_model('blog', 'entry') qs = model.objects.filter(status__exact=1) return qs - + def build_detail_pages(self): ''' Grab all the blog posts, render them to a template string and write that out to the filesystem ''' qs = self.get_model_querset() for entry in qs: - c = Context({'object':entry,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('details/entry.html',c).encode('utf-8') - path = '%s/%s/' %(entry.pub_date.strftime("%Y/%b/%d").lower(), entry.slug) - self.write_file(path,t) - s = render_to_string('details/entry.txt',c).encode('utf-8') - self.write_file(path,s,'txt') - + c = Context({'object': entry, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) + t = render_to_string('details/entry.html', c).encode('utf-8') + path = '%s/%s/' % (entry.pub_date.strftime("%Y/%b/%d").lower(), entry.slug) + self.write_file(path, t) + s = render_to_string('details/entry.txt', c).encode('utf-8') + self.write_file(path, s, 'txt') def build_writing_archives(self): qs = self.get_model_querset() self.build_archive_pages(qs, 'writing/') - + def build_region_archive_pages(self): - model = get_model('locations', 'Region') + model = get_model('locations', 'Region') blog = get_model('blog', 'entry') regions = model.objects.all() for c in regions: - qs = blog.objects.filter(status__exact=1,location__state__country__region = c.id).order_by('-pub_date') - path = 'writing/%s/' %(c.slug) + qs = blog.objects.filter(status__exact=1, location__state__country__region=c.id).order_by('-pub_date') + path = 'writing/%s/' % (c.slug) self.build_archive_pages(qs, path) def build_country_archive_pages(self): - model = get_model('locations', 'Country') + model = get_model('locations', 'Country') blog = get_model('blog', 'entry') countries = model.objects.filter(visited=True) for c in countries: - qs = blog.objects.filter(status__exact=1,location__state__country = c).order_by('-pub_date') - path = 'writing/%s/' %(c.slug) + qs = blog.objects.filter(status__exact=1, location__state__country=c).order_by('-pub_date') + path = 'writing/%s/' % (c.slug) self.build_archive_pages(qs, path) - + def writing_year_archives(self): entry = get_model('blog', 'entry') years = entry.objects.dates('pub_date', 'year') for year in years: year = year.strftime('%Y') - qs = entry.objects.filter(status__exact=1,pub_date__year=year).order_by('-pub_date') - c = Context({'type':'year','date': year, 'object_list':qs,}) - t = render_to_string('archives/writing_date.html',c).encode('utf-8') - fpath = '%s/' %(year) - self.write_file(fpath,t) + qs = entry.objects.filter(status__exact=1, pub_date__year=year).order_by('-pub_date') + c = Context({'type': 'year', 'date': year, 'object_list': qs}) + t = render_to_string('archives/writing_date.html', c).encode('utf-8') + fpath = '%s/' % (year) + self.write_file(fpath, t) - def writing_month_archives(self): + def writing_month_archives(self): entry = get_model('blog', 'entry') months = entry.objects.dates('pub_date', 'month') for m in months: @@ -118,34 +118,39 @@ class BuildWriting(Build): month = m.strftime('%m') month_name = m.strftime('%b') month_full_name = m.strftime('%B') - qs = entry.objects.filter(status__exact=1,pub_date__year=year,pub_date__month=month).order_by('-pub_date') - c = Context({'type':'monthly','date': '%s %s' %(month_full_name,year), 'object_list':qs,}) - t = render_to_string('archives/writing_date.html',c).encode('utf-8') - fpath = '%s/%s/' %(year,month_name) - self.write_file(fpath,t) - + qs = entry.objects.filter(status__exact=1, pub_date__year=year, + pub_date__month=month).order_by('-pub_date') + c = Context({'type': 'monthly', 'date': '%s %s' % ( + month_full_name, year), 'object_list': qs, }) + t = render_to_string('archives/writing_date.html', c).encode('utf-8') + fpath = '%s/%s/' % (year, month_name) + self.write_file(fpath, t) + def build_homepage(self): qs = get_model('blog', 'entry').objects.filter(status__exact=1)[:4] - c = Context({'object_list':qs,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('archives/homepage.html',c).encode('utf-8') - self.write_file('',t) + c = Context({'object_list': qs, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) + t = render_to_string('archives/homepage.html', c).encode('utf-8') + self.write_file('', t) + class BuildPhotos(Build): def build(self): self.build_photo_archive_pages() self.build_detail_pages() - + def build_photo_archive_pages(self): qs = get_model('photos', 'PhotoGallery').objects.all() self.build_archive_pages(qs, 'photos/', 18) - + def build_detail_pages(self): qs = get_model('photos', 'PhotoGallery').objects.all() for photo in qs: - c = Context({'object':photo,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('details/photo_galleries.html',c).encode('utf-8') - path = 'photos/galleries/%s/' %(photo.set_slug) - self.write_file(path,t) + c = Context({'object': photo, 'MEDIA_URL': + settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) + t = render_to_string('details/photo_galleries.html', c).encode('utf-8') + path = 'photos/galleries/%s/' % (photo.set_slug) + self.write_file(path, t) + class BuildProjects(Build): def build(self): @@ -158,16 +163,17 @@ class BuildProjects(Build): all_proj = [] projects = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') for proj in projects: - row = {'slug':proj.slug, 'name':proj.model_name} + row = {'slug': proj.slug, 'name': proj.model_name} all_proj.append(row) return all_proj - + def build_project_archive(self): qs = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') - c = Context({'object_list': qs,'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('archives/projects.html', c).encode('utf-8') - self.write_file('projects/',t) - + c = Context({'object_list': qs, 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL}) + t = render_to_string('archives/projects.html', c).encode('utf-8') + self.write_file('projects/', t) + def build_project_details(self): projects = self.get_projects() for proj in projects: @@ -176,11 +182,15 @@ class BuildProjects(Build): qs = model.objects.filter(visited__exact=True).order_by("-date_visited_begin") else: qs = model.objects.filter(status__exact=1) - c = Context({'object_list': qs,'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('details/%s.html' %(proj['slug']), c).encode('utf-8') - path = 'projects/%s/' %(proj['slug']) - self.write_file(path,t) - + c = Context({ + 'object_list': qs, + 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL + }) + t = render_to_string('details/%s.html' % (proj['slug']), c).encode('utf-8') + path = 'projects/%s/' % (proj['slug']) + self.write_file(path, t) + """ not sure how to handle projects really, the above doesn't work and if I just keep writing if/else statements that gets messy, so I guess @@ -189,13 +199,14 @@ class BuildProjects(Build): def build_gifs(self): qs = get_model('projects', 'AnimatedGif').objects.all() for gif in qs: - c = Context({'object':gif,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('details/gifs.html',c).encode('utf-8') - path = 'projects/gifs/%s/' %(gif.slug) - self.write_file(path,t) - - - + c = Context({ + 'object': gif, + 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL + }) + t = render_to_string('details/gifs.html', c).encode('utf-8') + path = 'projects/gifs/%s/' % (gif.slug) + self.write_file(path, t) def build_project_data(self): from projects.shortcuts import render_to_geojson @@ -204,29 +215,32 @@ class BuildProjects(Build): qs = model.objects.filter(pk=park.id) json = render_to_geojson( qs, - included_fields=['id',], + included_fields=['id'], geom_attribute='mpoly', - mimetype = 'application/json', - ) + mimetype='application/json', + ) json = str(json) - json ="\n".join(json.splitlines()[3:]) + json = "\n".join(json.splitlines()[3:]) #print json path = 'projects/data/natparks/' - self.write_file(path, json, 'json', park.id) + self.write_file(path, bytes(json, 'UTF-8'), 'json', park.id) + class BuildSitemap(Build): def build(self): c = Client() response = c.get('/sitemap.xml') - self.write_file('',str(response.content), 'xml','sitemap') + self.write_file('', response.content, 'xml', 'sitemap') + class BuildWritingFeed(Build): def build(self): qs = get_model('blog', 'entry').objects.filter(status__exact=1).order_by('-pub_date')[:20] - c = Context({'object_list':qs,'SITE_URL':settings.SITE_URL}) - t = render_to_string('feed.xml',c).encode('utf-8') - fpath = '%s' %('rss/',) - self.write_file(fpath,t,'xml') + c = Context({'object_list': qs, 'SITE_URL': settings.SITE_URL}) + t = render_to_string('feed.xml', c).encode('utf-8') + fpath = '%s' % ('rss/',) + self.write_file(fpath, t, 'xml') + class BuildMap(Build): def build(self): @@ -234,36 +248,48 @@ class BuildMap(Build): cl = get_model('locations', 'Country').objects.filter(visited=True).exclude(name='default') rl = get_model('locations', 'Region').objects.all() rtl = get_model('locations', 'Route').objects.all() - c = Context({'object_list':qs, 'country_list':cl,'region_list':rl, 'route_list':rtl, 'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('archives/map_data.html',c).encode('utf-8') - self.write_file('media/js/',t, 'js','mainmap') - c = Context({'country_list':cl,'region_list':rl,'route_list':rtl,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string('archives/map.html',c).encode('utf-8') - self.write_file('map/',t) - + c = Context({ + 'object_list': qs, + 'country_list': cl, + 'region_list': rl, + 'route_list': rtl, + 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL + }) + t = render_to_string('archives/map_data.html', c).encode('utf-8') + self.write_file('media/js/', t, 'js', 'mainmap') + c = Context({ + 'country_list': cl, + 'region_list': rl, + 'route_list': rtl, + 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL + }) + t = render_to_string('archives/map.html', c).encode('utf-8') + self.write_file('map/', t) + + class BuildPages(Build): def build(self): model = get_model('pages', 'page') pages = model.objects.all() for page in pages: - c = Context({'object':page,'SITE_URL':settings.SITE_URL, 'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL}) - t = render_to_string(["details/%s.html" % page.slug, 'details/page.html'],c).encode('utf-8') - s = render_to_string('details/page.txt',c).encode('utf-8') - fpath = '%s/' %(page.slug) - self.write_file(fpath,t) - self.write_file(fpath,s,'txt') - + c = Context({'object': page, 'SITE_URL': settings.SITE_URL, 'MEDIA_URL': + settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) + t = render_to_string( + ["details/%s.html" % page.slug, 'details/page.html'], c).encode('utf-8') + s = render_to_string('details/page.txt', c).encode('utf-8') + fpath = '%s/' % (page.slug) + self.write_file(fpath, t) + self.write_file(fpath, s, 'txt') class BuildContact(Build): def build(self): c = Client() response = c.get('/contact/') - path = '%scontact/' %(settings.BAKED_ROOT) + path = '%scontact/' % (settings.BAKED_ROOT) if not os.path.isdir(path): os.makedirs(path) - fpath = '%sindex.html' %(path) - self.write_file(fpath,str(response.content)) - -#class BuildCodeSite(Build): - + fpath = '%sindex.html' % (path) + self.write_file(fpath, response.content) diff --git a/app/builder/views.py b/app/builder/views.py index ca1296f..c0b8125 100644 --- a/app/builder/views.py +++ b/app/builder/views.py @@ -1,81 +1,32 @@ -from django.http import HttpResponseRedirect -from django.core.urlresolvers import reverse -from django.shortcuts import render_to_response,get_object_or_404,redirect - +from django.shortcuts import render_to_response from django.template import RequestContext +from builder.base import BuildWriting, BuildWritingFeed, BuildMap, BuildPages, BuildPhotos, BuildProjects, BuildSitemap, BuildContact + +options = { + 'writing': BuildWriting, + 'photo_galleries': BuildPhotos, + 'projects': BuildProjects, + 'pages': BuildPages, + 'map': BuildMap, + 'feed': BuildWritingFeed, + 'sitemap': BuildSitemap, +} -from builder.base import BuildWriting, BuildWritingFeed, BuildMap, BuildPages, BuildPhotos,BuildProjects,BuildSitemap,BuildContact def do_build(request): section = request.GET.get('id', '') - if section != '': - - #build writing archives - if section == 'writing': - BuildWriting().build() - context = {'message': 'Writing Posts to Disk',} - - #build photo galleries - elif section == 'photos': - BuildPhotos().build() - context = {'message': 'Writing Photo Galleries to Disk',} - - #build project pages - elif section == 'projects': - BuildProjects().build() - context = {'message': 'Writing Project pages to Disk',} - - #build pages - elif section == 'pages': - BuildPages().build() - context = {'message': 'Writing Pages to Disk',} - - #build map - elif section == 'map': - BuildMap().build() - context = {'message': 'Writing Map to Disk',} - - #build Writing RSS Feed - elif section == 'feed': - BuildWritingFeed().build() - context = {'message': 'Writing RSS Feed to Disk',} - - #build Sitemap - elif section == 'sitemap': - BuildSitemap().build() - context = {'message': 'Writing Sitemap to Disk',} - - #build Everything need for new post - elif section == 'newpost': - #build writing archives/details pages/homepage - BuildWriting().build() - #build map - BuildMap().build() - #build feed - BuildWritingFeed().build() - #build sitemap - BuildSitemap().build() - context = {'message': 'Publishing New Post',} - - #build Homepage - elif section == 'home': - BuildWriting().build_homepage() - context = {'message': 'Writing Homepage to Disk',} - #Crawl Flickr for new Photosets - elif section == 'scrapeflickr': - from photos import retriever - retriever.sync_sets() - context = {'message': 'Crawling Flickr for new photosets',} - """ - elif section == 'all': - g.build_entire_site() - context = {'message': 'Writing Entire Site to disk',} - """ - + context = {} + if section == 'newpost': + BuildWriting().build() + BuildMap().build() + BuildWritingFeed().build() + BuildSitemap().build() + context = {'message': 'Writing %s to Disk' % section} + elif section == 'scrapeflickr': + from photos import retriever + retriever.sync_sets() + context = {'message': 'Crawling Flickr for new photosets'} else: - context = {} - #return redirect('/admin/', message='test') - return render_to_response('admin/message.html', context, context_instance = RequestContext(request)) - - - + options[section]().build() + context = {'message': 'Writing %s to Disk' % section} + return render_to_response('admin/message.html', context, context_instance=RequestContext(request)) diff --git a/app/guide/admin.py b/app/guide/admin.py index cd24ab3..c81a2a5 100644 --- a/app/guide/admin.py +++ b/app/guide/admin.py @@ -1,63 +1,60 @@ from django.contrib import admin -from django import forms from guide.models import Guide from django.contrib.gis.admin import OSMGeoAdmin -from django.contrib.gis.maps.google import GoogleMap -from django.conf import settings - -GMAP = GoogleMap(key=settings.GOOGLE_MAPS_API_KEY) - class GuideAdmin(OSMGeoAdmin): - list_display = ('title', 'pub_date','template_name', 'status','location','photo_gallery') + list_display = ( + 'title', + 'pub_date', + 'template_name', + 'status', + 'location', + 'photo_gallery' + ) search_fields = ['title', 'body_markdown'] - prepopulated_fields = {"slug" : ('title',)} - list_filter = ('pub_date', 'status','location__state__country__lux_region','location') + prepopulated_fields = {"slug": ('title',)} + list_filter = ('pub_date', 'status', 'location__state__country__lux_region', 'location') fieldsets = ( - ('Note', {'fields': ('title','body_markdown', ('location'), 'pub_date', 'status', 'slug','photo_gallery'), 'classes': ('show','extrapretty','wide')}), - ('Extra', {'fields': ('dek', 'meta_description','template_name', ('image', 'thumbnail')), 'classes': ('collapse', 'wide')}), + ('Note', { + 'fields': ( + 'title', + 'body_markdown', + 'location', + 'pub_date', + 'status', + 'slug', + 'photo_gallery' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), + ('Extra', { + 'fields': ( + 'dek', + 'meta_description', + 'template_name', + 'image', + 'thumbnail' + ), + 'classes': ( + 'collapse', + 'wide' + ) + }), ) - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #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 = -9314310 - default_lat = 3991847 + + # options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 default_zoom = 6 - #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 + 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(Guide, GuideAdmin) diff --git a/app/guide/models.py b/app/guide/models.py index 90f63e1..9df83d3 100644 --- a/app/guide/models.py +++ b/app/guide/models.py @@ -3,59 +3,60 @@ from django.contrib.gis.db import models from django.conf import settings from django.contrib.sitemaps import Sitemap from django.contrib.syndication.views import Feed -from django.template.defaultfilters import truncatewords_html from PIL import Image import markdown -from taggit.managers import TaggableManager -from locations.models import Location,Region,Country +from taggit.managers import TaggableManager +from locations.models import Location from blog.models import Entry from photos.models import PhotoGallery + def get_upload_path(self, filename): - return "images/guide-images/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/guide-images/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + def get_tn_path(self, filename): - return "images/guide-thumbnail/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) - + return "images/guide-thumbnail/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + def image_url_replace(str): str = str.replace('[[base_url]]', settings.IMAGES_URL) return str -def markdown_processor(md): - return markdown.markdown(md, ['footnotes'],safe_mode = False) -PUB_STATUS = ( - (0, 'Draft'), - (1, 'Published'), - ) +def markdown_processor(md): + return markdown.markdown(md, ['footnotes'], safe_mode=False) + -TEMPLATES = ( - (0, 'single'), - (1, 'double'), - (2, 'single-dark'), - (3, 'double-dark'), - ) - class Guide(models.Model): title = models.CharField(max_length=200) slug = models.SlugField(unique_for_date='pub_date') entry = models.ForeignKey(Entry, null=True, blank=True) body_html = models.TextField(blank=True) body_markdown = models.TextField() - dek = models.TextField(null=True,blank=True) + dek = models.TextField(null=True, blank=True) pub_date = models.DateTimeField('Date published') location = models.ForeignKey(Location, null=True, blank=True) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) status = models.IntegerField(choices=PUB_STATUS, default=0) photo_gallery = models.ForeignKey(PhotoGallery, blank=True, null=True, verbose_name='photo set') meta_description = models.CharField(max_length=256, null=True, blank=True) + TEMPLATES = ( + (0, 'single'), + (1, 'double'), + (2, 'single-dark'), + (3, 'double-dark'), + ) template_name = models.IntegerField(choices=TEMPLATES, default=0) tags = TaggableManager(blank=True) - image = models.FileField(upload_to=get_upload_path, null=True,blank=True) - thumbnail = models.FileField(upload_to=get_tn_path, null=True,blank=True) + image = models.FileField(upload_to=get_upload_path, null=True, blank=True) + thumbnail = models.FileField(upload_to=get_tn_path, null=True, blank=True) - @property def longitude(self): '''Get the site's longitude.''' @@ -64,8 +65,8 @@ class Guide(models.Model): @property def latitude(self): '''Get the site's latitude.''' - return self.point.y - + return self.point.y + class Meta: ordering = ('-pub_date',) get_latest_by = 'pub_date' @@ -79,29 +80,30 @@ class Guide(models.Model): return "/travel-guide/location/%s/%s/" % (self.location.slug, self.slug) else: return "/travel-guide/%s/" % (self.slug) - + def get_thumbnail_url(self): image_dir, img = self.thumbnail.url.split('guide-thumbnail/')[1].split('/') - return '%sguide-thumbnail/%s/%s' %(settings.IMAGES_URL, image_dir, img) - + return '%sguide-thumbnail/%s/%s' % (settings.IMAGES_URL, image_dir, img) + def get_image_url(self): image_dir, img = self.image.url.split('guide-images/')[1].split('/') - return '%sguide-images/%s/%s' %(settings.IMAGES_URL, image_dir, img) - - def save(self): + return '%sguide-images/%s/%s' % (settings.IMAGES_URL, image_dir, img) + + def save(self): #get image dimensions if self.image: img = Image.open(self.image) - self.image_width, self.image_height = img.size + self.image_width, self.image_height = img.size #same for thumb img = Image.open(self.thumbnail) - self.thumb_width, self.thumb_height = img.size + self.thumb_width, self.thumb_height = img.size md = image_url_replace(self.body_markdown) #run markdown self.body_html = markdown_processor(md) - self.dek == markdown.markdown(self.dek, safe_mode = False) + self.dek = markdown.markdown(self.dek, safe_mode=False) super(Guide, self).save() + class GuideSitemap(Sitemap): changefreq = "never" priority = 1.0 @@ -112,6 +114,7 @@ class GuideSitemap(Sitemap): def lastmod(self, obj): return obj.pub_date + class GuideFull(Feed): title = "Luxagraf: Topographical Writings" link = "/writing/" diff --git a/app/guide/views.py b/app/guide/views.py index 50a42d2..c22a6b3 100644 --- a/app/guide/views.py +++ b/app/guide/views.py @@ -1,33 +1,30 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext -from django.core.exceptions import ObjectDoesNotExist from guide.models import Guide -from locations.models import Location -def guide_list(request,page): - """ - List of all guides - """ + +def guide_list(request, page): + """List of all guides""" request.page_url = "/guide/%d/" request.page = int(page) - context={ - 'object_list':Guide.objects.filter(status__exact=1).order_by('-pub_date').select_related(), - 'page':page, - } + context = { + 'object_list': Guide.objects.filter(status__exact=1).order_by('-pub_date').select_related(), + 'page': page, + } return render_to_response("archives/guide.html", context, context_instance=RequestContext(request)) -def guide_list_by_location(request,location): - context={ + +def guide_list_by_location(request, location): + context = { "object_list": Guide.objects.filter(location__slug__exact=location), } return render_to_response("archives/guide.html", context, context_instance=RequestContext(request)) + def location_list(request): - """ - List of all locations with guides - """ - context={ + """List of all locations with guides""" + context = { "object_list": Guide.objects.filter(status__exact=1).order_by('-pub_date').select_related() } return render_to_response("archives/guide.html", context, context_instance=RequestContext(request)) @@ -35,7 +32,4 @@ def location_list(request): def guide_detail(request, slug, location=None): obj = get_object_or_404(Guide, slug__exact=slug) - return render_to_response('details/guide.html', {'object': obj,}, context_instance=RequestContext(request)) - - - + return render_to_response('details/guide.html', {'object': obj}, context_instance=RequestContext(request)) diff --git a/app/links/admin.py b/app/links/admin.py index 2c73c76..68efe9e 100644 --- a/app/links/admin.py +++ b/app/links/admin.py @@ -1,14 +1,30 @@ from django.contrib import admin - from links.models import Link + class LinkAdmin(admin.ModelAdmin): list_display = ('title', 'rating', 'pub_date', 'status') - search_fields = ['title','description','url'] + search_fields = ['title', 'description', 'url'] list_filter = ['rating', 'status'] fieldsets = ( - (None, {'fields': ('title','url','description','rating')}), - ('Details', {'fields': ('screen_url', 'pub_date', 'link_id', 'tags', 'status'), 'classes': 'collapse'}), + (None, { + 'fields': ( + 'title', + 'url', + 'description', + 'rating' + ) + }), + ('Details', { + 'fields': ( + 'screen_url', + 'pub_date', + 'link_id', + 'tags', + 'status' + ), + 'classes': 'collapse' + }), ) - -admin.site.register(Link, LinkAdmin)
\ No newline at end of file + +admin.site.register(Link, LinkAdmin) diff --git a/app/links/detail_urls.py b/app/links/detail_urls.py index b629f3e..9c76a7f 100644 --- a/app/links/detail_urls.py +++ b/app/links/detail_urls.py @@ -4,11 +4,7 @@ from django.views.generic.detail import DetailView from links.models import Link -detail_dict = { - 'queryset': Link.objects.filter(status__exact=1), -} urlpatterns = patterns('', - (r'^$', RedirectView.as_view(url="/links/1/")), - (r'^(?P<object_id>\d+)/$', DetailView.as_view(model=Link,template_name='details/link.html')), + (r'^$', RedirectView.as_view(url="/links/1/")), + (r'^(?P<object_id>\d+)/$', DetailView.as_view(model=Link, template_name='details/link.html')), ) - diff --git a/app/links/models.py b/app/links/models.py index 4c3e59d..c6b502c 100644 --- a/app/links/models.py +++ b/app/links/models.py @@ -2,7 +2,7 @@ import datetime from django.db import models from django.contrib.sitemaps import Sitemap from django.contrib.syndication.views import Feed -from taggit.managers import TaggableManager +from taggit.managers import TaggableManager RATINGS = ( ('1', "1 Star"), @@ -12,8 +12,7 @@ RATINGS = ( ('5', "5 Stars"), ) -DEBUG = 1 - + class Link(models.Model): link_id = models.CharField(max_length=60, blank=True, null=True) title = models.CharField(max_length=400) @@ -31,29 +30,29 @@ class Link(models.Model): class Meta: ordering = ['-pub_date'] - + def __unicode__(self): return self.title - + def get_absolute_url(self): return self.url - + def get_model_name(self): return 'link' - + def get_previous_published(self): return self.get_previous_by_pub_date(status__exact=1) - + def get_next_published(self): return self.get_next_by_pub_date(status__exact=1) - - + def get_thumbnail_url(self): - return "http://images.luxagraf.net/magnolia_thumbs/%s" %(self.screen_url) + return "http://images.luxagraf.net/magnolia_thumbs/%s" % (self.screen_url) + def comment_period_open(self): return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date - - + + class LinkSitemap(Sitemap): changefreq = "never" priority = 0.4 @@ -63,7 +62,8 @@ class LinkSitemap(Sitemap): def lastmod(self, obj): return obj.pub_date - + + class LatestLinks(Feed): title = "Luxagraf: Links" link = "http://ma.gnolia.com/people/luxagraf/bookmarks" diff --git a/app/links/retriever.py b/app/links/retriever.py index bcbc8fa..9e7aae5 100644 --- a/app/links/retriever.py +++ b/app/links/retriever.py @@ -5,15 +5,33 @@ from django.template.defaultfilters import striptags from django.core.mail import EmailMessage from django.conf import settings - -from utils.strutils import safestr,unquotehtml from links.models import Link -from utils import pinboard +# https://github.com/mgan59/python-pinboard/ +import pinboard + + +def safestr(s): + """ + Safely corerce *anything* to a string. If the object can't be str'd, an + empty string will be returned. + + You can (and I do) use this for really crappy unicode handling, but it's + a bit like killing a mosquito with a bazooka. + """ + if s is None: + return "" + if isinstance(s, unicode): + return s.encode('ascii', 'xmlcharrefreplace') + else: + try: + return str(s) + except: + return "" + def sync_pinboard_links(): """ sync bookmarks from my pinboard account - dependancies: python-pinboard https://github.com/mgan59/python-pinboard/ """ p = pinboard.open(settings.PIN_USER, settings.PIN_PASS) @@ -22,17 +40,17 @@ def sync_pinboard_links(): for link in links: try: #check to see if link exists - row = Link.objects.get(link_id=safestr(link['hash'])) + row = Link.objects.get(link_id=safestr(link['hash'])) except ObjectDoesNotExist: l, created = Link.objects.get_or_create( - title = link['description'], - link_id = safestr(link['hash']), - url = safestr(link['href']), - description = safestr(link['extended']), - rating = "3", - pub_date = datetime.datetime.strptime(link['time'], "%Y-%m-%dT%H:%M:%SZ"), - status = 0 - ) + title=link['description'], + link_id=safestr(link['hash']), + url=safestr(link['href']), + description=safestr(link['extended']), + rating="3", + pub_date=datetime.datetime.strptime(link['time'], "%Y-%m-%dT%H:%M:%SZ"), + status=0 + ) print l.title if created: print l.title @@ -40,72 +58,14 @@ def sync_pinboard_links(): l.tags.add(t) email_link(l) -''' -def sync_delicious_links(*args, **kwargs): - b = delicious.get_all(settings.DELICIOUS_USER, settings.DELICIOUS_PASS) - dupe = False - for post in b: - taglist = [] - try: - row = Link.objects.get(magnolia_id=safestr(post['hash'])) - # If the row exists already, set the dupe flag - dupe = True - except ObjectDoesNotExist: - #f = copy_file(safestr(post.findtext('screenshot')), safestr(info['id'])) - #fake the image since delicious doesn't offer them - local_image_url = "%s/%s.jpg" %(safestr(datetime.datetime.today().strftime("%b").lower()), safestr(post['hash'])) - tags = str(post['tag']).split(" ") - for tag in tags: - taglist.append(tag) - for tag in taglist: - if tag == '2lux': - status = 1 - break - else: - status = 0 - descr = markdown.markdown(unquotehtml(safestr(post['extended'])), safe_mode = False) - l, created = Link.objects.get_or_create( - title = post['description'], - magnolia_id = safestr(post['hash']), - url = safestr(post['href']), - description = descr, - screen_url = local_image_url, - #fake the rating since delicious doesn't offer such things - rating = "3", - pub_date = datetime.datetime.strptime(post['time'], "%Y-%m-%dT%H:%M:%SZ"), - status = status, - enable_comments = True, - tags = ", ".join(t for t in taglist if t != "2lux") - ) - - email_link(l) - if l.status == 1: - pass - #post_to_tumblr(l) - #send_to_deliciousfb(l) - if(dupe): - break - - -''' def email_link(link): """ Sends an imported link to Gmail (never hurts to have backups) """ subject = link.title - body = "%s\n\n%s\n\n\nvisit site:%s\n" %(link.title, link.description, link.url) + body = "%s\n\n%s\n\n\nvisit site:%s\n" % (link.title, link.description, link.url) msg = EmailMessage(subject, striptags(body), 'sng@luxagraf.net', ['luxagraf+links@gmail.com']) msg.send() msg = EmailMessage(subject, striptags(body), 'sng@luxagraf.net', ['sng+links@luxagraf.net']) msg.send() - -''' -def send_to_delicious(link): - del_tags = '' - tags = link.tags.split(',') - for tag in tags: - del_tags += tag.strip().replace(' ','_')+' ' - delicious.add(settings.DELICIOUS_USER, settings.DELICIOUS_PASS, link.url, link.title, tags = del_tags, extended = striptags(link.description), dt =safestr(link.pub_date), replace="no") - -''' diff --git a/app/links/sync_links.py b/app/links/sync_links.py index cd1373d..b61395c 100644 --- a/app/links/sync_links.py +++ b/app/links/sync_links.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(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 links import retriever diff --git a/app/locations/admin.py b/app/locations/admin.py index 5e6106b..6d971f1 100644 --- a/app/locations/admin.py +++ b/app/locations/admin.py @@ -1,297 +1,232 @@ from django.contrib import admin from django.contrib.gis.admin import OSMGeoAdmin -from locations.models import Region,Country,Location,State,Route - -from django.contrib.gis.maps.google import GoogleMap +from locations.models import Region, Country, Location, State, Route from django.conf import settings -GMAP = GoogleMap(key=settings.GOOGLE_MAPS_API_KEY) - class RegionAdmin(OSMGeoAdmin): - # Standard Django Admin Options - list_display = ('name','slug') + list_display = ('name', 'slug') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) ordering = ('name',) save_as = True - search_fields = ['name',] + search_fields = ['name'] list_select_related = True fieldsets = ( - ('Region', {'fields': ('name','slug','pub_date'), 'classes': ('show','extrapretty')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), + ('Region', { + 'fields': ( + 'name', + 'slug', + 'pub_date' + ), + 'classes': ( + 'show', + 'extrapretty' + ) + } + ), + ('Editable Map View', { + 'fields': ( + 'geometry', + ), + 'classes': ( + 'show', + 'wide' + ) + } + ), ) - 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(Region, RegionAdmin) -# Finally, with these options set now register the model -# associating the Options with the actual model -admin.site.register(Region,RegionAdmin) class CountryAdmin(OSMGeoAdmin): - """ - # Standard Django Admin Options - list_display = ('name','slug','region') - prepopulated_fields = {'slug': ('name',)} - search_fields = ('name',) - ordering = ('name',) - save_as = True - search_fields = ['name',] - list_select_related = True - fieldsets = ( - ('Country', {'fields': ('name','slug','abbr','region','pub_date'), 'classes': ('show','extrapretty')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), - ) - """ - - # Standard Django Admin Options - list_display = ('name','pop2005','region','subregion',) + list_display = ('name', 'pop2005', 'region', 'subregion') search_fields = ('name',) ordering = ('name',) - list_filter = ('visited','region','subregion',) + list_filter = ('visited', 'region', 'subregion') save_as = True - search_fields = ['name','iso2','iso3','subregion','region'] + search_fields = ['name', 'iso2', 'iso3', 'subregion', 'region'] list_select_related = True fieldsets = ( - ('Country Attributes', {'fields': (('name','pop2005','slug','zoom_level','visited')), 'classes': ('show','extrapretty')}), - ('Country Codes', {'fields': ('region','subregion','iso2','iso3','un',), 'classes': ('collapse',)}), - ('Area and Coordinates', {'fields': ('area','lat','lon',), 'classes': ('collapse', 'wide')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), + ('Country Attributes', + {'fields': ( + 'name', + 'pop2005', + 'slug', + 'zoom_level', + 'visited' + ), + 'classes': ( + 'show', + 'extrapretty' + ) + } + ), + ('Country Codes', + {'fields': ( + 'region', + 'subregion', + 'iso2', + 'iso3', + 'un', + ), + 'classes': ('collapse',) + } + ), + ('Area and Coordinates', + {'fields': ( + 'area', + 'lat', + 'lon', + ), + 'classes': ('collapse', 'wide') + } + ), + ('Editable Map View', + {'fields': ('geometry',), + 'classes': ('show', 'wide') + } + ), ) - 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' -# Finally, with these options set now register the model -# associating the Options with the actual model -admin.site.register(Country,CountryAdmin) +admin.site.register(Country, CountryAdmin) class StateAdmin(OSMGeoAdmin): - # Standard Django Admin Options - list_display = ('name','code','slug','country') + list_display = ('name', 'code', 'slug', 'country') prepopulated_fields = {'slug': ('name',)} - search_fields = ('name','country') + search_fields = ('name', 'country') ordering = ('name',) save_as = True - search_fields = ['name',] + search_fields = ['name'] list_select_related = True fieldsets = ( - ('Location', {'fields': ('name','slug','code','pub_date','country'), 'classes': ('show','extrapretty')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), + ('Location', + {'fields': ( + 'name', + 'slug', + 'code', + 'pub_date', + 'country' + ), + 'classes': ('show', 'extrapretty') + } + ), + ('Editable Map View', + {'fields': ('geometry',), + 'classes': ('show', 'wide') + } + ), ) - 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(State, StateAdmin) -# Finally, with these options set now register the model -# associating the Options with the actual model -admin.site.register(State,StateAdmin) class LocationAdmin(OSMGeoAdmin): - # Standard Django Admin Options - list_display = ('name','slug','state') + list_display = ('name', 'slug', 'state') prepopulated_fields = {'slug': ('name',)} - search_fields = ('name','state') + search_fields = ('name', 'state') ordering = ('name',) save_as = True - search_fields = ['name',] + search_fields = ['name'] list_select_related = True fieldsets = ( - ('Location', {'fields': ('name','slug','pub_date','state'), 'classes': ('show','extrapretty')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), + ('Location', + {'fields': ( + 'name', + 'slug', + 'pub_date', + 'state' + ), + 'classes': ('show', 'extrapretty') + } + ), + ('Editable Map View', + {'fields': ('geometry',), + 'classes': ('show', 'wide') + } + ), ) - 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(Location, LocationAdmin) -# Finally, with these options set now register the model -# associating the Options with the actual model -admin.site.register(Location,LocationAdmin) class RouteAdmin(OSMGeoAdmin): - # Standard Django Admin Options - list_display = ('name','slug',) + list_display = ('name', 'slug') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) ordering = ('name',) save_as = True - search_fields = ['name',] + search_fields = ['name'] list_select_related = True fieldsets = ( - ('Location', {'fields': ('name','slug','pub_date','template_var_name','zoom'), 'classes': ('show','extrapretty')}), - ('Editable Map View', {'fields': ('geometry',), 'classes': ('show', 'wide')}), + ('Location', + {'fields': ( + 'name', + 'slug', + 'pub_date', + 'template_var_name', + 'zoom' + ), + 'classes': ('show', 'extrapretty') + } + ), + ('Editable Map View', + {'fields': ('geometry',), + 'classes': ('show', 'wide') + } + ), ) - 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 - -# Finally, with these options set now register the model -# associating the Options with the actual model -admin.site.register(Route,RouteAdmin) - - + map_height = 425 + map_template = 'gis/admin/osm.html' +admin.site.register(Route, RouteAdmin) diff --git a/app/locations/models.py b/app/locations/models.py index e088697..ac8ec44 100755..100644 --- a/app/locations/models.py +++ b/app/locations/models.py @@ -1,66 +1,38 @@ -# -*- coding: utf-8 -*- -# models.py - -# All standard Django fields as well as GeoDjango geometry fields and the GeoManager() can be -# imported from django.contrib.gis.db after adding django.contrib.gis to INSTALLED_APPS from django.contrib.gis.db import models from django.contrib.sitemaps import Sitemap -# Used to display html 'help text' links within Admin App from django.utils.safestring import mark_safe + class Region(models.Model): - name = models.CharField(max_length=50, ) + """Model to define arbitrary regions based on where I've been""" + name = models.CharField(max_length=50) slug = models.SlugField() - pub_date = models.DateTimeField('Date published',null=True) + pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPolygonField(srid=4326, null=True) - lon = models.FloatField('Longitude',help_text="Longitude of centerpoint",null=True) - lat = models.FloatField('Latitude',help_text="Latitude of centerpoint",null=True) - zoom_level = models.CharField(max_length=2,null=True) + lon = models.FloatField('Longitude', help_text="Longitude of centerpoint", null=True) + lat = models.FloatField('Latitude', help_text="Latitude of centerpoint", null=True) + zoom_level = models.CharField(max_length=2, null=True) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() - + def get_absolute_url(self): return "/locations/region/%s/" % (self.slug) - - def __unicode__(self): return self.name - -# imported from django.contrib.gis.db -from django.contrib.gis.db import models + def __str__(self): + return self.name -# Used to display html 'help text' links within Admin App -from django.utils.safestring import mark_safe class Country(models.Model): """ - - A geographic model based on the v3 of the simplified world borders multipolygon shapefile - from http://thematicmapping.org/downloads/world_borders.php. - - Field names, Django types, and max_lengths were autogenerated using the ogrinspect utility with hand - edits to add alternative field names and help_text. - - Imported using LayerMapping (requires GDAL) called within the load_data.py script provided - within this sample project. - - All fields match the source dataset, an ESRI format shapefile made up of several related files: - .shp - holds the vector data that is to be stored in the MultiPolygonField field named'geometry'. - .shx - spatial index file for geometries stored in the .shp. - .dbf - database file for holding attribute data (can be opened in excel and open office). - .prj - contains the spatial reference information for the geometries stored in the .shp - - + A geographic model based on the v3 of the simplified world borders multipolygon shapefile from http://thematicmapping.org/downloads/world_borders.php. """ - - # Regular Django fields corresponding to the attributes in the - # world borders shapefile name = models.CharField(max_length=50) area = models.IntegerField(help_text="Area of Country in SQ meters") pop2005 = models.IntegerField('Population 2005') fips = models.CharField('FIPS Code', max_length=2, help_text=mark_safe('<a href="http://www.census.gov/geo/www/fips/fips.html">Federal Information Processing Standard Code</a>')) - iso2 = models.CharField('2 Digit ISO', max_length=2, help_text=mark_safe('<a href="http://www.iso.org/">International Organization for Standardization</a>' )) - iso3 = models.CharField('3 Digit ISO', max_length=3,help_text=mark_safe('<a href="http://www.iso.org/">International Organization for Standardization</a>' )) + iso2 = models.CharField('2 Digit ISO', max_length=2, help_text=mark_safe('<a href="http://www.iso.org/">International Organization for Standardization</a>')) + iso3 = models.CharField('3 Digit ISO', max_length=3, help_text=mark_safe('<a href="http://www.iso.org/">International Organization for Standardization</a>')) un = models.IntegerField('United Nations Code') REGION_CODES = ( (0, 'MISC'), @@ -95,96 +67,92 @@ class Country(models.Model): (154, 'Northern Europe'), (155, 'Western Europe'), ) - region = models.IntegerField('Region Code',choices=REGION_CODES) - subregion = models.IntegerField('Sub-Region Code',choices=SUBREGION_CODES) - lon = models.FloatField('Longitude',help_text="Longitude of centerpoint") - lat = models.FloatField('Latitude',help_text="Latitude of centerpoint") - zoom_level = models.CharField(max_length=2,null=True) + region = models.IntegerField('Region Code', choices=REGION_CODES) + subregion = models.IntegerField('Sub-Region Code', choices=SUBREGION_CODES) + lon = models.FloatField('Longitude', help_text="Longitude of centerpoint") + lat = models.FloatField('Latitude', help_text="Latitude of centerpoint") + zoom_level = models.CharField(max_length=2, null=True) slug = models.SlugField(null=True) visited = models.BooleanField(default=False) lux_region = models.ForeignKey(Region, null=True) - pub_date = models.DateTimeField('Date published',null=True) - # GeoDjango-specific: a geometry field (MultiPolygonField), and - # overriding the default manager with a GeoManager instance. - geometry = models.MultiPolygonField('Country Border',srid=4326) + pub_date = models.DateTimeField('Date published', null=True) + geometry = models.MultiPolygonField('Country Border', srid=4326) objects = models.GeoManager() - - # Returns the string representation of the model. - def __unicode__(self): - return self.name - class Meta: ordering = ['name'] verbose_name_plural = 'Countries' - + + def __str__(self): + return self.name + def get_absolute_url(self): return "/locations/%s/" % (self.slug) - + class State(models.Model): + """Model to hold state boundaries""" name = models.CharField(max_length=250, blank=True, null=True,) country = models.ForeignKey(Country) slug = models.SlugField() code = models.CharField(max_length=2, null=True, blank=True) - pub_date = models.DateTimeField('Date published',null=True) - geometry = models.MultiPolygonField(srid=4326,null=True) + pub_date = models.DateTimeField('Date published', null=True) + geometry = models.MultiPolygonField(srid=4326, null=True) objects = models.GeoManager() - + class Meta: ordering = ['name'] - - class Admin: - pass - - def __unicode__(self): - return "%s" %(self.name) + + def __str__(self): + return "%s" % (self.name) def get_absolute_url(self): return "/locations/%s/%s/" % (self.country.slug, self.slug) + class Location(models.Model): + """Model to hold location shapes as arbitrarily defined by me""" state = models.ForeignKey(State) name = models.CharField(max_length=50, ) slug = models.SlugField() - pub_date = models.DateTimeField('Date published',null=True) + pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPolygonField(srid=4326) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() - + + def __str__(self): + return self.name + def get_absolute_url(self): return "/locations/%s/%s/%s/" % (self.state.country.slug, self.state.slug, self.slug) - - def __unicode__(self): return self.name class Route(models.Model): + """Model to hold routes for longer trips""" name = models.CharField(max_length=200) slug = models.SlugField() zoom = models.CharField(max_length=2, null=True) template_var_name = models.CharField(max_length=10, null=True) - pub_date = models.DateTimeField('Date published',null=True) + pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPointField(srid=4326) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() - + def get_absolute_url(self): return "/locations/%s/%s/%s/" % (self.slug) - - def __unicode__(self): return self.name - + def __str__(self): + return self.name class WritingbyLocationSitemap(Sitemap): changefreq = "weekly" priority = 0.6 - + def location(): - return '/writing/%s/1/' %(self.slug) - + return '/writing/%s' % self.slug + def items(self): return Location.objects.all() - diff --git a/app/locations/urls.py b/app/locations/urls.py index 8bc86aa..c7ddb74 100644 --- a/app/locations/urls.py +++ b/app/locations/urls.py @@ -1,8 +1,6 @@ - from django.conf.urls import * urlpatterns = patterns('', (r'data/(?P<id>\d+)/$', 'locations.views.data_json'), (r'^$', 'locations.views.map_list'), ) - diff --git a/app/locations/views.py b/app/locations/views.py index 234d867..5ae1ef9 100644 --- a/app/locations/views.py +++ b/app/locations/views.py @@ -1,35 +1,44 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext - from blog.models import Entry from locations.models import Location, Country, Region, Route +from projects.shortcuts import render_to_geojson + def map_list(request): context = { - 'object_list' : Entry.objects.filter(status__exact=1), - 'country_list' : Country.objects.filter(visited=True).exclude(name='default'), - 'route_list' : Route.objects.all(), - 'region_list' : Region.objects.all() + 'object_list': Entry.objects.filter(status__exact=1), + 'country_list': Country.objects.filter(visited=True).exclude(name='default'), + 'route_list': Route.objects.all(), + 'region_list': Region.objects.all() } - return render_to_response('archives/map.html', context, context_instance=RequestContext(request)) + return render_to_response( + 'archives/map.html', + context, + context_instance=RequestContext(request) + ) + def map_data(request): context = { - 'object_list' : Entry.objects.filter(status__exact=1), - 'route_list' : Route.objects.all(), - 'country_list' : Country.objects.filter(visited=True).exclude(name='default'), - 'region_list' : Region.objects.all() + 'object_list': Entry.objects.filter(status__exact=1), + 'route_list': Route.objects.all(), + 'country_list': Country.objects.filter(visited=True).exclude(name='default'), + 'region_list': Region.objects.all() } - return render_to_response('archives/map_data.html', context, context_instance=RequestContext(request)) - -from projects.shortcuts import render_to_geojson + return render_to_response( + 'archives/map_data.html', + context, + context_instance=RequestContext(request) + ) + def data_json(request, id): qs = Route.objects.filter(pk=id) return render_to_geojson( qs, - included_fields=['id',], + included_fields=['id', ], geom_attribute='geometry', - mimetype = 'application/json', + mimetype='application/json', pretty_print=True - ) + ) diff --git a/app/pages/admin.py b/app/pages/admin.py index e1328e9..e6befe5 100644 --- a/app/pages/admin.py +++ b/app/pages/admin.py @@ -1,26 +1,26 @@ from django.contrib import admin -from django import forms from pages.models import Page -from django.conf import settings -from django.forms import TextInput, Textarea +from django.forms import Textarea from django.db import models + + class PageAdmin(admin.ModelAdmin): formfield_overrides = { - models.TextField: {'widget': Textarea(attrs={'rows':25, 'cols':40})}, + models.TextField: {'widget': Textarea(attrs={'rows': 25, 'cols': 40})}, } - list_display = ('title', 'slug',) + list_display = ('title', 'slug',) search_fields = ['title', 'body_markdown'] - prepopulated_fields = {"slug" : ('title',)} + prepopulated_fields = {"slug": ('title',)} fieldsets = ( ('Page', { - 'fields': ('title','body_markdown', 'slug'), - 'classes': ('show','extrapretty','wide') - }), + 'fields': ('title', 'body_markdown', 'slug'), + 'classes': ('show', 'extrapretty', 'wide') + }), ('Metadata', { 'classes': ('collapse closed',), - 'fields': ('meta_description',), + 'fields': ('meta_description',), }) ) - + admin.site.register(Page, PageAdmin) diff --git a/app/pages/models.py b/app/pages/models.py index fcc0e5a..2462b06 100644 --- a/app/pages/models.py +++ b/app/pages/models.py @@ -1,38 +1,31 @@ -import datetime from django.db import models -from django.conf import settings from django.contrib.sitemaps import Sitemap - import markdown -def markdown_processor(md): - return markdown.markdown(md, ['footnotes'],safe_mode = False) -TEMPLATES = ( - (0, 'single'), - (1, 'double'), - (2, 'single-dark'), - (3, 'double-dark'), - ) - +def markdown_processor(md): + return markdown.markdown(md, ['footnotes'], safe_mode=False) + + class Page(models.Model): title = models.CharField(max_length=200) slug = models.SlugField() body_html = models.TextField(blank=True) body_markdown = models.TextField() meta_description = models.CharField(max_length=256, null=True, blank=True) - + def __unicode__(self): return self.title def get_absolute_url(self): return "/%s/" % (self.slug) - - def save(self): + + def save(self): #run markdown self.body_html = markdown_processor(self.body_markdown) super(Page, self).save() + class PageSitemap(Sitemap): changefreq = "never" priority = 1.0 diff --git a/app/pages/views.py b/app/pages/views.py index a568f3b..c4a12e9 100644 --- a/app/pages/views.py +++ b/app/pages/views.py @@ -1,13 +1,9 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext -from django.conf import settings - - from pages.models import Page -def page(request,slug): - obj = get_object_or_404(Page, slug__exact=slug) - context = { 'object': obj,} - return render_to_response(["details/%s.html" % obj.slug, 'details/page.html'], context, context_instance = RequestContext(request)) - +def page(request, slug): + obj = get_object_or_404(Page, slug__exact=slug) + context = {'object': obj, } + return render_to_response(["details/%s.html" % obj.slug, 'details/page.html'], context, context_instance=RequestContext(request)) 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)) diff --git a/app/projects/admin.py b/app/projects/admin.py index e97a261..15c822a 100644 --- a/app/projects/admin.py +++ b/app/projects/admin.py @@ -1,8 +1,5 @@ from django.contrib import admin -from django import forms from django.contrib.gis.admin import OSMGeoAdmin -from django.contrib.gis.maps.google import GoogleMap -from django.conf import settings from projects.models.base import Project from projects.models.fiveby import FiveBy @@ -10,200 +7,110 @@ from projects.models.natparks import NationalParks from projects.models.gifs import AnimatedGif -GMAP = GoogleMap(key=settings.GOOGLE_MAPS_API_KEY) - class ProjectAdmin(OSMGeoAdmin): - - list_display = ('title', 'pub_date', 'status',) + list_display = ('title', 'pub_date', 'status',) search_fields = ['title', 'body_markdown'] - prepopulated_fields = {"slug" : ('title',)} + prepopulated_fields = {"slug": ('title',)} list_filter = ('pub_date', 'status') fieldsets = ( - ('Project', {'fields': ('title','subtitle','lede', 'pub_date', 'model_name',('status','image',), 'slug',), 'classes': ('show','extrapretty','wide')}), + ('Project', { + 'fields': ( + 'title', + 'subtitle', + 'lede', + 'pub_date', + 'model_name', + ('status', 'image'), + 'slug', + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), ) - + class Media: js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #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 = -9314310 - default_lat = 3991847 - default_zoom = 6 - #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 - 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 + class FiveByAdmin(OSMGeoAdmin): - - list_display = ('title', 'pub_date', 'status',) - search_fields = ['title',] - prepopulated_fields = {"slug" : ('title',)} + list_display = ('title', 'pub_date', 'status',) + search_fields = ['title'] + prepopulated_fields = {"slug": ('title',)} list_filter = ('pub_date', 'status') fieldsets = ( - ('Project', {'fields': ('title','lede', 'pub_date', 'status',('image','videoh264','videoogg'), 'slug',('vimeo_link','youtube_link'),('point','location','region')), 'classes': ('show','extrapretty','wide')}), + ('Project', {'fields': ('title', 'lede', 'pub_date', 'status', ('image', 'videoh264', 'videoogg'), 'slug', ('vimeo_link', 'youtube_link'), ('point', 'location', 'region')), 'classes': ('show', 'extrapretty', 'wide')}), ) - - - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #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 = -9314310 - default_lat = 3991847 + + # options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 default_zoom = 6 - #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 + 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' class NationalParksAdmin(OSMGeoAdmin): - - list_display = ('unit_name','type','state','name','visited', 'size') + list_display = ('unit_name', 'type', 'state', 'name', 'visited', 'size') list_filter = ('state', 'type') - search_fields = ['name',] + search_fields = ['name'] fieldsets = ( - ('Project', {'fields': ('name', 'tag_line',('state','visited'),'dek','date_visited_begin','date_visited_end','mpoly','image',('post','gallery'),('url','size','fee', 'camping_fee','date_park_created'),'zoom'), 'classes': ('show','extrapretty','wide')}), + ('Project', { + 'fields': ( + 'name', + 'tag_line', + ('state', 'visited'), + 'dek', + 'date_visited_begin', + 'date_visited_end', + 'mpoly', + 'image', + ('post', 'gallery'), + ('url', 'size', 'fee', 'camping_fee', 'date_park_created'), + 'zoom' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), ) - - - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #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 = -9314310 - default_lat = 3991847 + + # options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 default_zoom = 6 - #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 + 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' -from django.contrib import admin - -from projects.models.code import Code,CodeBlogEntry,CodeBlogDemo - -class CodeAdmin(admin.ModelAdmin): - list_display = ('name', 'date_created', 'status') - search_fields = ['name','body_html'] - list_filter = ['status',] - fieldsets = ( - (None, {'fields': ('name','date_created','slug','status','body_html')}), - ) - -class CodeBlogEntryAdmin(admin.ModelAdmin): - list_display = ('title', 'pub_date', 'status') - search_fields = ['name','body_markdown'] - list_filter = ['status',] - prepopulated_fields = {"slug" : ('title',)} - fieldsets = ( - (None, {'fields': ('title','body_markdown','pub_date','slug','status','enable_comments')}), - ) - -class CodeBlogDemoAdmin(admin.ModelAdmin): - list_display = ('title', 'pub_date', ) - search_fields = ['name','body'] - fieldsets = ( - (None, {'fields': ('title','slug','template','head','body')}), - ) class AnimatedGifAdmin(admin.ModelAdmin): list_display = ('title', 'date_created') - search_fields = ['title',] + search_fields = ['title'] fieldsets = ( - (None, {'fields': ('title','gif','date_created','slug','music_ogg','music_mp3')}), + (None, { + 'fields': ( + 'title', + 'gif', + 'date_created', + 'slug', + 'music_ogg', + 'music_mp3' + ) + }), ) - + admin.site.register(AnimatedGif, AnimatedGifAdmin) -admin.site.register(CodeBlogEntry, CodeBlogEntryAdmin) -admin.site.register(CodeBlogDemo, CodeBlogDemoAdmin) -admin.site.register(Code, CodeAdmin) admin.site.register(Project, ProjectAdmin) admin.site.register(FiveBy, FiveByAdmin) admin.site.register(NationalParks, NationalParksAdmin) diff --git a/app/projects/models/base.py b/app/projects/models/base.py index 26a0122..51379a0 100644 --- a/app/projects/models/base.py +++ b/app/projects/models/base.py @@ -1,26 +1,18 @@ import datetime from django.contrib.gis.db import models -from django.conf import settings from django.contrib.sitemaps import Sitemap -from django.template.defaultfilters import truncatewords_html -from django.contrib.syndication.views import Feed - import markdown -from photos.models import PhotoGallery -from locations.models import Location,Region - - def get_upload_path(self, filename): - return "images/project-thumbs/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/project-thumbs/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) -def markdown_processor(md): - html = markdown.markdown(md, safe_mode = False).split('<break>') + +def markdown_processor(md): + html = markdown.markdown(md, safe_mode=False).split('<break>') return html - class Project(models.Model): title = models.CharField(max_length=200) subtitle = models.CharField(max_length=200, null=True, blank=True) @@ -32,9 +24,9 @@ class Project(models.Model): (1, 'Published'), ) status = models.IntegerField(choices=PUB_STATUS, default=0) - image = models.FileField(upload_to=get_upload_path, null=True,blank=True) + image = models.FileField(upload_to=get_upload_path, null=True, blank=True) model_name = models.CharField(max_length=200, null=True) - + @property def longitude(self): '''Get the site's longitude.''' @@ -43,8 +35,8 @@ class Project(models.Model): @property def latitude(self): '''Get the site's latitude.''' - return self.point.y - + return self.point.y + class Meta: ordering = ('-pub_date',) get_latest_by = 'pub_date' @@ -55,14 +47,14 @@ class Project(models.Model): def get_absolute_url(self): return "/%s/%s/" % ('projects', self.slug) - + def get_previous_published(self): return self.get_previous_by_pub_date(status__exact=1) - + def get_next_published(self): return self.get_next_by_pub_date(status__exact=1) - - + + class ProjectSitemap(Sitemap): changefreq = "monthly" priority = 0.5 diff --git a/app/projects/models/fiveby.py b/app/projects/models/fiveby.py index 45aa21d..b6c7e33 100644 --- a/app/projects/models/fiveby.py +++ b/app/projects/models/fiveby.py @@ -1,25 +1,23 @@ import datetime from django.contrib.gis.db import models -from django.conf import settings -from django.contrib.sitemaps import Sitemap -from django.template.defaultfilters import truncatewords_html -from django.contrib.syndication.views import Feed +from locations.models import Location, Region -from locations.models import Location,Region def get_upload_path(self, filename): - return "images/projects/videos/5x5/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/projects/videos/5x5/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + def get_image_upload_path(self, filename): - return "images/projects/5x5/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) - + return "images/projects/5x5/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + class FiveBy(models.Model): title = models.CharField(max_length=200) slug = models.SlugField(unique_for_date='pub_date') lede = models.TextField(blank=True) - image = models.FileField(upload_to=get_image_upload_path, null=True,blank=True) - videoh264 = models.FileField(upload_to=get_upload_path, null=True,blank=True) - videoogg = models.FileField(upload_to=get_upload_path, null=True,blank=True) + image = models.FileField(upload_to=get_image_upload_path, null=True, blank=True) + videoh264 = models.FileField(upload_to=get_upload_path, null=True, blank=True) + videoogg = models.FileField(upload_to=get_upload_path, null=True, blank=True) vimeo_link = models.CharField(max_length=200) youtube_link = models.CharField(max_length=200) pub_date = models.DateTimeField('Date published') @@ -31,21 +29,19 @@ class FiveBy(models.Model): point = models.PointField(null=True) location = models.ForeignKey(Location, null=True) region = models.ForeignKey(Region, null=True) - - - + class Meta: ordering = ('-pub_date',) get_latest_by = 'pub_date' app_label = 'projects' verbose_name_plural = '5x5' - - def __unicode__(self): + + def __str__(self): return self.title def get_absolute_url(self): return "/%s/%s/%s/" % ('projects', '5x5', self.slug) - + @property def longitude(self): '''Get the site's longitude.''' @@ -54,5 +50,4 @@ class FiveBy(models.Model): @property def latitude(self): '''Get the site's latitude.''' - return self.point.y - + return self.point.y diff --git a/app/projects/models/gifs.py b/app/projects/models/gifs.py index e20530b..25b8734 100644 --- a/app/projects/models/gifs.py +++ b/app/projects/models/gifs.py @@ -3,7 +3,7 @@ from django.db import models def get_upload_path(self, filename): - return "images/projects/gifs/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/projects/gifs/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) class AnimatedGif(models.Model): @@ -18,8 +18,9 @@ class AnimatedGif(models.Model): verbose_name_plural = "Animated Gifs" app_label = 'projects' ordering = ('-date_created',) - # Returns the string representation of the model. - def __unicode__(self): + + def __str__(self): return self.slug + def get_absolute_url(self): - return '/projects/gifs/%s/' %(self.slug) + return '/projects/gifs/%s/' % (self.slug) diff --git a/app/projects/models/natparks.py b/app/projects/models/natparks.py index 11fe6bb..3615737 100644 --- a/app/projects/models/natparks.py +++ b/app/projects/models/natparks.py @@ -1,19 +1,13 @@ -from django.contrib.gis.db import models +import datetime from PIL import Image +from django.contrib.gis.db import models from blog.models import Entry from photos.models import PhotoGallery from locations.models import State -PUB_STATUS = ( - (0, 'Draft'), - (1, 'Published'), - ) - - -import datetime def get_upload_path(self, filename): - return "images/projects/np/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + return "images/projects/np/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) class NationalParks(models.Model): @@ -24,33 +18,34 @@ class NationalParks(models.Model): fee = models.CharField(max_length=5, null=True) camping_fee = models.CharField(max_length=10, null=True) url = models.CharField(max_length=250, null=True) - code= models.CharField(max_length=16) - unit_name= models.CharField(max_length=254) - date_visited_begin = models.DateField('Date Visited',null=True) - date_visited_end = models.DateField('Date Visited',null=True) - date_park_created = models.DateField('Date Park Created',null=True) - zoom= models.IntegerField(null=True) + code = models.CharField(max_length=16) + unit_name = models.CharField(max_length=254) + date_visited_begin = models.DateField('Date Visited', null=True) + date_visited_end = models.DateField('Date Visited', null=True) + date_park_created = models.DateField('Date Park Created', null=True) + zoom = models.IntegerField(null=True) mpoly = models.MultiPolygonField(null=True) visited = models.BooleanField(default=False) dek = models.TextField(null=True, blank=True) tag_line = models.CharField(max_length=254, null=True) post = models.ForeignKey(Entry, null=True) gallery = models.ForeignKey(PhotoGallery, blank=True, null=True, verbose_name='photo set') - image = models.FileField(upload_to=get_upload_path, null=True,blank=True,help_text="width: 980px, height: > 450px") - image_height = models.CharField(max_length=20, null=True,blank=True) - image_width = models.CharField(max_length=20, null=True,blank=True) + image = models.FileField(upload_to=get_upload_path, null=True, blank=True, + help_text="width: 980px, height: > 450px") + image_height = models.CharField(max_length=20, null=True, blank=True) + image_width = models.CharField(max_length=20, null=True, blank=True) objects = models.GeoManager() class Meta: verbose_name_plural = "National Parks" app_label = 'projects' - ordering = ('-visited','unit_name',) - # Returns the string representation of the model. - def __unicode__(self): + ordering = ('-visited', 'unit_name',) + + def __str__(self): return self.unit_name - def save(self): + def save(self): #get image dimensions img = Image.open(self.image) - self.image_width, self.image_height = img.size + self.image_width, self.image_height = img.size super(NationalParks, self).save() diff --git a/app/projects/shortcuts.py b/app/projects/shortcuts.py index 600e56d..7753d18 100644 --- a/app/projects/shortcuts.py +++ b/app/projects/shortcuts.py @@ -28,22 +28,22 @@ def a_shapes(request): mimetype=mimetype,
proj_transform=900913,
pretty_print=pretty_print
- )
-
+ )
+
def responses(qs,type_='countries',pretty_print=True,mimetype='text/plain'):
if type_ == 'locations':
qs = qs.geolocations()
- return render_to_geojson(qs,
- excluded_fields=['json'],
+ return render_to_geojson(qs,
+ excluded_fields=['json'],
geom_field='point',
proj_transform=900913,
mimetype=mimetype,
pretty_print=pretty_print
)
- elif type_ == 'affiliates':
+ elif type_ == 'affiliates':
qs = qs.exclude(geokeywords='').attach_locations()
return render_to_geojson(qs,
- included_fields=['id','_geokeywords_cache'],
+ included_fields=['id','_geokeywords_cache'],
geom_attribute='point',
extra_attributes=['name'],
proj_transform=900913,
@@ -57,11 +57,11 @@ def responses(qs,type_='countries',pretty_print=True,mimetype='text/plain'): #geom_attribute='point',
mimetype=mimetype,
pretty_print=pretty_print
- )
+ )
else:# type_ == 'countries' or type is None:
if len(qs) > 10:
# this is a limit, weird huh?
- # requires another all() otherwise it
+ # requires another all() otherwise it
# returns a list!
qs = qs.all()[:10]
return render_to_geojson(qs,
@@ -77,10 +77,10 @@ def responses(qs,type_='countries',pretty_print=True,mimetype='text/plain'): def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_attributes=[],mimetype='text/plain', pretty_print=False, excluded_fields=[],included_fields=[],proj_transform=None):
'''
-
+
Shortcut to render a GeoJson FeatureCollection from a Django QuerySet.
Currently computes a bbox and adds a crs member as a sr.org link
-
+
'''
excluded_fields.append('_state')
collection = {}
@@ -89,7 +89,7 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att query_set = [query_set]
else:
fields = query_set.model._meta.fields
-
+
if geom_attribute:
geometry_name = geom_attribute
geo_field = None
@@ -112,7 +112,7 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att else:
geo_fields = [f for f in fields if isinstance(f, GeometryField)]
-
+
#attempt to assign geom_field that was passed in
if geom_field:
#import pdb;pdb.set_trace()
@@ -126,15 +126,15 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att raise Exception('There appears to be no valid geometry on this model')
geo_field = geo_fields[0] # no support yet for multiple geometry fields
-
- #remove other geom fields from showing up in attributes
+
+ #remove other geom fields from showing up in attributes
if len(geo_fields) > 1:
for field in geo_fields:
if field.name not in excluded_fields:
excluded_fields.append(field.name)
geometry_name = geo_field.name
-
+
srid = geo_field.srid
@@ -148,10 +148,10 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att crs_properties = {}
crs_properties['href'] = 'http://spatialreference.org/ref/epsg/%s/' % to_srid
crs_properties['type'] = 'proj4'
- crs['properties'] = crs_properties
+ crs['properties'] = crs_properties
collection['crs'] = crs
collection['srid'] = to_srid
-
+
# Build list of features
features = []
if query_set.distinct():
@@ -199,14 +199,14 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att pass #features.append({'type':'Feature','geometry': {},'properties':{}})
# Label as FeatureCollection and add Features
- collection['type'] = "FeatureCollection"
+ collection['type'] = "FeatureCollection"
collection['features'] = features
-
+
# Attach extent of all features
if query_set:
ex = None
query_set.query.distinct = False
- if hasattr(query_set,'agg_extent'):
+ if hasattr(query_set,'agg_extent'):
ex = [x for x in query_set.agg_extent.tuple]
elif '.' in geometry_name:
prop, meth = geometry_name.split('.')
@@ -223,13 +223,13 @@ def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_att poly.transform(proj_transform)
ex = poly.extent
collection['bbox'] = ex
-
+
# Return response
response = HttpResponse()
if pretty_print:
response.write('%s' % simplejson.dumps(collection, indent=1))
else:
- response.write('%s' % simplejson.dumps(collection))
+ response.write('%s' % simplejson.dumps(collection))
response['Content-length'] = str(len(response.content))
response['Content-Type'] = mimetype
- return response
\ No newline at end of file + return response
diff --git a/app/projects/urls.py b/app/projects/urls.py index bd7c13d..f826624 100644 --- a/app/projects/urls.py +++ b/app/projects/urls.py @@ -9,7 +9,6 @@ urlpatterns = patterns('', (r'(?P<slug>[-\w]+)/$', 'projects.views.detail'), (r'^$', ListView.as_view( queryset=Project.objects.filter(status__exact=1).order_by('-pub_date'), - template_name = "archives/projects.html", + template_name="archives/projects.html", )), ) - diff --git a/app/projects/views.py b/app/projects/views.py index e9c755f..39ae781 100644 --- a/app/projects/views.py +++ b/app/projects/views.py @@ -1,21 +1,21 @@ -from django.shortcuts import render_to_response,get_object_or_404 +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.db.models import get_model -from django.http import HttpResponse -from django.core import serializers from projects.shortcuts import render_to_geojson -from projects.models.base import Project -from projects.models.fiveby import FiveBy from projects.models.natparks import NationalParks from projects.models.gifs import AnimatedGif -projects = {'5x5':'FiveBy','6x6':'SixBy','national-parks':'NationalParks','code':'Code'} +projects = { + '5x5': 'FiveBy', + '6x6': 'SixBy', + 'national-parks': 'NationalParks', + 'code': 'Code' +} -""" -Projects by slug -""" -def detail(request,slug): + +def detail(request, slug): + """Projects by slug""" name = projects[slug] model = get_model('projects', name) if slug == 'national-parks': @@ -23,13 +23,13 @@ def detail(request,slug): else: qs = model.objects.filter(status__exact=1) context = { - "object_list" : qs, - } - template = 'details/%s.html' %(slug) - return render_to_response(template, context, context_instance = RequestContext(request)) + "object_list": qs, + } + template = 'details/%s.html' % (slug) + return render_to_response(template, context, context_instance=RequestContext(request)) -def gif_detail(request,slug): +def gif_detail(request, slug): obj = get_object_or_404(AnimatedGif, slug__exact=slug) return render_to_response('details/gifs.html', {'object': obj}, context_instance=RequestContext(request)) @@ -38,9 +38,8 @@ def data_json(request, id): qs = NationalParks.objects.filter(pk=id) return render_to_geojson( qs, - included_fields=['id',], + included_fields=['id'], geom_attribute='mpoly', - mimetype = 'application/json', + mimetype='application/json', pretty_print=True - ) - + ) diff --git a/design/templates/admin/buttons.html b/design/templates/admin/buttons.html index d3a120f..aed7464 100644 --- a/design/templates/admin/buttons.html +++ b/design/templates/admin/buttons.html @@ -42,11 +42,10 @@ <ul class="grp-listing-small cust"> <li class="item"><a href="/admin/build/build?id=newpost">Build New Post</a></li> <li class="item"><a href="/admin/build/build?id=writing">Build Writing Archives</a></li> - <li class="item"><a href="/admin/build/build?id=photos">Build Photo Galleries</a></li> + <li class="item"><a href="/admin/build/build?id=photo_galleries">Build Photo Galleries</a></li> <li class="item"><a href="/admin/build/build?id=projects">Build Project Pages</a></li> <li class="item"><a href="/admin/build/build?id=map">Build Map</a></li> <li class="item"><a href="/admin/build/build?id=pages">Build All Pages</a></li> - <li class="item"><a href="/admin/build/build?id=home">Build Homepage</a></li> <li class="item"><a href="/admin/build/build?id=feed">Build RSS Feed</a></li> <li class="item"><a href="/admin/build/build?id=sitemap">Build Sitemap</a></li> <li class="item"><a href="/admin/build/build?id=all">Build Entire Site</a></li> |