From b1138f615315b3e90638c59b3f451a56297ae1ca Mon Sep 17 00:00:00 2001 From: Greg Thole Date: Mon, 15 Feb 2016 09:36:19 -0500 Subject: [PATCH] Switch to docker --- .gitignore | 6 +- Dockerfile | 10 + __init__.py | 7 - api.py | 44 -- docker-compose.yml | 42 ++ gedgo/__init__.py | 7 + admin.py => gedgo/admin.py | 0 forms.py => gedgo/forms.py | 0 gedcom_parser.py => gedgo/gedcom_parser.py | 0 gedcom_update.py => gedgo/gedcom_update.py | 34 +- {management => gedgo/management}/__init__.py | 0 .../management}/commands/__init__.py | 0 .../management}/commands/add_gedcom.py | 0 .../management}/commands/update_gedcom.py | 0 middleware.py => gedgo/middleware.py | 14 +- gedgo/migrations/0001_initial.py | 200 +++++++++ {migrations => gedgo/migrations}/__init__.py | 0 {models => gedgo/models}/__init__.py | 0 {models => gedgo/models}/blogpost.py | 2 - {models => gedgo/models}/document.py | 4 +- {models => gedgo/models}/documentary.py | 2 - {models => gedgo/models}/event.py | 0 {models => gedgo/models}/family.py | 2 +- {models => gedgo/models}/gedcom.py | 2 - {models => gedgo/models}/note.py | 0 {models => gedgo/models}/person.py | 4 +- .../static}/img/generic_person.gif | Bin {static => gedgo/static}/img/sad.jpg | Bin {static => gedgo/static}/js/pedigree.js | 0 {static => gedgo/static}/js/timeline.js | 0 .../static}/screenshots/individualview.png | Bin .../static}/screenshots/timeline.png | Bin .../static}/styles/style-default.css | 0 .../static}/styles/style-login.css | 0 gedgo/storages.py | 56 +++ tasks.py => gedgo/tasks.py | 6 +- {templates => gedgo/templates}/404.html | 0 {templates => gedgo/templates}/500.html | 0 .../templates}/admin/base_site.html | 0 {templates => gedgo/templates}/auth/base.html | 0 .../templates}/auth/login.html | 0 .../auth/password_reset_confirm.html | 0 .../templates}/auth/password_reset_done.html | 0 .../templates}/auth/password_reset_email.html | 0 .../templates}/default/base.html | 0 .../templates}/default/blogpost.html | 0 .../templates}/default/blogpost_list.html | 0 .../templates}/default/comment_form.html | 0 .../templates}/default/dashboard.html | 0 .../templates}/default/documentaries.html | 0 .../templates}/default/gedcom.html | 0 .../templates}/default/person-card.html | 0 .../templates}/default/person.html | 0 .../templates}/default/research.html | 17 +- .../templates}/default/search_results.html | 0 .../templates}/default/user_tracking.html | 0 tests.py => gedgo/tests.py | 0 gedgo/urls.py | 55 +++ {views => gedgo/views}/__init__.py | 0 {views => gedgo/views}/blog.py | 0 {views => gedgo/views}/dashboard.py | 33 +- {views => gedgo/views}/model_views.py | 0 gedgo/views/research.py | 78 ++++ {views => gedgo/views}/search.py | 0 {views => gedgo/views}/util.py | 60 +-- {views => gedgo/views}/visualizations.py | 0 manage.py | 10 + migrations/0001_initial.py | 399 ------------------ reqs.pip | 9 +- settings.py | 139 ++++++ static/test/test.ged | 80 ---- urls.py | 81 +--- views/research.py | 79 ---- 73 files changed, 733 insertions(+), 749 deletions(-) create mode 100644 Dockerfile delete mode 100644 api.py create mode 100644 docker-compose.yml create mode 100644 gedgo/__init__.py rename admin.py => gedgo/admin.py (100%) rename forms.py => gedgo/forms.py (100%) rename gedcom_parser.py => gedgo/gedcom_parser.py (100%) rename gedcom_update.py => gedgo/gedcom_update.py (91%) rename {management => gedgo/management}/__init__.py (100%) rename {management => gedgo/management}/commands/__init__.py (100%) rename {management => gedgo/management}/commands/add_gedcom.py (100%) rename {management => gedgo/management}/commands/update_gedcom.py (100%) rename middleware.py => gedgo/middleware.py (78%) create mode 100644 gedgo/migrations/0001_initial.py rename {migrations => gedgo/migrations}/__init__.py (100%) rename {models => gedgo/models}/__init__.py (100%) rename {models => gedgo/models}/blogpost.py (93%) rename {models => gedgo/models}/document.py (91%) rename {models => gedgo/models}/documentary.py (96%) rename {models => gedgo/models}/event.py (100%) rename {models => gedgo/models}/family.py (97%) rename {models => gedgo/models}/gedcom.py (96%) rename {models => gedgo/models}/note.py (100%) rename {models => gedgo/models}/person.py (96%) rename {static => gedgo/static}/img/generic_person.gif (100%) rename {static => gedgo/static}/img/sad.jpg (100%) rename {static => gedgo/static}/js/pedigree.js (100%) rename {static => gedgo/static}/js/timeline.js (100%) rename {static => gedgo/static}/screenshots/individualview.png (100%) rename {static => gedgo/static}/screenshots/timeline.png (100%) rename {static => gedgo/static}/styles/style-default.css (100%) rename {static => gedgo/static}/styles/style-login.css (100%) create mode 100644 gedgo/storages.py rename tasks.py => gedgo/tasks.py (95%) rename {templates => gedgo/templates}/404.html (100%) rename {templates => gedgo/templates}/500.html (100%) rename {templates => gedgo/templates}/admin/base_site.html (100%) rename {templates => gedgo/templates}/auth/base.html (100%) rename {templates => gedgo/templates}/auth/login.html (100%) rename {templates => gedgo/templates}/auth/password_reset_confirm.html (100%) rename {templates => gedgo/templates}/auth/password_reset_done.html (100%) rename {templates => gedgo/templates}/auth/password_reset_email.html (100%) rename {templates => gedgo/templates}/default/base.html (100%) rename {templates => gedgo/templates}/default/blogpost.html (100%) rename {templates => gedgo/templates}/default/blogpost_list.html (100%) rename {templates => gedgo/templates}/default/comment_form.html (100%) rename {templates => gedgo/templates}/default/dashboard.html (100%) rename {templates => gedgo/templates}/default/documentaries.html (100%) rename {templates => gedgo/templates}/default/gedcom.html (100%) rename {templates => gedgo/templates}/default/person-card.html (100%) rename {templates => gedgo/templates}/default/person.html (100%) rename {templates => gedgo/templates}/default/research.html (60%) rename {templates => gedgo/templates}/default/search_results.html (100%) rename {templates => gedgo/templates}/default/user_tracking.html (100%) rename tests.py => gedgo/tests.py (100%) create mode 100644 gedgo/urls.py rename {views => gedgo/views}/__init__.py (100%) rename {views => gedgo/views}/blog.py (100%) rename {views => gedgo/views}/dashboard.py (84%) rename {views => gedgo/views}/model_views.py (100%) create mode 100644 gedgo/views/research.py rename {views => gedgo/views}/search.py (100%) rename {views => gedgo/views}/util.py (69%) rename {views => gedgo/views}/visualizations.py (100%) create mode 100644 manage.py delete mode 100644 migrations/0001_initial.py create mode 100644 settings.py delete mode 100644 static/test/test.ged delete mode 100644 views/research.py diff --git a/.gitignore b/.gitignore index 0686785..baab8ce 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,8 @@ pip-log.txt *bootstrap*.js *bootstrap*.css -*d3.*.js \ No newline at end of file +*d3.*.js + +.files/ +*.ged +settings_local.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d94821c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:2.7 + +COPY ./ /src/ + +WORKDIR /src/ +RUN pip install -r reqs.pip + +RUN adduser --disabled-password --gecos '' gedgo +RUN chown -R gedgo:gedgo /src +USER gedgo diff --git a/__init__.py b/__init__.py index 75d82e3..e69de29 100644 --- a/__init__.py +++ b/__init__.py @@ -1,7 +0,0 @@ -from django.conf import settings -import redis - -REDIS = None -if hasattr(settings, 'GEDGO_REDIS_SERVER'): - REDIS = redis.StrictRedis(host=settings.GEDGO_REDIS_SERVER) - REDIS.ping() diff --git a/api.py b/api.py deleted file mode 100644 index 9f2f726..0000000 --- a/api.py +++ /dev/null @@ -1,44 +0,0 @@ -from tastypie.resources import ModelResource -from gedgo.models import Person, Family -from tastypie.authentication import BasicAuthentication -from tastypie.authorization import ReadOnlyAuthorization - -from functools import wraps - - -def add_photos(f): - @wraps(f) - def wrapper(self, bundle): - photos = bundle.obj.photos() - if not photos: - return bundle - images = map(lambda i: i.docfile.url, photos) - bundle.data['images'] = images - return bundle - return wrapper - - -class PersonResource(ModelResource): - class Meta: - list_allowed_methods = ['get'] - queryset = Person.objects.all() - resource_name = 'person' - authentication = BasicAuthentication() - authorization = ReadOnlyAuthorization() - - @add_photos - def dehydrate(self, bundle): - return bundle - - -class FamilyResource(ModelResource): - class Meta: - list_allowed_methods = ['get'] - queryset = Family.objects.all() - resource_name = 'family' - authentication = BasicAuthentication() - authorization = ReadOnlyAuthorization() - - @add_photos - def dehydrate(self, bundle): - return bundle diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e89d45a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +# Dev services +avahi: + image: 'enernoclabs/avahi:latest' + net: 'host' + log_driver: 'none' + restart: 'on-failure' +db: + image: 'mysql' + ports: + - '3306:3306' + environment: + MYSQL_ROOT_PASSWORD: 'docker' + MYSQL_DATABASE: 'gedgo' + MYSQL_USER: 'gedgo' + MYSQL_PASSWORD: 'gedgo' + log_driver: 'none' +redis: + image: 'redis' + ports: + - '6379' + log_driver: 'none' +# Application +app: + build: '.' + container_name: 'gedgo_app' + command: ['python', 'manage.py', 'runserver', '0.0.0.0:8000'] + volumes: + - './:/src' + ports: + - '8000:8000' + links: + - 'db' + - 'redis' +worker: + image: 'gedgo_app' + command: ['python', 'manage.py', 'celeryd', '-c', '1', '--loglevel=info'] + volumes: + - './:/src' + links: + - 'app' + - 'db' + - 'redis' diff --git a/gedgo/__init__.py b/gedgo/__init__.py new file mode 100644 index 0000000..ae6f887 --- /dev/null +++ b/gedgo/__init__.py @@ -0,0 +1,7 @@ +from django.conf import settings +import redis as Redis + +redis = None +if hasattr(settings, 'GEDGO_REDIS_SERVER'): + redis = Redis.StrictRedis(host=settings.GEDGO_REDIS_SERVER) + redis.ping() diff --git a/admin.py b/gedgo/admin.py similarity index 100% rename from admin.py rename to gedgo/admin.py diff --git a/forms.py b/gedgo/forms.py similarity index 100% rename from forms.py rename to gedgo/forms.py diff --git a/gedcom_parser.py b/gedgo/gedcom_parser.py similarity index 100% rename from gedcom_parser.py rename to gedgo/gedcom_parser.py diff --git a/gedcom_update.py b/gedgo/gedcom_update.py similarity index 91% rename from gedcom_update.py rename to gedgo/gedcom_update.py index 8687171..46226ca 100644 --- a/gedcom_update.py +++ b/gedgo/gedcom_update.py @@ -6,6 +6,7 @@ from django.utils import timezone from django.conf import settings from datetime import datetime +from dropbox.dropbox import Dropbox from re import findall from os import path, mkdir @@ -54,7 +55,7 @@ def update(g, file_name, verbose=True): g.save() -#--- Second Level script functions +# --- Second Level script functions def __process_all_relations(gedcom, parsed, verbose=True): if verbose: print ' Starting Person objects.' @@ -254,7 +255,7 @@ def __process_Document(entry, obj, g): else: thumb = None - known = Document.objects.filter(docfile=unicode(file_name)) + known = Document.objects.filter(docfile=file_name.decode('utf-8').strip()) if len(known) > 0: m = known[0] @@ -353,12 +354,20 @@ def __child_by_tag(entry, tag): return child +# TODO: Proper Storage class approach to this code def __valid_document_entry(e): - file_name = __child_value_by_tags(e, 'FILE') - img_presence = path.join(settings.MEDIA_ROOT, path.basename(file_name)) + file_name = __strip_files_directories(e) + media_file = path.join(settings.MEDIA_ROOT, file_name) + + # The file exists already + if isinstance(file_name, basestring) and file_name and \ + path.exists(media_file): + return True + + if __get_from_dropbox(file_name, media_file, ): + return True - return isinstance(file_name, basestring) and file_name and \ - path.exists(img_presence) + return False def __strip_files_directories(e): @@ -366,6 +375,19 @@ def __strip_files_directories(e): return path.basename(file_name) +def __get_from_dropbox(file_name, media_file_name): + if not getattr(settings, 'DROPBOX_ACCESS_TOKEN', None): + return False + d = Dropbox(settings.DROPBOX_ACCESS_TOKEN) + resource_path = path.join(settings.DROPBOX_BASE_PATH, file_name) + print ' .. %s' % resource_path + try: + d.files_download_to_file(media_file_name, resource_path) + return True + except: + return False + + def make_thumbnail(file_name): base_name = path.basename(file_name) dir_name = path.dirname(file_name) diff --git a/management/__init__.py b/gedgo/management/__init__.py similarity index 100% rename from management/__init__.py rename to gedgo/management/__init__.py diff --git a/management/commands/__init__.py b/gedgo/management/commands/__init__.py similarity index 100% rename from management/commands/__init__.py rename to gedgo/management/commands/__init__.py diff --git a/management/commands/add_gedcom.py b/gedgo/management/commands/add_gedcom.py similarity index 100% rename from management/commands/add_gedcom.py rename to gedgo/management/commands/add_gedcom.py diff --git a/management/commands/update_gedcom.py b/gedgo/management/commands/update_gedcom.py similarity index 100% rename from management/commands/update_gedcom.py rename to gedgo/management/commands/update_gedcom.py diff --git a/middleware.py b/gedgo/middleware.py similarity index 78% rename from middleware.py rename to gedgo/middleware.py index 0de3230..bd1ed43 100644 --- a/middleware.py +++ b/gedgo/middleware.py @@ -1,4 +1,4 @@ -from gedgo import REDIS +from gedgo import redis import json import time import re @@ -16,8 +16,8 @@ class SimpleTrackerMiddleware(object): """ def process_response(self, request, response): - # Don't process if REDIS isn't configured or non-200 response - if REDIS is None or response.status_code != 200: + # Don't process if redis isn't configured or non-200 response + if redis is None or response.status_code != 200: return response # Only track non-superuser visitors @@ -41,15 +41,15 @@ def process_response(self, request, response): 'path': request.path_info, 'time': int(time.time()) } - REDIS.lpush('gedgo_user_%d_page_views' % id_, json.dumps(page_view)) - REDIS.ltrim('gedgo_user_%d_page_views' % id_, 0, 100) + redis.lpush('gedgo_user_%d_page_views' % id_, json.dumps(page_view)) + redis.ltrim('gedgo_user_%d_page_views' % id_, 0, 100) return response def _increment_key(key_name): try: - pvc = int(REDIS.get(key_name)) + pvc = int(redis.get(key_name)) except TypeError: pvc = 0 - REDIS.set(key_name, pvc + 1) + redis.set(key_name, pvc + 1) diff --git a/gedgo/migrations/0001_initial.py b/gedgo/migrations/0001_initial.py new file mode 100644 index 0000000..0468a1f --- /dev/null +++ b/gedgo/migrations/0001_initial.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-12 06:49 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='BlogPost', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=60)), + ('body', models.TextField()), + ('created', models.DateTimeField(auto_now_add=True)), + ], + ), + migrations.CreateModel( + name='Document', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, max_length=40, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('docfile', models.FileField(upload_to=b'uploaded')), + ('last_updated', models.DateTimeField(auto_now_add=True)), + ('thumb', models.FileField(blank=True, null=True, upload_to=b'uploaded/thumbs')), + ('kind', models.CharField(choices=[(b'DOCUM', b'Document'), (b'VIDEO', b'Video'), (b'PHOTO', b'Image')], max_length=5)), + ], + ), + migrations.CreateModel( + name='Documentary', + fields=[ + ('title', models.CharField(max_length=100, primary_key=True, serialize=False)), + ('tagline', models.CharField(max_length=100)), + ('location', models.CharField(blank=True, max_length=100, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('last_updated', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'verbose_name_plural': 'Documentaries', + }, + ), + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField(null=True)), + ('year_range_end', models.IntegerField(null=True)), + ('date_format', models.CharField(max_length=10, null=True)), + ('date_approxQ', models.BooleanField(verbose_name=b'Date is approximate')), + ('place', models.CharField(max_length=50)), + ], + ), + migrations.CreateModel( + name='Family', + fields=[ + ('pointer', models.CharField(max_length=10, primary_key=True, serialize=False)), + ('kind', models.CharField(blank=True, max_length=10, null=True, verbose_name=b'Event')), + ], + ), + migrations.CreateModel( + name='Gedcom', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file_name', models.CharField(blank=True, max_length=40, null=True)), + ('title', models.CharField(blank=True, max_length=40, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('last_updated', models.DateTimeField()), + ('key_families', models.ManyToManyField(blank=True, related_name='gedcom_key_families', to='gedgo.Family')), + ], + ), + migrations.CreateModel( + name='Note', + fields=[ + ('pointer', models.CharField(max_length=10, primary_key=True, serialize=False)), + ('text', models.TextField()), + ('gedcom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom')), + ], + ), + migrations.CreateModel( + name='Person', + fields=[ + ('pointer', models.CharField(max_length=10, primary_key=True, serialize=False)), + ('first_name', models.CharField(max_length=255)), + ('last_name', models.CharField(max_length=255)), + ('prefix', models.CharField(max_length=255)), + ('suffix', models.CharField(max_length=255)), + ('education', models.TextField(null=True)), + ('religion', models.CharField(blank=True, max_length=255, null=True)), + ('birth', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='person_birth', to='gedgo.Event')), + ('child_family', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='person_child_family', to='gedgo.Family')), + ('death', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='person_death', to='gedgo.Event')), + ('gedcom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom')), + ('notes', models.ManyToManyField(blank=True, to='gedgo.Note')), + ('profile', models.ManyToManyField(blank=True, to='gedgo.Document')), + ('spousal_families', models.ManyToManyField(related_name='person_spousal_families', to='gedgo.Family')), + ], + options={ + 'verbose_name_plural': 'People', + }, + ), + migrations.AddField( + model_name='gedcom', + name='key_people', + field=models.ManyToManyField(blank=True, related_name='gedcom_key_people', to='gedgo.Person'), + ), + migrations.AddField( + model_name='family', + name='children', + field=models.ManyToManyField(related_name='family_children', to='gedgo.Person'), + ), + migrations.AddField( + model_name='family', + name='gedcom', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom'), + ), + migrations.AddField( + model_name='family', + name='husbands', + field=models.ManyToManyField(related_name='family_husbands', to='gedgo.Person'), + ), + migrations.AddField( + model_name='family', + name='joined', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='family_joined', to='gedgo.Event'), + ), + migrations.AddField( + model_name='family', + name='notes', + field=models.ManyToManyField(blank=True, to='gedgo.Note'), + ), + migrations.AddField( + model_name='family', + name='separated', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='family_separated', to='gedgo.Event'), + ), + migrations.AddField( + model_name='family', + name='wives', + field=models.ManyToManyField(related_name='family_wives', to='gedgo.Person'), + ), + migrations.AddField( + model_name='event', + name='gedcom', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom'), + ), + migrations.AddField( + model_name='documentary', + name='gedcom', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom'), + ), + migrations.AddField( + model_name='documentary', + name='tagged_families', + field=models.ManyToManyField(blank=True, related_name='documentaries_tagged_families', to='gedgo.Family'), + ), + migrations.AddField( + model_name='documentary', + name='tagged_people', + field=models.ManyToManyField(blank=True, related_name='documentaries_tagged_people', to='gedgo.Person'), + ), + migrations.AddField( + model_name='documentary', + name='thumb', + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='documentaries_thumb', to='gedgo.Document'), + ), + migrations.AddField( + model_name='document', + name='gedcom', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='gedgo.Gedcom'), + ), + migrations.AddField( + model_name='document', + name='tagged_families', + field=models.ManyToManyField(blank=True, related_name='media_tagged_families', to='gedgo.Family'), + ), + migrations.AddField( + model_name='document', + name='tagged_people', + field=models.ManyToManyField(blank=True, related_name='media_tagged_people', to='gedgo.Person'), + ), + migrations.AddField( + model_name='blogpost', + name='tagged_people', + field=models.ManyToManyField(blank=True, related_name='blogpost_tagged_people', to='gedgo.Person'), + ), + migrations.AddField( + model_name='blogpost', + name='tagged_photos', + field=models.ManyToManyField(blank=True, related_name='blogpost_tagged_photos', to='gedgo.Document'), + ), + ] diff --git a/migrations/__init__.py b/gedgo/migrations/__init__.py similarity index 100% rename from migrations/__init__.py rename to gedgo/migrations/__init__.py diff --git a/models/__init__.py b/gedgo/models/__init__.py similarity index 100% rename from models/__init__.py rename to gedgo/models/__init__.py diff --git a/models/blogpost.py b/gedgo/models/blogpost.py similarity index 93% rename from models/blogpost.py rename to gedgo/models/blogpost.py index 898a077..d048e93 100644 --- a/models/blogpost.py +++ b/gedgo/models/blogpost.py @@ -12,13 +12,11 @@ class Meta: tagged_photos = models.ManyToManyField( 'Document', related_name='blogpost_tagged_photos', - null=True, blank=True ) tagged_people = models.ManyToManyField( 'Person', related_name='blogpost_tagged_people', - null=True, blank=True ) diff --git a/models/document.py b/gedgo/models/document.py similarity index 91% rename from models/document.py rename to gedgo/models/document.py index 2753f5a..92759df 100644 --- a/models/document.py +++ b/gedgo/models/document.py @@ -24,11 +24,11 @@ class Meta: ) tagged_people = models.ManyToManyField( 'Person', - related_name='media_tagged_people', null=True, blank=True + related_name='media_tagged_people', blank=True ) tagged_families = models.ManyToManyField( 'Family', - related_name='media_tagged_families', null=True, blank=True + related_name='media_tagged_families', blank=True ) def __unicode__(self): diff --git a/models/documentary.py b/gedgo/models/documentary.py similarity index 96% rename from models/documentary.py rename to gedgo/models/documentary.py index 4a7b92a..bf2d000 100644 --- a/models/documentary.py +++ b/gedgo/models/documentary.py @@ -21,13 +21,11 @@ class Meta: tagged_people = models.ManyToManyField( 'Person', related_name='documentaries_tagged_people', - null=True, blank=True ) tagged_families = models.ManyToManyField( 'Family', related_name='documentaries_tagged_families', - null=True, blank=True ) diff --git a/models/event.py b/gedgo/models/event.py similarity index 100% rename from models/event.py rename to gedgo/models/event.py diff --git a/models/family.py b/gedgo/models/family.py similarity index 97% rename from models/family.py rename to gedgo/models/family.py index e361753..9e9c9c0 100644 --- a/models/family.py +++ b/gedgo/models/family.py @@ -13,7 +13,7 @@ class Meta: wives = models.ManyToManyField('Person', related_name='family_wives') children = models.ManyToManyField('Person', related_name='family_children') - notes = models.ManyToManyField('Note', null=True) + notes = models.ManyToManyField('Note', blank=True) kind = models.CharField('Event', max_length=10, blank=True, null=True) joined = models.ForeignKey( diff --git a/models/gedcom.py b/gedgo/models/gedcom.py similarity index 96% rename from models/gedcom.py rename to gedgo/models/gedcom.py index 492cc2f..703c58e 100644 --- a/models/gedcom.py +++ b/gedgo/models/gedcom.py @@ -16,13 +16,11 @@ class Meta: key_people = models.ManyToManyField( 'Person', related_name='gedcom_key_people', - null=True, blank=True ) key_families = models.ManyToManyField( 'Family', related_name='gedcom_key_families', - null=True, blank=True ) diff --git a/models/note.py b/gedgo/models/note.py similarity index 100% rename from models/note.py rename to gedgo/models/note.py diff --git a/models/person.py b/gedgo/models/person.py similarity index 96% rename from models/person.py rename to gedgo/models/person.py index 54ad62e..c3a18d7 100644 --- a/models/person.py +++ b/gedgo/models/person.py @@ -49,10 +49,10 @@ class Meta: ) # Notes - notes = models.ManyToManyField('Note', null=True) + notes = models.ManyToManyField('Note', blank=True) # Profile - profile = models.ManyToManyField('Document', null=True, blank=True) + profile = models.ManyToManyField('Document', blank=True) def __unicode__(self): return '%s, %s (%s)' % (self.last_name, self.first_name, self.pointer) diff --git a/static/img/generic_person.gif b/gedgo/static/img/generic_person.gif similarity index 100% rename from static/img/generic_person.gif rename to gedgo/static/img/generic_person.gif diff --git a/static/img/sad.jpg b/gedgo/static/img/sad.jpg similarity index 100% rename from static/img/sad.jpg rename to gedgo/static/img/sad.jpg diff --git a/static/js/pedigree.js b/gedgo/static/js/pedigree.js similarity index 100% rename from static/js/pedigree.js rename to gedgo/static/js/pedigree.js diff --git a/static/js/timeline.js b/gedgo/static/js/timeline.js similarity index 100% rename from static/js/timeline.js rename to gedgo/static/js/timeline.js diff --git a/static/screenshots/individualview.png b/gedgo/static/screenshots/individualview.png similarity index 100% rename from static/screenshots/individualview.png rename to gedgo/static/screenshots/individualview.png diff --git a/static/screenshots/timeline.png b/gedgo/static/screenshots/timeline.png similarity index 100% rename from static/screenshots/timeline.png rename to gedgo/static/screenshots/timeline.png diff --git a/static/styles/style-default.css b/gedgo/static/styles/style-default.css similarity index 100% rename from static/styles/style-default.css rename to gedgo/static/styles/style-default.css diff --git a/static/styles/style-login.css b/gedgo/static/styles/style-login.css similarity index 100% rename from static/styles/style-login.css rename to gedgo/static/styles/style-login.css diff --git a/gedgo/storages.py b/gedgo/storages.py new file mode 100644 index 0000000..9c28e1e --- /dev/null +++ b/gedgo/storages.py @@ -0,0 +1,56 @@ +from django.core.files.storage import Storage +from django.utils._os import safe_join +from django.conf import settings + +import os +from dropbox.client import DropboxClient + + +class DropboxStorage(Storage): + def __init__(self, *args, **kwargs): + self.client = DropboxClient(settings.DROPBOX_ACCESS_TOKEN) + self.location = kwargs.get('location', settings.MEDIA_ROOT) + + def path(self, name): + return safe_join(self.location, name) + + def created_time(self, name): + raise NotImplementedError + + def exists(self, name): + raise NotImplementedError + + def get_available_name(self, name): + raise NotImplementedError + + def get_valid_name(self, name): + raise NotImplementedError + + def listdir(self, path): + meta = self.client.metadata(self.path(path)) + directories, files = [], [] + for entry in meta['contents']: + name = os.path.basename(entry['path']) + if entry['is_dir']: + directories.append(name) + else: + files.append(name) + return (directories, files) + + def preview(self, name): + return self.client.thumbnail(self.path(name)).read() + + def modified_time(self, name): + raise NotImplementedError + + def open(self, name, mode='rb'): + raise NotImplementedError + + def save(self, name, content, max_length=None): + raise NotImplementedError + + def size(self, name): + raise NotImplementedError + + def url(self, name): + return self.client.media(self.path(name))['url'] diff --git a/tasks.py b/gedgo/tasks.py similarity index 95% rename from tasks.py rename to gedgo/tasks.py index 2439189..bb2a342 100644 --- a/tasks.py +++ b/gedgo/tasks.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from gedgo.gedcom_update import update -from gedgo import REDIS +from gedgo import redis from gedgo.models import Gedcom import os from celery import Celery @@ -63,12 +63,12 @@ def async_update(gedcom_id, file_name, recipient_ids, @app.task def geo_resolve_ip(ip_address): - if REDIS is None: + if redis is None: return try: response = requests.get('ipinfo.io/%s/json' % ip_address) j = response.json() j['requested'] = datetime.utcnow().isoformat() - REDIS.set('gedgo_ip_%s', json.dumps(j)) + redis.set('gedgo_ip_%s', json.dumps(j)) except (requests.exceptions.RequestsException, ValueError): return diff --git a/templates/404.html b/gedgo/templates/404.html similarity index 100% rename from templates/404.html rename to gedgo/templates/404.html diff --git a/templates/500.html b/gedgo/templates/500.html similarity index 100% rename from templates/500.html rename to gedgo/templates/500.html diff --git a/templates/admin/base_site.html b/gedgo/templates/admin/base_site.html similarity index 100% rename from templates/admin/base_site.html rename to gedgo/templates/admin/base_site.html diff --git a/templates/auth/base.html b/gedgo/templates/auth/base.html similarity index 100% rename from templates/auth/base.html rename to gedgo/templates/auth/base.html diff --git a/templates/auth/login.html b/gedgo/templates/auth/login.html similarity index 100% rename from templates/auth/login.html rename to gedgo/templates/auth/login.html diff --git a/templates/auth/password_reset_confirm.html b/gedgo/templates/auth/password_reset_confirm.html similarity index 100% rename from templates/auth/password_reset_confirm.html rename to gedgo/templates/auth/password_reset_confirm.html diff --git a/templates/auth/password_reset_done.html b/gedgo/templates/auth/password_reset_done.html similarity index 100% rename from templates/auth/password_reset_done.html rename to gedgo/templates/auth/password_reset_done.html diff --git a/templates/auth/password_reset_email.html b/gedgo/templates/auth/password_reset_email.html similarity index 100% rename from templates/auth/password_reset_email.html rename to gedgo/templates/auth/password_reset_email.html diff --git a/templates/default/base.html b/gedgo/templates/default/base.html similarity index 100% rename from templates/default/base.html rename to gedgo/templates/default/base.html diff --git a/templates/default/blogpost.html b/gedgo/templates/default/blogpost.html similarity index 100% rename from templates/default/blogpost.html rename to gedgo/templates/default/blogpost.html diff --git a/templates/default/blogpost_list.html b/gedgo/templates/default/blogpost_list.html similarity index 100% rename from templates/default/blogpost_list.html rename to gedgo/templates/default/blogpost_list.html diff --git a/templates/default/comment_form.html b/gedgo/templates/default/comment_form.html similarity index 100% rename from templates/default/comment_form.html rename to gedgo/templates/default/comment_form.html diff --git a/templates/default/dashboard.html b/gedgo/templates/default/dashboard.html similarity index 100% rename from templates/default/dashboard.html rename to gedgo/templates/default/dashboard.html diff --git a/templates/default/documentaries.html b/gedgo/templates/default/documentaries.html similarity index 100% rename from templates/default/documentaries.html rename to gedgo/templates/default/documentaries.html diff --git a/templates/default/gedcom.html b/gedgo/templates/default/gedcom.html similarity index 100% rename from templates/default/gedcom.html rename to gedgo/templates/default/gedcom.html diff --git a/templates/default/person-card.html b/gedgo/templates/default/person-card.html similarity index 100% rename from templates/default/person-card.html rename to gedgo/templates/default/person-card.html diff --git a/templates/default/person.html b/gedgo/templates/default/person.html similarity index 100% rename from templates/default/person.html rename to gedgo/templates/default/person.html diff --git a/templates/default/research.html b/gedgo/templates/default/research.html similarity index 60% rename from templates/default/research.html rename to gedgo/templates/default/research.html index 8fae9cb..181aba4 100644 --- a/templates/default/research.html +++ b/gedgo/templates/default/research.html @@ -23,12 +23,23 @@ {% endif %}

