commit 6043ee127a1fb1e24f40105878dd9f0bd927774e Author: Tyrel Souza Date: Mon Aug 31 23:31:25 2015 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8a0469 --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# Created by https://www.gitignore.io/api/django,python + +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py + + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +.idea/ +*.sqlite3 diff --git a/bikemap/__init__.py b/bikemap/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bikemap/settings.py b/bikemap/settings.py new file mode 100644 index 0000000..bf97271 --- /dev/null +++ b/bikemap/settings.py @@ -0,0 +1,106 @@ +""" +Django settings for bikemap project. + +Generated by 'django-admin startproject' using Django 1.8.4. + +For more information on this file, see +https://docs.djangoproject.com/en/1.8/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.8/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 's16bs6p9e%#fn#6pc0t92mzuc(z6r!^tw5a)eoy01dxs#cy(iq' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django_extensions', + 'home', + 'tracking', +) + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.security.SecurityMiddleware', +) + +ROOT_URLCONF = 'bikemap.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')] + , + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'bikemap.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/bikemap/urls.py b/bikemap/urls.py new file mode 100644 index 0000000..7dce839 --- /dev/null +++ b/bikemap/urls.py @@ -0,0 +1,23 @@ +"""bikemap URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.8/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Add an import: from blog import urls as blog_urls + 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) +""" +from django.conf.urls import include, url +from django.contrib import admin +from home import views as home_views + +urlpatterns = [ + url(r'^$', home_views.home, name='home'), + url(r'^admin/', include(admin.site.urls)), +] diff --git a/bikemap/wsgi.py b/bikemap/wsgi.py new file mode 100644 index 0000000..5b111b8 --- /dev/null +++ b/bikemap/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for bikemap project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bikemap.settings") + +application = get_wsgi_application() diff --git a/home/__init__.py b/home/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/migrations/__init__.py b/home/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/tests.py b/home/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/home/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/home/views.py b/home/views.py new file mode 100644 index 0000000..6bdaad9 --- /dev/null +++ b/home/views.py @@ -0,0 +1,6 @@ +from django.http import HttpResponse + + +# Create your views here. +def home(request): + return HttpResponse("Home") diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..f7a9754 --- /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", "bikemap.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6be7f9e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Django==1.8.4 +django-extensions +coverage \ No newline at end of file diff --git a/tracking/__init__.py b/tracking/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tracking/admin.py b/tracking/admin.py new file mode 100644 index 0000000..6b54242 --- /dev/null +++ b/tracking/admin.py @@ -0,0 +1,13 @@ +from django.contrib import admin +from tracking.models import Track, Point + + +class TrackAdmin(admin.ModelAdmin): + pass + +class PointAdmin(admin.ModelAdmin): + pass + +# Register your models here. +admin.site.register(Track, TrackAdmin) +admin.site.register(Point, PointAdmin) \ No newline at end of file diff --git a/tracking/fixtures/tracking_test_fixtures.json b/tracking/fixtures/tracking_test_fixtures.json new file mode 100644 index 0000000..0a0ac7d --- /dev/null +++ b/tracking/fixtures/tracking_test_fixtures.json @@ -0,0 +1,5 @@ +[{"fields": +{"username": "tyrel", "first_name": "", "last_name": "", + "is_active": true, "is_superuser": true, "is_staff": true, + "last_login": "2015-09-01T02:46:14.601Z", "groups": [], "user_permissions": [], + "password": "nopass", "email": "tyrelsouza@gmail.com", "date_joined": "2015-09-01T02:46:09.186Z"}, "model": "auth.user", "pk": 1}] diff --git a/tracking/management/__init__.py b/tracking/management/__init__.py new file mode 100644 index 0000000..1e330b8 --- /dev/null +++ b/tracking/management/__init__.py @@ -0,0 +1 @@ +__author__ = 'tyrel' diff --git a/tracking/management/commands/__init__.py b/tracking/management/commands/__init__.py new file mode 100644 index 0000000..1e330b8 --- /dev/null +++ b/tracking/management/commands/__init__.py @@ -0,0 +1 @@ +__author__ = 'tyrel' diff --git a/tracking/management/commands/import_gpx.py b/tracking/management/commands/import_gpx.py new file mode 100644 index 0000000..62a81c2 --- /dev/null +++ b/tracking/management/commands/import_gpx.py @@ -0,0 +1,32 @@ +__author__ = 'tyrel' +from django.core.management.base import BaseCommand, CommandError +from django.contrib.auth.models import User +from tracking.models import Track, Point +from xml.etree import ElementTree +import os + + +class Command(BaseCommand): + help = 'Import a gpx file' + + def add_arguments(self, parser): + parser.add_argument('username', help="Username to import to.") + parser.add_argument('filepath', help="File or directory to import a gpx file.") + + def handle(self, *args, **options): + username = options['username'] + filepath = options['filepath'] + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + raise CommandError("User %s does not exist" % username) + + self.stdout.write("Importing for user %s" % user.username) + + if os.path.isdir(filepath): + self.stdout("OK, path") + elif os.path.isfile(filepath): + self.stdout("OK, file") + else: + raise CommandError("{0} is neither an existing file, nor a path.".format(filepath)) + diff --git a/tracking/migrations/0001_initial.py b/tracking/migrations/0001_initial.py new file mode 100644 index 0000000..d667ea0 --- /dev/null +++ b/tracking/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Point', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('time', models.DateTimeField()), + ('latitude', models.FloatField()), + ('longitude', models.FloatField()), + ('elevation', models.DecimalField(max_digits=20, decimal_places=2)), + ], + ), + migrations.CreateModel( + name='Track', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('start', models.DateTimeField()), + ('name', models.CharField(max_length=1024)), + ('description', models.TextField(blank=True)), + ], + ), + migrations.AddField( + model_name='point', + name='track', + field=models.ForeignKey(to='tracking.Track'), + ), + ] diff --git a/tracking/migrations/__init__.py b/tracking/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tracking/models.py b/tracking/models.py new file mode 100644 index 0000000..e3b89ec --- /dev/null +++ b/tracking/models.py @@ -0,0 +1,23 @@ +from django.db import models + +# Create your models here. + + +class Track(models.Model): + start = models.DateTimeField() + name = models.CharField(max_length=1024, blank=False) + description = models.TextField(blank=True) + + @property + def finish(self): + return self.point_set.order_by("-time")[0].time + + +class Point(models.Model): + time = models.DateTimeField() + latitude = models.FloatField() + longitude = models.FloatField() + elevation = models.DecimalField(max_digits=20, decimal_places=2) + track = models.ForeignKey(Track) + + diff --git a/tracking/tests.py b/tracking/tests.py new file mode 100644 index 0000000..ebff0a8 --- /dev/null +++ b/tracking/tests.py @@ -0,0 +1,15 @@ +from django.test import TestCase +from django.core import management +from django.core.management.base import CommandError + +# Create your tests here. +class ImportGPXManagementTest(TestCase): + fixtures = ['tracking_test_fixtures.json',] + def test_user_does_not_exist(self): + with self.assertRaisesMessage(CommandError, "User THISUSERWONTEXIST does not exist"): + management.call_command('import_gpx', 'THISUSERWONTEXIST', 'foo') + + def test_path_exists(self): + with self.assertRaisesMessage(CommandError, "/noop/nodir/ is neither an existing file, nor a path."): + management.call_command('import_gpx', 'tyrel', '/noop/nodir/') + diff --git a/tracking/views.py b/tracking/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/tracking/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.