diff --git a/.gitignore b/.gitignore index 5966d39..c1d6cb2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ pip-log.txt #Virtualenv .env + +#databases +*.sqlite3 diff --git a/django_ett/django_ett/settings/common.py b/django_ett/django_ett/settings/common.py index 40cf921..7199ee3 100644 --- a/django_ett/django_ett/settings/common.py +++ b/django_ett/django_ett/settings/common.py @@ -112,11 +112,9 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', - # Uncomment the next line to enable the admin: - # 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', 'south', + 'tastypie', + 'etasks', ) # A sample logging configuration. The only tangible logging diff --git a/django_ett/django_ett/urls.py b/django_ett/django_ett/urls.py index 899729d..2d9a84d 100644 --- a/django_ett/django_ett/urls.py +++ b/django_ett/django_ett/urls.py @@ -5,6 +5,7 @@ from django.conf.urls import patterns, include, url # admin.autodiscover() urlpatterns = patterns('', + url('', include('etasks.urls')), # Examples: # url(r'^$', 'django_ett.views.home', name='home'), # url(r'^django_ett/', include('django_ett.foo.urls')), diff --git a/django_ett/etasks/__init__.py b/django_ett/etasks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django_ett/etasks/api.py b/django_ett/etasks/api.py new file mode 100644 index 0000000..f93a3a5 --- /dev/null +++ b/django_ett/etasks/api.py @@ -0,0 +1,30 @@ +from tastypie.resources import ModelResource +from tastypie.authentication import ApiKeyAuthentication +from tastypie.authorization import Authorization +from tastypie.api import Api + +from .models import Task, TimeEntry + + +class EtasksAuthorization(Authorization): + + def apply_limits(self, request, object_list): + + if request and hasattr(request, 'user'): + return object_list.filter(user__pk=request.user.pk) + + return object_list.none() + + +class TaskResource(ModelResource): + + class Meta: + queryset = Task.objects.all() + resource_name = 'task' + + authentication = ApiKeyAuthentication() + authorization = EtasksAuthorization() + + +v1_api = Api(api_name='1.0') +v1_api.register(TaskResource()) \ No newline at end of file diff --git a/django_ett/etasks/models.py b/django_ett/etasks/models.py new file mode 100644 index 0000000..26d8928 --- /dev/null +++ b/django_ett/etasks/models.py @@ -0,0 +1,54 @@ +from django.db import models +from django.contrib.auth.models import User +from tastypie.models import create_api_key + + +# Connect the tastypie API key creation call +models.signals.post_save.connect(create_api_key, sender=User) + + +class Task(models.Model): + """ + Represents a user's task entry that time can be allocated to + """ + + user = models.ForeignKey(User, related_name='tasks') + name = models.CharField('Task Name', max_length=200, blank=False) + created = models.DateTimeField('Created Date/Time', auto_now_add=True) + + def __unicode__(self): + if self.name: + return self.name + return u'Unknown' + + +class TimeEntry(models.Model): + """ + A entry of time against a task + """ + + TYPE_OFF = 1 + TYPE_ON = 2 + TYPE_STRIKE = 3 + + TYPE_CHOICES = ( + (TYPE_OFF, 'Off'), + (TYPE_ON, 'On'), + (TYPE_STRIKE, 'Strike'), + ) + + task = models.ForeignKey(Task, related_name='entries') + type = models.IntegerField('Type', choices=TYPE_CHOICES, default=TYPE_OFF) + date = models.DateField('Date') + segment = models.IntegerField('Segment') + + created = models.DateTimeField('Created Date/Time', auto_now_add=True) + updated = models.DateTimeField('Updated Date/Time', auto_now=True) + + def get_segment_time(self): + if segment: + return self.segment * 15 + return 0 + + def __unicode__(self): + return u'%s - %s %s' % (self.task.name, self.date, self.get_segment_time()) \ No newline at end of file diff --git a/django_ett/etasks/templates/etasks/task_detail.html b/django_ett/etasks/templates/etasks/task_detail.html new file mode 100644 index 0000000..45da8d1 --- /dev/null +++ b/django_ett/etasks/templates/etasks/task_detail.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/django_ett/etasks/tests.py b/django_ett/etasks/tests.py new file mode 100644 index 0000000..5ee5582 --- /dev/null +++ b/django_ett/etasks/tests.py @@ -0,0 +1,24 @@ +from __future__ import with_statement +from django.utils import unittest +from django.db import IntegrityError +from django.contrib.auth.models import User + +from .models import Task + + +class TaskTest(unittest.TestCase): + + def setUp(self): + self.user, created = User.objects.get_or_create(username='TestUser') + self.task = Task.objects.create(user=self.user, name="Test Task 1") + + def testDisplay(self): + self.assertEqual(str(self.task), "Test Task 1") + + def testBadCreation(self): + with self.assertRaises(IntegrityError): + Task.objects.create(name='Bad Test') + with self.assertRaises(IntegrityError): + Task.objects.create(user=self.user) + with self.assertRaises(IntegrityError): + Task.objects.create() \ No newline at end of file diff --git a/django_ett/etasks/urls.py b/django_ett/etasks/urls.py new file mode 100644 index 0000000..bff9528 --- /dev/null +++ b/django_ett/etasks/urls.py @@ -0,0 +1,11 @@ +from django.conf.urls import patterns, include, url + +from .api import v1_api +from .views import TaskDetailView + + +urlpatterns = patterns('', + url(r'^task/(?P.*)/$', TaskDetailView.as_view(), name='task-detail'), + + url('^api/', include(v1_api.urls)), +) diff --git a/django_ett/etasks/views.py b/django_ett/etasks/views.py new file mode 100644 index 0000000..e48d932 --- /dev/null +++ b/django_ett/etasks/views.py @@ -0,0 +1,7 @@ +from django.views.generic import DetailView +from .models import Task + + +class TaskDetailView(DetailView): + + model = Task \ No newline at end of file diff --git a/fabfile.py b/fabfile.py new file mode 100644 index 0000000..ad68f37 --- /dev/null +++ b/fabfile.py @@ -0,0 +1,19 @@ +from __future__ import with_statement +from fabric.api import task, prefix, env, local + +env.shell = '/bin/bash -l -c' + +###### Local Tasks + +@task +def runserver(port=3333): + with prefix('. .env/bin/activate'): + ip = local("""ip addr list eth0 |grep "inet " |cut -d' ' -f6|cut -d/ -f1""", capture=True) + local('django_ett/manage.py runserver %s:%s' % (ip, port), capture=False) + +@task +def test(): + with prefix('. .env/bin/activate'): + local('django_ett/manage.py test --noinput --failfast') + + diff --git a/requirements.txt b/requirements.txt index a4f227a..1d3a270 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ django>=1.4.2 south>=0.7.6 +django-tastypie>=0.9.11 +fabric>=1.4.3