{{ current_level }}

+
+ + {% endblock %} diff --git a/templates/default/search_results.html b/gedgo/templates/default/search_results.html similarity index 100% rename from templates/default/search_results.html rename to gedgo/templates/default/search_results.html diff --git a/templates/default/user_tracking.html b/gedgo/templates/default/user_tracking.html similarity index 100% rename from templates/default/user_tracking.html rename to gedgo/templates/default/user_tracking.html diff --git a/tests.py b/gedgo/tests.py similarity index 100% rename from tests.py rename to gedgo/tests.py diff --git a/gedgo/urls.py b/gedgo/urls.py new file mode 100644 index 0000000..a68de07 --- /dev/null +++ b/gedgo/urls.py @@ -0,0 +1,55 @@ +from django.conf.urls import url +from django.shortcuts import redirect +from django.contrib.auth.views import password_reset, password_reset_done, \ + password_reset_confirm + +from gedgo import views + +urlpatterns = [ + url( + r'^(?P\d+)/(?PI\d+)/$', + views.person, + name='person' + ), + url(r'^(?P\d+)/$', views.gedcom, name='gedcom'), + + # XHR Data views + url(r'^(?P\d+)/pedigree/(?PI\d+)/$', views.pedigree), + url(r'^(?P\d+)/timeline/(?PI\d+)/$', views.timeline), + url(r'^dashboard/worker/status$', views.worker_status), + + url(r'^blog/$', views.blog_list), + url(r'^blog/(?P\d+)/(?P\d+)/$', views.blog), + url(r'^blog/post/(?P\d+)/$', views.blogpost), + url(r'^documentaries/$', views.documentaries), + url(r'^research/(?P.*)$', views.research), + url(r'^search/$', views.search), + url(r'^dashboard/$', views.dashboard), + url(r'^dashboard/user/(?P\d+)/$', views.user_tracking), + + # Auth + url(r'^logout/$', views.logout_view), + url(r'^password_reset/$', + password_reset, + { + 'template_name': 'auth/login.html', + 'email_template_name': 'auth/password_reset_email.html', + 'post_reset_redirect': '/gedgo/password_reset/done/' + }), + url(r'^password_reset/done/$', + password_reset_done, + { + 'template_name': 'auth/password_reset_done.html' + }), + url(r'^password_reset/(?P[0-9A-Za-z]+)-(?P.+)/$', + password_reset_confirm, + { + 'post_reset_redirect': '/', + 'template_name': 'auth/password_reset_confirm.html' + }), + + # Backup media fileserve view + url(r'^media/(?P.*)$', views.media), + + url(r'^$', lambda r: redirect('/gedgo/1/')), +] diff --git a/views/__init__.py b/gedgo/views/__init__.py similarity index 100% rename from views/__init__.py rename to gedgo/views/__init__.py diff --git a/views/blog.py b/gedgo/views/blog.py similarity index 100% rename from views/blog.py rename to gedgo/views/blog.py diff --git a/views/dashboard.py b/gedgo/views/dashboard.py similarity index 84% rename from views/dashboard.py rename to gedgo/views/dashboard.py index 1e9b59b..f3cb671 100644 --- a/views/dashboard.py +++ b/gedgo/views/dashboard.py @@ -2,7 +2,7 @@ from gedgo.tasks import app, async_update from gedgo.views.util import render from gedgo.models import Gedcom -from gedgo import REDIS +from gedgo import redis from django.http import Http404, HttpResponse from django.contrib.auth.decorators import login_required @@ -10,7 +10,6 @@ from django.core.files.storage import default_storage from django.contrib import messages from django.shortcuts import redirect -from django.contrib.sites.models import get_current_site from django.conf import settings from django.shortcuts import get_object_or_404 @@ -37,7 +36,7 @@ def dashboard(request): if form is None: form = UpdateForm() - # Collect tracking stats from Redis storage + # Collect tracking stats from redis storage tracking_start, user_views, total = _page_view_stats() # Render list page with the documents and the form @@ -77,11 +76,11 @@ def user_tracking(request, user_id): raise Http404 user = get_object_or_404(User, id=user_id) - count = REDIS.keys('gedgo_user_%d_page_view_count' % user.id) + count = redis.keys('gedgo_user_%d_page_view_count' % user.id) if not count: raise Http404 - views = REDIS.lrange('gedgo_user_%d_page_views' % user.id, 0, -1) + views = redis.lrange('gedgo_user_%d_page_views' % user.id, 0, -1) views = [_load_page_view(v) for v in views] return render( @@ -105,7 +104,7 @@ def _handle_upload(request, form): os.path.join(settings.MEDIA_ROOT, file_name), form.cleaned_data['email_users'], form.cleaned_data['message'], - get_current_site(request).domain, + request.get_host(), request.user.id ) messages.success( @@ -122,29 +121,29 @@ def _handle_upload(request, form): def _reset_tracking(): - if REDIS is None: + if redis is None: return {} - keys = REDIS.keys('gedgo_*') + keys = redis.keys('gedgo_*') for key in keys: - REDIS.delete(key) + redis.delete(key) - REDIS.set('gedgo_tracking_start', int(time.time())) + redis.set('gedgo_tracking_start', int(time.time())) def _page_view_stats(): - if REDIS is None: - return {} + if redis is None: + return datetime.datetime.utcnow(), {}, 0 - user_keys = REDIS.keys('gedgo_user_*_page_view_count') + user_keys = redis.keys('gedgo_user_*_page_view_count') users = User.objects.filter( id__in=[int(k.split('_')[2]) for k in user_keys] ) user_views = [] for user in users: - last = REDIS.lrange('gedgo_user_%d_page_views' % user.id, 0, 0)[0] - pvc = REDIS.get('gedgo_user_%d_page_view_count' % user.id) + last = redis.lrange('gedgo_user_%d_page_views' % user.id, 0, 0)[0] + pvc = redis.get('gedgo_user_%d_page_view_count' % user.id) user_views.append({ 'user': user, 'last_view': _load_page_view(last)['timestamp'], @@ -154,7 +153,7 @@ def _page_view_stats(): tracking_start = _timestamp_from_redis('gedgo_tracking_start') - return tracking_start, user_views, REDIS.get('gedgo_page_view_count') + return tracking_start, user_views, redis.get('gedgo_page_view_count') def _load_page_view(json_str): @@ -165,7 +164,7 @@ def _load_page_view(json_str): def _timestamp_from_redis(key): try: - timestamp = REDIS.get(key) + timestamp = redis.get(key) return datetime.datetime.fromtimestamp(int(timestamp)) except: pass diff --git a/views/model_views.py b/gedgo/views/model_views.py similarity index 100% rename from views/model_views.py rename to gedgo/views/model_views.py diff --git a/gedgo/views/research.py b/gedgo/views/research.py new file mode 100644 index 0000000..35bd772 --- /dev/null +++ b/gedgo/views/research.py @@ -0,0 +1,78 @@ +from django.conf import settings +from django.http import Http404, HttpResponseRedirect +from django.contrib.auth.decorators import login_required +from django.utils.module_loading import import_string + +from os import path +import mimetypes + +from gedgo.views.util import render + + +storage = None +if getattr(settings, 'GEDGO_RESEARCH_FILE_STORAGE', None): + storage = import_string(settings.GEDGO_RESEARCH_FILE_STORAGE)( + location=settings.GEDGO_RESEARCH_FILE_ROOT) + + +@login_required +def research(request, pathname): + if storage is None: + raise Http404 + + name = pathname.strip('/') + + # Serve the content through xsendfile or directly. + try: + if '.' in name: + return HttpResponseRedirect(storage.url(name)) + else: + directories, files = storage.listdir(name) + directories = [__process(name, d, True) for d in directories] + files = [__process(name, f, False) for f in files] + + # Build a depth tree of the directories above this one for + # navigation + levels = [('Research Files', '')] + if name: + lp = '' + for l in name.split('/'): + lp = '%s/%s' % (lp, l) + levels.append((l, lp)) + + return render( + request, + 'research.html', + { + 'directories': directories, + 'files': files, + 'levels': levels + } + ) + except Exception as e: + raise e + raise Http404 + + +def __process(name, p, is_dir=False): + type_ = 'folder_open' if is_dir else _get_type(p) + return { + 'type': type_, + 'path': path.join(name, p), + 'name': p, + 'preview': type_ == 'image' + } + +# glyphicon name mappings +MIMETYPE_MAPPING = { + 'video': 'facetime-video', + 'audio': 'volume-up', + 'image': 'picture' +} + + +def _get_type(c): + guess, _ = mimetypes.guess_type(c) + if guess and guess.split('/')[0] in MIMETYPE_MAPPING: + return MIMETYPE_MAPPING[guess.split('/')[0]] + return 'file' diff --git a/views/search.py b/gedgo/views/search.py similarity index 100% rename from views/search.py rename to gedgo/views/search.py diff --git a/views/util.py b/gedgo/views/util.py similarity index 69% rename from views/util.py rename to gedgo/views/util.py index 2751fa6..0436c58 100644 --- a/views/util.py +++ b/gedgo/views/util.py @@ -1,10 +1,9 @@ -from django.http import HttpResponse -from django.core.servers.basehttp import FileWrapper +from wsgiref.util import FileWrapper +from django.http import HttpResponse, HttpResponseRedirect from django.core.files.storage import default_storage from django.contrib.auth.decorators import login_required from django.http import Http404 from django.conf import settings -from django.contrib.sites.models import get_current_site from django.shortcuts import redirect from django.contrib.auth import logout from django.contrib import messages @@ -25,8 +24,8 @@ def media(request, file_base_name): it's much better to have a webserver handle this through an authenticated proxy """ - filename = path.join(settings.MEDIA_ROOT, file_base_name.strip('/')) - return serve_content(filename) + filename = file_base_name.strip('/') + return serve_content(request, filename) def process_comments(request, noun): @@ -83,12 +82,12 @@ def site_context(request): show_blog = BlogPost.objects.exists() show_documentaries = Documentary.objects.exists() show_researchfiles = isinstance( - getattr(settings, 'RESEARCH_FILES_ROOT', None), + getattr(settings, 'GEDGO_RESEARCH_FILE_ROOT', None), basestring ) show_file_uploads = getattr( settings, 'GEDGO_ALLOW_FILE_UPLOADS', True) is True - site_title = get_current_site(request).name + site_title = settings.GEDGO_SITE_TITLE user = request.user return { @@ -101,31 +100,40 @@ def site_context(request): } -def serve_content(filename): +def serve_content(request, filename): """ Generate a response to server protected content. http://djangosnippets.org/snippets/365/ http://www.chicagodjango.com/blog/permission-based-file-serving/ """ - if not path.exists(filename): - raise Http404 - media_server = getattr(settings, 'GEDGO_MEDIA_SERVER', '').lower() - if media_server == 'apache': - response = HttpResponse() - response['X-Sendfile'] = filename - elif media_server == 'nginx': - response = HttpResponse() - response['X-Accel-Redirect'] = filename + storage_class = default_storage.__class__.__name__ + if storage_class == 'FileSystemStorage': + file_path = default_storage.path(filename) + if not default_storage.exists(filename): + raise Http404 + if settings.DEBUG: + # Serve it ourselves in debug mode only + wrapper = FileWrapper(file(file_path)) + response = HttpResponse(wrapper) + else: + # Set sendfile headers + response['X-Sendfile'] = file_path # apache + response['X-Accel-Redirect'] = file_path # nginx + response = HttpResponse() + file_type = mimetypes.guess_type(filename)[0] + response['Content-Type'] = file_type + response['Content-Length'] = path.getsize(file_path) + if file_type is None: + response['Content-Disposition'] = "attachment; filename=%s;" % ( + path.basename(filename)) + return response else: - wrapper = FileWrapper(file(filename)) - response = HttpResponse(wrapper) - file_type = mimetypes.guess_type(filename)[0] - response['Content-Type'] = file_type - response['Content-Length'] = path.getsize(filename) - if file_type is None: - response['Content-Disposition'] = "attachment; filename=%s;" % ( - path.basename(filename)) - return response + # Other storages we'll use the url attribute + try: + url = default_storage.url(filename) + return HttpResponseRedirect(url) + except Exception as e: + raise e # Http404 def logout_view(request): diff --git a/views/visualizations.py b/gedgo/views/visualizations.py similarity index 100% rename from views/visualizations.py rename to gedgo/views/visualizations.py diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..f9726f9 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py deleted file mode 100644 index 773b5f0..0000000 --- a/migrations/0001_initial.py +++ /dev/null @@ -1,399 +0,0 @@ -# -*- coding: utf-8 -*- -# flake8: noqa - -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding model 'Document' - db.create_table('gedgo_document', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), - ('docfile', self.gf('django.db.models.fields.files.FileField')(max_length=100)), - ('thumb', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True)), - ('kind', self.gf('django.db.models.fields.CharField')(max_length=5)), - ('last_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'], null=True, blank=True)), - )) - db.send_create_signal('gedgo', ['Document']) - - # Adding M2M table for field tagged_people on 'Document' - m2m_table_name = db.shorten_name('gedgo_document_tagged_people') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('document', models.ForeignKey(orm['gedgo.document'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['document_id', 'person_id']) - - # Adding M2M table for field tagged_families on 'Document' - m2m_table_name = db.shorten_name('gedgo_document_tagged_families') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('document', models.ForeignKey(orm['gedgo.document'], null=False)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)) - )) - db.create_unique(m2m_table_name, ['document_id', 'family_id']) - - # Adding model 'Gedcom' - db.create_table('gedgo_gedcom', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('file_name', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), - ('last_updated', self.gf('django.db.models.fields.DateTimeField')()), - )) - db.send_create_signal('gedgo', ['Gedcom']) - - # Adding M2M table for field key_people on 'Gedcom' - m2m_table_name = db.shorten_name('gedgo_gedcom_key_people') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('gedcom', models.ForeignKey(orm['gedgo.gedcom'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['gedcom_id', 'person_id']) - - # Adding M2M table for field key_families on 'Gedcom' - m2m_table_name = db.shorten_name('gedgo_gedcom_key_families') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('gedcom', models.ForeignKey(orm['gedgo.gedcom'], null=False)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)) - )) - db.create_unique(m2m_table_name, ['gedcom_id', 'family_id']) - - # Adding model 'Documentary' - db.create_table('gedgo_documentary', ( - ('title', self.gf('django.db.models.fields.CharField')(max_length=100, primary_key=True)), - ('tagline', self.gf('django.db.models.fields.CharField')(max_length=100)), - ('location', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)), - ('thumb', self.gf('django.db.models.fields.related.ForeignKey')(related_name='documentaries_thumb', blank=True, to=orm['gedgo.Document'])), - ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'])), - ('last_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - )) - db.send_create_signal('gedgo', ['Documentary']) - - # Adding M2M table for field tagged_people on 'Documentary' - m2m_table_name = db.shorten_name('gedgo_documentary_tagged_people') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('documentary', models.ForeignKey(orm['gedgo.documentary'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['documentary_id', 'person_id']) - - # Adding M2M table for field tagged_families on 'Documentary' - m2m_table_name = db.shorten_name('gedgo_documentary_tagged_families') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('documentary', models.ForeignKey(orm['gedgo.documentary'], null=False)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)) - )) - db.create_unique(m2m_table_name, ['documentary_id', 'family_id']) - - # Adding model 'Person' - db.create_table('gedgo_person', ( - ('pointer', self.gf('django.db.models.fields.CharField')(max_length=10, primary_key=True)), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'])), - ('first_name', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('last_name', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('prefix', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('suffix', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('birth', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='person_birth', null=True, to=orm['gedgo.Event'])), - ('death', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='person_death', null=True, to=orm['gedgo.Event'])), - ('education', self.gf('django.db.models.fields.TextField')(null=True)), - ('religion', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), - ('child_family', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='person_child_family', null=True, to=orm['gedgo.Family'])), - )) - db.send_create_signal('gedgo', ['Person']) - - # Adding M2M table for field spousal_families on 'Person' - m2m_table_name = db.shorten_name('gedgo_person_spousal_families') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)) - )) - db.create_unique(m2m_table_name, ['person_id', 'family_id']) - - # Adding M2M table for field notes on 'Person' - m2m_table_name = db.shorten_name('gedgo_person_notes') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)), - ('note', models.ForeignKey(orm['gedgo.note'], null=False)) - )) - db.create_unique(m2m_table_name, ['person_id', 'note_id']) - - # Adding M2M table for field profile on 'Person' - m2m_table_name = db.shorten_name('gedgo_person_profile') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)), - ('document', models.ForeignKey(orm['gedgo.document'], null=False)) - )) - db.create_unique(m2m_table_name, ['person_id', 'document_id']) - - # Adding model 'Family' - db.create_table('gedgo_family', ( - ('pointer', self.gf('django.db.models.fields.CharField')(max_length=10, primary_key=True)), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'])), - ('kind', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), - ('joined', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='family_joined', null=True, to=orm['gedgo.Event'])), - ('separated', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='family_separated', null=True, to=orm['gedgo.Event'])), - )) - db.send_create_signal('gedgo', ['Family']) - - # Adding M2M table for field husbands on 'Family' - m2m_table_name = db.shorten_name('gedgo_family_husbands') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['family_id', 'person_id']) - - # Adding M2M table for field wives on 'Family' - m2m_table_name = db.shorten_name('gedgo_family_wives') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['family_id', 'person_id']) - - # Adding M2M table for field children on 'Family' - m2m_table_name = db.shorten_name('gedgo_family_children') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['family_id', 'person_id']) - - # Adding M2M table for field notes on 'Family' - m2m_table_name = db.shorten_name('gedgo_family_notes') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('family', models.ForeignKey(orm['gedgo.family'], null=False)), - ('note', models.ForeignKey(orm['gedgo.note'], null=False)) - )) - db.create_unique(m2m_table_name, ['family_id', 'note_id']) - - # Adding model 'Event' - db.create_table('gedgo_event', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('date', self.gf('django.db.models.fields.DateField')(null=True)), - ('year_range_end', self.gf('django.db.models.fields.IntegerField')(null=True)), - ('date_format', self.gf('django.db.models.fields.CharField')(max_length=10, null=True)), - ('date_approxQ', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'])), - ('place', self.gf('django.db.models.fields.CharField')(max_length=50)), - )) - db.send_create_signal('gedgo', ['Event']) - - # Adding model 'Note' - db.create_table('gedgo_note', ( - ('pointer', self.gf('django.db.models.fields.CharField')(max_length=10, primary_key=True)), - ('text', self.gf('django.db.models.fields.TextField')()), - ('gedcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gedgo.Gedcom'])), - )) - db.send_create_signal('gedgo', ['Note']) - - # Adding model 'BlogPost' - db.create_table('gedgo_blogpost', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=60)), - ('body', self.gf('django.db.models.fields.TextField')()), - ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - )) - db.send_create_signal('gedgo', ['BlogPost']) - - # Adding M2M table for field tagged_photos on 'BlogPost' - m2m_table_name = db.shorten_name('gedgo_blogpost_tagged_photos') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('blogpost', models.ForeignKey(orm['gedgo.blogpost'], null=False)), - ('document', models.ForeignKey(orm['gedgo.document'], null=False)) - )) - db.create_unique(m2m_table_name, ['blogpost_id', 'document_id']) - - # Adding M2M table for field tagged_people on 'BlogPost' - m2m_table_name = db.shorten_name('gedgo_blogpost_tagged_people') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('blogpost', models.ForeignKey(orm['gedgo.blogpost'], null=False)), - ('person', models.ForeignKey(orm['gedgo.person'], null=False)) - )) - db.create_unique(m2m_table_name, ['blogpost_id', 'person_id']) - - def backwards(self, orm): - # Deleting model 'Document' - db.delete_table('gedgo_document') - - # Removing M2M table for field tagged_people on 'Document' - db.delete_table(db.shorten_name('gedgo_document_tagged_people')) - - # Removing M2M table for field tagged_families on 'Document' - db.delete_table(db.shorten_name('gedgo_document_tagged_families')) - - # Deleting model 'Gedcom' - db.delete_table('gedgo_gedcom') - - # Removing M2M table for field key_people on 'Gedcom' - db.delete_table(db.shorten_name('gedgo_gedcom_key_people')) - - # Removing M2M table for field key_families on 'Gedcom' - db.delete_table(db.shorten_name('gedgo_gedcom_key_families')) - - # Deleting model 'Documentary' - db.delete_table('gedgo_documentary') - - # Removing M2M table for field tagged_people on 'Documentary' - db.delete_table(db.shorten_name('gedgo_documentary_tagged_people')) - - # Removing M2M table for field tagged_families on 'Documentary' - db.delete_table(db.shorten_name('gedgo_documentary_tagged_families')) - - # Deleting model 'Person' - db.delete_table('gedgo_person') - - # Removing M2M table for field spousal_families on 'Person' - db.delete_table(db.shorten_name('gedgo_person_spousal_families')) - - # Removing M2M table for field notes on 'Person' - db.delete_table(db.shorten_name('gedgo_person_notes')) - - # Removing M2M table for field profile on 'Person' - db.delete_table(db.shorten_name('gedgo_person_profile')) - - # Deleting model 'Family' - db.delete_table('gedgo_family') - - # Removing M2M table for field husbands on 'Family' - db.delete_table(db.shorten_name('gedgo_family_husbands')) - - # Removing M2M table for field wives on 'Family' - db.delete_table(db.shorten_name('gedgo_family_wives')) - - # Removing M2M table for field children on 'Family' - db.delete_table(db.shorten_name('gedgo_family_children')) - - # Removing M2M table for field notes on 'Family' - db.delete_table(db.shorten_name('gedgo_family_notes')) - - # Deleting model 'Event' - db.delete_table('gedgo_event') - - # Deleting model 'Note' - db.delete_table('gedgo_note') - - # Deleting model 'BlogPost' - db.delete_table('gedgo_blogpost') - - # Removing M2M table for field tagged_photos on 'BlogPost' - db.delete_table(db.shorten_name('gedgo_blogpost_tagged_photos')) - - # Removing M2M table for field tagged_people on 'BlogPost' - db.delete_table(db.shorten_name('gedgo_blogpost_tagged_people')) - - models = { - 'gedgo.blogpost': { - 'Meta': {'object_name': 'BlogPost'}, - 'body': ('django.db.models.fields.TextField', [], {}), - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'tagged_people': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'blogpost_tagged_people'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'tagged_photos': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'blogpost_tagged_photos'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Document']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '60'}) - }, - 'gedgo.document': { - 'Meta': {'object_name': 'Document'}, - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'docfile': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']", 'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kind': ('django.db.models.fields.CharField', [], {'max_length': '5'}), - 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'tagged_families': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'media_tagged_families'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Family']"}), - 'tagged_people': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'media_tagged_people'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'thumb': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) - }, - 'gedgo.documentary': { - 'Meta': {'object_name': 'Documentary'}, - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']"}), - 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'tagged_families': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'documentaries_tagged_families'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Family']"}), - 'tagged_people': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'documentaries_tagged_people'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'tagline': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'thumb': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documentaries_thumb'", 'blank': 'True', 'to': "orm['gedgo.Document']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'primary_key': 'True'}) - }, - 'gedgo.event': { - 'Meta': {'object_name': 'Event'}, - 'date': ('django.db.models.fields.DateField', [], {'null': 'True'}), - 'date_approxQ': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'date_format': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'place': ('django.db.models.fields.CharField', [], {'max_length': '50'}), - 'year_range_end': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) - }, - 'gedgo.family': { - 'Meta': {'object_name': 'Family'}, - 'children': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'family_children'", 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']"}), - 'husbands': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'family_husbands'", 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'joined': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'family_joined'", 'null': 'True', 'to': "orm['gedgo.Event']"}), - 'kind': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gedgo.Note']", 'null': 'True', 'symmetrical': 'False'}), - 'pointer': ('django.db.models.fields.CharField', [], {'max_length': '10', 'primary_key': 'True'}), - 'separated': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'family_separated'", 'null': 'True', 'to': "orm['gedgo.Event']"}), - 'wives': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'family_wives'", 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}) - }, - 'gedgo.gedcom': { - 'Meta': {'object_name': 'Gedcom'}, - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'key_families': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'gedcom_key_families'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Family']"}), - 'key_people': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'gedcom_key_people'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['gedgo.Person']"}), - 'last_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) - }, - 'gedgo.note': { - 'Meta': {'object_name': 'Note'}, - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']"}), - 'pointer': ('django.db.models.fields.CharField', [], {'max_length': '10', 'primary_key': 'True'}), - 'text': ('django.db.models.fields.TextField', [], {}) - }, - 'gedgo.person': { - 'Meta': {'object_name': 'Person'}, - 'birth': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'person_birth'", 'null': 'True', 'to': "orm['gedgo.Event']"}), - 'child_family': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'person_child_family'", 'null': 'True', 'to': "orm['gedgo.Family']"}), - 'death': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'person_death'", 'null': 'True', 'to': "orm['gedgo.Event']"}), - 'education': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'gedcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gedgo.Gedcom']"}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'notes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gedgo.Note']", 'null': 'True', 'symmetrical': 'False'}), - 'pointer': ('django.db.models.fields.CharField', [], {'max_length': '10', 'primary_key': 'True'}), - 'prefix': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'profile': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['gedgo.Document']", 'null': 'True', 'blank': 'True'}), - 'religion': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'spousal_families': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'person_spousal_families'", 'symmetrical': 'False', 'to': "orm['gedgo.Family']"}), - 'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - } - } - - complete_apps = ['gedgo'] diff --git a/reqs.pip b/reqs.pip index 301490d..dfa08f7 100644 --- a/reqs.pip +++ b/reqs.pip @@ -1,8 +1,7 @@ -django -django-celery -South -django-tastypie -pillow +django==1.9.2 +django-celery==3.1.17 +pillow==3.1.1 +dropbox mysql-python redis flake8 diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..c8c58f7 --- /dev/null +++ b/settings.py @@ -0,0 +1,139 @@ +import os +project_root = os.path.dirname(__file__) +# Django settings for gedgo project. + +DEBUG = True + +ADMINS = () + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'gedgo', + 'USER': 'gedgo', + 'PASSWORD': 'gedgo', + 'HOST': 'db', + 'PORT': '', + } +} + +ALLOWED_HOSTS = [] +TIME_ZONE = 'America/New_York' +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 +USE_I18N = True +USE_L10N = True +USE_TZ = True + +MEDIA_ROOT = '/src/.files/' +MEDIA_URL = '/gedgo/media/' + +STATIC_ROOT = '' +STATIC_URL = '/static/' + +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) + +SECRET_KEY = 'not_a_secret' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(project_root, 'gedgo/templates'), + os.path.join(project_root, 'gedgo/templates/default'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + # Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this + # list if you haven't customized them: + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + # Uncomment the next line for simple clickjacking protection: + # 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'urls' +# WSGI_APPLICATION = 'wsgi.application' + + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'djcelery', + 'django.contrib.admin', + 'gedgo' +) + +MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' + +# Just send emails to the console. +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +SERVER_EMAIL = ['noreply@example.com'] + +GEDGO_SITE_TITLE = 'My Genealogy Site' +GEDGO_REDIS_SERVER = 'redis' + +BROKER_BACKEND = 'redis' +BROKER_URL = 'redis://redis:6379/0' +CELERY_RESULT_BACKEND = 'redis://redis:6379/0' +CELERY_ACCEPT_CONTENT = ["json"] + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} + +try: + from settings_local import * # noqa +except ImportError: + pass + +import djcelery +djcelery.setup_loader() diff --git a/static/test/test.ged b/static/test/test.ged deleted file mode 100644 index 8a9ebaf..0000000 --- a/static/test/test.ged +++ /dev/null @@ -1,80 +0,0 @@ -0 HEAD -1 SOUR Test -2 VERS V9.0 -1 DEST Test -1 DATE 21 JUN 2012 -1 TITL Test Gedcom -1 FILE Test -1 GEDC -2 VERS 5.5 -1 CHAR UTF-8 -0 @I1@ INDI -1 NAME John /Doe/ -1 SEX M -1 BIRT -2 DATE 22 MAR 1950 -2 PLAC Houston, Texas -1 _CONTACT -2 TYPE home -2 ADDR Paris, France -1 NOTE @N1@ -1 FAMC @F2@ -1 FAMS @F1@ -1 CHAN -2 DATE 5 JUL 2004 -0 @I2@ INDI -1 NAME Jill /Jillian/ -1 SEX F -1 BIRT -2 DATE 8 JUN 1952 -2 PLAC Honolulu, Hawaii -1 FAMS @F1@ -0 @I3@ INDI -1 NAME John /Doe/ -1 NSFX , Jr. -1 SEX M -1 BIRT -2 DATE 10 MAR 1984 -2 PLAC Arlington, Virgina -1 FAMC @F19@ -0 @I4@ INDI -1 NAME Jane /Doe/ -1 SEX F -1 BIRT -2 DATE 3 NOV 1986 -2 PLAC Arlington, Virginia -1 FAMC @F1@ -0 @I5@ INDI -1 NAME Smith /Joe/ -1 SEX M -1 BIRT -2 DATE 10 MAY 1945 -2 PLAC Mount Plesant, Titus, Texas -1 DEAT -2 DATE 7 FEB 1987 -2 PLAC Fort Worth, Tarrant, Texas -1 FAMS @F2@ -0 @I6@ INDI -1 NAME Jayda /Doe/ -1 SEX F -1 BIRT -2 DATE BET. 1946 1953 -2 PLAC Fort Worth, Tarrant, Texas -1 FAMC @F2@ -0 @F1@ FAM -1 HUSB @I1@ -1 WIFE @I2@ -1 MARR -2 DATE 7 JUN 1972 -2 PLAC The Moon -1 CHIL @I3@ -1 CHIL @I4@ -0 @F2@ FAM -1 HUSB @I5@ -1 CHIL @I1@ -1 CHIL @I6@ -0 @N1@ NOTE -1 CONT John Doe is an American Musician, known for the bop, the beep, and the Whoa Nelly. He incorporated elements of jazz, ja -1 CONC xx and trip-hop to form an influential style. He garnered a large following, including notable musicians such as Cab -1 CONC Calloway and Tribe Called Quest's Q-Tip. [Citation Needed] -0 TRLR diff --git a/urls.py b/urls.py index 3ec1f6d..10c6c96 100644 --- a/urls.py +++ b/urls.py @@ -1,62 +1,21 @@ -from django.conf.urls import patterns, url -from django.conf.urls import include +from django.conf.urls import include, url from django.shortcuts import redirect -from tastypie.api import Api -from gedgo.api import PersonResource, FamilyResource - -from gedgo import views - -v1_api = Api(api_name='v1') -v1_api.register(PersonResource()) -v1_api.register(FamilyResource()) - -urlpatterns = patterns( - '', - url( - r'^(?P\d+)/(?PI\d+)/$', - views.person, - name='person' - ), - url(r'^(?P\d+)/$', views.gedcom, name='gedcom'), - - # XHR Data views - url(r'^(?P\d+)/pedigree/(?PI\d+)/$', views.pedigree), - url(r'^(?P\d+)/timeline/(?PI\d+)/$', views.timeline), - url(r'^dashboard/worker/status$', views.worker_status), - - url(r'^blog/$', views.blog_list), - url(r'^blog/(?P\d+)/(?P\d+)/$', views.blog), - url(r'^blog/post/(?P\d+)/$', views.blogpost), - url(r'^documentaries/$', views.documentaries), - url(r'^research/(?P.*)$', views.research), - url(r'^api/', include(v1_api.urls)), - url(r'^search/$', views.search), - url(r'^dashboard/$', views.dashboard), - url(r'^dashboard/user/(?P\d+)/$', views.user_tracking), - - # Auth - url(r'^logout/$', views.logout_view), - url(r'^password_reset/$', - 'django.contrib.auth.views.password_reset', - { - 'template_name': 'auth/login.html', - 'email_template_name': 'auth/password_reset_email.html', - 'post_reset_redirect': '/gedgo/password_reset/done/' - }), - url(r'^password_reset/done/$', - 'django.contrib.auth.views.password_reset_done', - { - 'template_name': 'auth/password_reset_done.html' - }), - url(r'^password_reset/(?P[0-9A-Za-z]+)-(?P.+)/$', - 'django.contrib.auth.views.password_reset_confirm', - { - 'post_reset_redirect': '/', - 'template_name': 'auth/password_reset_confirm.html' - }), - - # Backup media fileserve view - url(r'^media/(?P.*)$', views.media), - - url(r'^$', lambda r: redirect('/gedgo/1/')), -) +from django.http import HttpResponse +from django.contrib import admin +from django.contrib.auth.views import login + +admin.autodiscover() + +urlpatterns = [ + url(r'^$', lambda r: redirect('/gedgo/')), + url(r'^gedgo/', include('gedgo.urls')), + url(r'^admin/', include(admin.site.urls)), + url(r'^accounts/login/$', login, + {'template_name': 'auth/login.html'}), + url(r'^login/$', login, + {'template_name': 'auth/login.html'}), + url(r'^robots\.txt$', + lambda r: HttpResponse( + "User-agent: *\nDisallow: /", + mimetype="text/plain")) +] diff --git a/views/research.py b/views/research.py deleted file mode 100644 index f95718b..0000000 --- a/views/research.py +++ /dev/null @@ -1,79 +0,0 @@ -from django.conf import settings -from django.http import Http404 -from django.contrib.auth.decorators import login_required - -from os import path -from os import listdir -import mimetypes - -from gedgo.views.util import serve_content, render - -# glyphicon name mappings -MIMETYPE_MAPPING = { - 'video': 'facetime-video', - 'audio': 'volume-up', - 'image': 'picture' -} - - -@login_required -def research(request, pathname): - try: - root = path.abspath(settings.RESEARCH_FILES_ROOT) - except: - raise Http404 - - # Force join the path with the research root to prevent serving - # private files. - pathname = pathname.strip('/') - r = path.join(root, pathname) - - # Don't allow relative path locations outside of the root. - if '..' in pathname: - raise Http404 - - # Serve the content through xsendfile or directly. - if path.isfile(r): - return serve_content(r) - - elif path.isdir(r) and '.' not in pathname: - # List the contents of the directory - contents = [ - (_get_type(r, c), c, _normalize('%s/%s' % (pathname, c))) - for c in listdir(r) if not c.startswith('.') - ] - - # Build a depth tree of the directories above this one for navigation - levels = [('Research Files', '')] - if pathname: - lp = '' - for l in pathname.split('/'): - lp = _normalize('%s/%s' % (lp, l)) - levels.append((l, lp)) - - return render( - request, - 'research.html', - { - 'contents': contents, - 'levels': levels - } - ) - else: - raise Http404 - - -def _normalize(p): - p = path.normpath(p) - if not p.startswith('/'): - p = '/' + p - return p - - -def _get_type(r, c): - if path.isdir(path.join(r, c)): - return 'folder-open' - guess, _ = mimetypes.guess_type(c) - if guess and guess.split('/')[0] in ['audio', 'video', 'image']: - return MIMETYPE_MAPPING[guess.split('/')[0]] - return 'file'