diff options
author | Leif Johansson <leifj@sunet.se> | 2010-07-05 21:37:04 +0200 |
---|---|---|
committer | Leif Johansson <leifj@sunet.se> | 2010-07-05 21:37:04 +0200 |
commit | 8f7f4ff3a35ddeacea7d5530c7dc3c296907ab67 (patch) | |
tree | 7d481dc7030ad191314aa2569cca9f8301e1f997 |
import
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | .project | 18 | ||||
-rw-r--r-- | .pydevproject | 15 | ||||
-rw-r--r-- | coip/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/invitation/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/invitation/admin.py | 4 | ||||
-rw-r--r-- | coip/apps/invitation/forms.py | 11 | ||||
-rw-r--r-- | coip/apps/invitation/models.py | 34 | ||||
-rw-r--r-- | coip/apps/invitation/views.py | 33 | ||||
-rw-r--r-- | coip/apps/membership/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/membership/admin.py | 4 | ||||
-rw-r--r-- | coip/apps/membership/forms.py | 11 | ||||
-rw-r--r-- | coip/apps/membership/models.py | 23 | ||||
-rw-r--r-- | coip/apps/membership/views.py | 13 | ||||
-rw-r--r-- | coip/apps/name/__init__.py | 0 | ||||
-rw-r--r-- | coip/apps/name/admin.py | 5 | ||||
-rw-r--r-- | coip/apps/name/forms.py | 15 | ||||
-rw-r--r-- | coip/apps/name/models.py | 73 | ||||
-rw-r--r-- | coip/apps/name/views.py | 0 | ||||
-rw-r--r-- | coip/mimeparse.py | 123 | ||||
-rw-r--r-- | coip/multiresponse.py | 78 | ||||
-rw-r--r-- | coip/urls.py | 17 | ||||
-rwxr-xr-x | dev-django-admin.sh | 1 | ||||
-rwxr-xr-x | manage.py | 11 | ||||
-rw-r--r-- | settings.py | 75 |
26 files changed, 567 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07025ed --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.db +*.log diff --git a/.project b/.project new file mode 100644 index 0000000..4224eb4 --- /dev/null +++ b/.project @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>coip</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.python.pydev.PyDevBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.python.pydev.pythonNature</nature> + <nature>org.python.pydev.django.djangoNature</nature> + </natures> +</projectDescription> diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..3f6940e --- /dev/null +++ b/.pydevproject @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?eclipse-pydev version="1.0"?> + +<pydev_project> +<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> +<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property> +<pydev_variables_property name="org.python.pydev.PROJECT_VARIABLE_SUBSTITUTION"> +<key>DJANGO_MANAGE_LOCATION</key> +<value>manage.py</value> +</pydev_variables_property> + +<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> +<path>/coip</path> +</pydev_pathproperty> +</pydev_project> diff --git a/coip/__init__.py b/coip/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/__init__.py diff --git a/coip/apps/__init__.py b/coip/apps/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/apps/__init__.py diff --git a/coip/apps/invitation/__init__.py b/coip/apps/invitation/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/apps/invitation/__init__.py diff --git a/coip/apps/invitation/admin.py b/coip/apps/invitation/admin.py new file mode 100644 index 0000000..722b147 --- /dev/null +++ b/coip/apps/invitation/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from coip.apps.invitation.models import Invitation + +admin.site.register(Invitation)
\ No newline at end of file diff --git a/coip/apps/invitation/forms.py b/coip/apps/invitation/forms.py new file mode 100644 index 0000000..3370597 --- /dev/null +++ b/coip/apps/invitation/forms.py @@ -0,0 +1,11 @@ +''' +Created on Jul 5, 2010 + +@author: leifj +''' +from django import forms +from coip.apps.invitation.models import Invitation + +class InvitationForm(forms.ModelForm): + class Meta: + model = Invitation
\ No newline at end of file diff --git a/coip/apps/invitation/models.py b/coip/apps/invitation/models.py new file mode 100644 index 0000000..951fa59 --- /dev/null +++ b/coip/apps/invitation/models.py @@ -0,0 +1,34 @@ +''' +Created on Jun 23, 2010 + +@author: leifj +''' + +from django.db import models +from django.contrib.auth.models import User +from coip.apps.membership.models import Membership +from pprint import pprint +from uuid import uuid4 +import datetime + +class Invitation(models.Model): + ''' + Represents an invitation to an application + ''' + sender = models.ForeignKey(User, unique=True) + membership = models.ForeignKey(Membership, unique=True) + timecreated = models.DateTimeField(auto_now_add=True) + lastupdated = models.DateTimeField(auto_now=True) + expires = models.DateTimeField() + token = models.TextField(unique=True) + + + def __init__(self): + self.token = uuid4() + + def valid(self): + return datetime.date.today() > self.expires + + def send_email(self): + pprint("sent email to "+self.to) + return
\ No newline at end of file diff --git a/coip/apps/invitation/views.py b/coip/apps/invitation/views.py new file mode 100644 index 0000000..fe1c6af --- /dev/null +++ b/coip/apps/invitation/views.py @@ -0,0 +1,33 @@ +''' +Created on Jun 23, 2010 + +@author: leifj +''' +from django.contrib.auth.decorators import login_required +from apps.invitation.forms import InvitationForm +from apps.invitation.models import Invitation +from django.shortcuts import render_to_response +from django.http import HttpResponseRedirect + +@login_required +def create(request): + user = request.user + if request.method == 'POST': + form = InvitationForm(request.POST) + if form.is_valid(): + to = form.cleaned_data["to"] + expires = form.cleaned_data["expires"] + invitation = Invitation(sender=user,to=to,expires=expires) + invitation.save() + invitation.send_email() + return HttpResponseRedirect("/user/home") + else: + form = InvitationForm({}); + + return render_to_response('apps/invitation/create.html') + +def accept(request,token): + user = request.user + invitation = Invitation.objects.get(token=token) + +
\ No newline at end of file diff --git a/coip/apps/membership/__init__.py b/coip/apps/membership/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/apps/membership/__init__.py diff --git a/coip/apps/membership/admin.py b/coip/apps/membership/admin.py new file mode 100644 index 0000000..a98efe7 --- /dev/null +++ b/coip/apps/membership/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from coip.apps.membership.models import Membership + +admin.site.register(Membership)
\ No newline at end of file diff --git a/coip/apps/membership/forms.py b/coip/apps/membership/forms.py new file mode 100644 index 0000000..9adab0d --- /dev/null +++ b/coip/apps/membership/forms.py @@ -0,0 +1,11 @@ +''' +Created on Jun 23, 2010 + +@author: leifj +''' +from django import forms +from coip.apps.membership.models import Membership + +class MembershipForm(forms.ModelForm): + class Meta: + model = Membership
\ No newline at end of file diff --git a/coip/apps/membership/models.py b/coip/apps/membership/models.py new file mode 100644 index 0000000..df6e796 --- /dev/null +++ b/coip/apps/membership/models.py @@ -0,0 +1,23 @@ +''' +Created on Jun 23, 2010 + +@author: leifj +''' +from django.db import models +from django.contrib.auth.models import User +from coip.apps.name.models import Name +import datetime + +class Membership(models.Model): + ''' + Membership in a namespace/group + ''' + user = models.ForeignKey(User,unique=True,blank=True) + enabled = models.BooleanField() + timecreated = models.DateTimeField(auto_now_add=True) + lastupdated = models.DateTimeField(auto_now=True) + expires = models.DateTimeField(blank=True) + name = models.ForeignKey(Name) + + def valid(self): + return self.enabled and datetime.date.today() > self.expires diff --git a/coip/apps/membership/views.py b/coip/apps/membership/views.py new file mode 100644 index 0000000..7a06a21 --- /dev/null +++ b/coip/apps/membership/views.py @@ -0,0 +1,13 @@ +''' +Created on Jun 23, 2010 + +@author: leifj +''' +from django.contrib.auth.decorators import login_required +from coip.apps.membership.models import Membership + +@login_required +def memberships(request,name): + + Membership.objects.get(name) +
\ No newline at end of file diff --git a/coip/apps/name/__init__.py b/coip/apps/name/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/apps/name/__init__.py diff --git a/coip/apps/name/admin.py b/coip/apps/name/admin.py new file mode 100644 index 0000000..477da76 --- /dev/null +++ b/coip/apps/name/admin.py @@ -0,0 +1,5 @@ +from django.contrib import admin +from coip.apps.name.models import Name, Attribute + +admin.site.register(Name) +admin.site.register(Attribute)
\ No newline at end of file diff --git a/coip/apps/name/forms.py b/coip/apps/name/forms.py new file mode 100644 index 0000000..0c96480 --- /dev/null +++ b/coip/apps/name/forms.py @@ -0,0 +1,15 @@ +''' +Created on Jun 24, 2010 + +@author: leifj +''' +from django import forms +from coip.apps.name.models import Name, Attribute + +class NameForm(forms.ModelForm): + class Meta: + model = Name + +class AttributeForm(forms.ModelForm): + class Meta: + model = Attribute
\ No newline at end of file diff --git a/coip/apps/name/models.py b/coip/apps/name/models.py new file mode 100644 index 0000000..ec86769 --- /dev/null +++ b/coip/apps/name/models.py @@ -0,0 +1,73 @@ +''' +Created on Jun 24, 2010 + +@author: leifj +''' +from django.db import models +from django.contrib.auth.models import User +import re + +class Attribute(models.Model): + name = models.CharField(unique=True,max_length=255) + description = models.TextField(blank=True) + timecreated = models.DateTimeField(auto_now_add=True) + lastupdated = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return self.name; + +class Name(models.Model): + ''' + A name-space/authorization/right/group/collaboration/thing + ''' + type = models.ForeignKey(Attribute, blank=True, null=True,related_name='names') + value = models.CharField(max_length=255) + parent = models.ForeignKey('self', blank=True, null=True,related_name='children') + partof = models.ForeignKey('self', blank=True, null=True,related_name='parts') + acl = models.TextField(blank=True) # fully-qualified-name '#' rights + description = models.TextField(blank=True) + creator = models.ForeignKey(User) + timecreated = models.DateTimeField(auto_now_add=True) + lastupdated = models.DateTimeField(auto_now=True) + + def relative_name(self): + if self.type: + return "%s=%s" % (self.type.name,self.value) + else: + return self.value + + def __unicode__(self): + n = self + str = "" + while n: + sep = "" + av = n.relative_name() + + if n.parent: + if av.find("=") == -1: + sep = ':' + else: + sep = ';' + + str = sep+av+str + n = n.parent + + return str + +def walkto(root,nameparts): + name = None + for n in nameparts: + (a,eq,v) = n.partition('=') + if v: + attribute = Attribute.objects.get(name=a) + name = Name.objects.get(parent=root,type=attribute.id,value=v) + else: + name = Name.objects.get(parent=root,type=None,value=a) + return name + +def lookup(name): + return walkto(None,nameparts=re.compile('[;:]').split(name)) + +def attribute(a): + Attribute.objects.get_or_create(name=a) +
\ No newline at end of file diff --git a/coip/apps/name/views.py b/coip/apps/name/views.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/coip/apps/name/views.py diff --git a/coip/mimeparse.py b/coip/mimeparse.py new file mode 100644 index 0000000..0fd91e7 --- /dev/null +++ b/coip/mimeparse.py @@ -0,0 +1,123 @@ +"""MIME-Type Parser + +This module provides basic functions for handling mime-types. It can handle +matching mime-types against a list of media-ranges. See section 14.1 of +the HTTP specification [RFC 2616] for a complete explanation. + + http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + +Contents: + - parse_mime_type(): Parses a mime-type into its component parts. + - parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q' quality parameter. + - quality(): Determines the quality ('q') of a mime-type when compared against a list of media-ranges. + - quality_parsed(): Just like quality() except the second parameter must be pre-parsed. + - best_match(): Choose the mime-type with the highest quality ('q') from a list of candidates. +""" + +__version__ = "0.1.2" +__author__ = 'Joe Gregorio' +__email__ = "joe@bitworking.org" +__credits__ = "" + +def parse_mime_type(mime_type): + """Carves up a mime-type and returns a tuple of the + (type, subtype, params) where 'params' is a dictionary + of all the parameters for the media range. + For example, the media range 'application/xhtml;q=0.5' would + get parsed into: + + ('application', 'xhtml', {'q', '0.5'}) + """ + parts = mime_type.split(";") + params = dict([tuple([s.strip() for s in param.split("=")])\ + for param in parts[1:] ]) + full_type = parts[0].strip() + # Java URLConnection class sends an Accept header that includes a single "*" + # Turn it into a legal wildcard. + if full_type == '*': full_type = '*/*' + (type, subtype) = full_type.split("/") + return (type.strip(), subtype.strip(), params) + +def parse_media_range(range): + """Carves up a media range and returns a tuple of the + (type, subtype, params) where 'params' is a dictionary + of all the parameters for the media range. + For example, the media range 'application/*;q=0.5' would + get parsed into: + + ('application', '*', {'q', '0.5'}) + + In addition this function also guarantees that there + is a value for 'q' in the params dictionary, filling it + in with a proper default if necessary. + """ + (type, subtype, params) = parse_mime_type(range) + if not params.has_key('q') or not params['q'] or \ + not float(params['q']) or float(params['q']) > 1\ + or float(params['q']) < 0: + params['q'] = '1' + return (type, subtype, params) + +def fitness_and_quality_parsed(mime_type, parsed_ranges): + """Find the best match for a given mime-type against + a list of media_ranges that have already been + parsed by parse_media_range(). Returns a tuple of + the fitness value and the value of the 'q' quality + parameter of the best match, or (-1, 0) if no match + was found. Just as for quality_parsed(), 'parsed_ranges' + must be a list of parsed media ranges. """ + best_fitness = -1 + best_fit_q = 0 + (target_type, target_subtype, target_params) =\ + parse_media_range(mime_type) + for (type, subtype, params) in parsed_ranges: + if (type == target_type or type == '*' or target_type == '*') and \ + (subtype == target_subtype or subtype == '*' or target_subtype == '*'): + param_matches = reduce(lambda x, y: x+y, [1 for (key, value) in \ + target_params.iteritems() if key != 'q' and \ + params.has_key(key) and value == params[key]], 0) + fitness = (type == target_type) and 100 or 0 + fitness += (subtype == target_subtype) and 10 or 0 + fitness += param_matches + if fitness > best_fitness: + best_fitness = fitness + best_fit_q = params['q'] + + return best_fitness, float(best_fit_q) + +def quality_parsed(mime_type, parsed_ranges): + """Find the best match for a given mime-type against + a list of media_ranges that have already been + parsed by parse_media_range(). Returns the + 'q' quality parameter of the best match, 0 if no + match was found. This function bahaves the same as quality() + except that 'parsed_ranges' must be a list of + parsed media ranges. """ + return fitness_and_quality_parsed(mime_type, parsed_ranges)[1] + +def quality(mime_type, ranges): + """Returns the quality 'q' of a mime-type when compared + against the media-ranges in ranges. For example: + + >>> quality('text/html','text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5') + 0.7 + + """ + parsed_ranges = [parse_media_range(r) for r in ranges.split(",")] + return quality_parsed(mime_type, parsed_ranges) + +def best_match(supported, header): + """Takes a list of supported mime-types and finds the best + match for all the media-ranges listed in header. The value of + header must be a string that conforms to the format of the + HTTP Accept: header. The value of 'supported' is a list of + mime-types. + + >>> best_match(['application/xbel+xml', 'text/xml'], 'text/*;q=0.5,*/*; q=0.1') + 'text/xml' + """ + parsed_header = [parse_media_range(r) for r in header.split(",")] + weighted_matches = [(fitness_and_quality_parsed(mime_type, parsed_header), mime_type)\ + for mime_type in supported] + weighted_matches.sort() + return weighted_matches[-1][0][1] and weighted_matches[-1][1] or '' diff --git a/coip/multiresponse.py b/coip/multiresponse.py new file mode 100644 index 0000000..9a3d965 --- /dev/null +++ b/coip/multiresponse.py @@ -0,0 +1,78 @@ +import coip.mimeparse as mimeparse +import re +from django.conf import settings +from django.shortcuts import render_to_response +from django.core.exceptions import ObjectDoesNotExist +from datetime import datetime +from pprint import pprint +from django.http import HttpResponse +from django.core import serializers + +default_suffix_mapping = {"\.htm(l?)$": "text/html", + "\.json$": "application/json", + "\.rss$": "application/rss+xml", + "\.torrent$": "application/x-bittorrent"} + +def _accept_types(request, suffix): + for r in suffix.keys(): + p = re.compile(r) + if p.search(request.path): + return suffix.get(r) + return None + + +def timeAsrfc822 ( theTime ) : + import rfc822 + return rfc822 . formatdate ( rfc822 . mktime_tz ( rfc822 . parsedate_tz ( theTime . strftime ( "%a, %d %b %Y %H:%M:%S" ) ) ) ) + +def make_response_dict(request,d={}): + + if request.user.is_authenticated(): + d['user'] = request.user + profile = None + try: + profile = request.user.profile.get(); + except ObjectDoesNotExist: + profile = UserProfile() + d['profile'] = profile + + #d['stomp_host'] = STOMP_HOST + #d['stomp_port'] = STOMP_PORT + #d['orbited_prefix'] = ORBITED_PREFIX + #d['announce_url'] = ANNOUNCE_URL + #d['date'] = timeAsrfc822(datetime.now()) + #if DEBUG is not None: + # d['debug'] = True + + return d + +def json_response(data): + json_serializer = serializers.get_serializer("json")() + json_serializer.serialize() + json_serializer.serialize(data) + + r = HttpResponse(data.getvalue(),content_type='application/json') + r['Cache-Control'] = 'no-cache, must-revalidate' + r['Pragma'] = 'no-cache' + + return r + +def respond_to(request, template_mapping, dict={}, suffix_mapping=default_suffix_mapping): + accept = _accept_types(request, suffix_mapping) + if accept is None: + accept = (request.META['HTTP_ACCEPT'].split(','))[0] + content_type = mimeparse.best_match(template_mapping.keys(), accept) + template = None + if template_mapping.has_key(content_type): + template = template_mapping[content_type] + else: + template = template_mapping["text/html"] + if callable(template): + response = template(make_response_dict(request,dict)) + elif isinstance(template, HttpResponse): + response = template + response['Content-Type'] = "%s; charset=%s" % (content_type, settings.DEFAULT_CHARSET) + else: + response = render_to_response(template,make_response_dict(request,dict)) + response['Content-Type'] = "%s; charset=%s" % (content_type, settings.DEFAULT_CHARSET) + return response diff --git a/coip/urls.py b/coip/urls.py new file mode 100644 index 0000000..d24cc15 --- /dev/null +++ b/coip/urls.py @@ -0,0 +1,17 @@ +from django.conf.urls.defaults import * + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + # Example: + # (r'^coip/', include('coip.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^admin/', include(admin.site.urls)), +) diff --git a/dev-django-admin.sh b/dev-django-admin.sh new file mode 100755 index 0000000..4ee21f8 --- /dev/null +++ b/dev-django-admin.sh @@ -0,0 +1 @@ +env PYTHONPATH=`pwd`:$PHTHONPATH DJANGO_SETTINGS_MODULE=settings django-admin $* diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..bcdd55e --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..ebd7e4f --- /dev/null +++ b/settings.py @@ -0,0 +1,75 @@ +# Django settings for coip project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +BASE_DIR = "/home/leifj/work/sunet.se/coip" +MANAGERS = ADMINS +DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. +DATABASE_NAME = '%s/sqlite.db' % BASE_DIR # Or path to database file if using sqlite3. +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Stockholm' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'us-en' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +MEDIA_ROOT = "%s/site-media" % BASE_DIR +ADMIN_MEDIA_ROOT = "/usr/lib/pymodules/python2.5/django/contrib/admin/media" +MEDIA_URL = '/site-media/' +ADMIN_MEDIA_PREFIX = '/admin-media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '!=ren*@$dklhfm$3#$h=a2g4r3)ra#+al)9kwi4&rpylr$3xnf' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + +ROOT_URLCONF = 'coip.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'django_extensions', + 'coip.apps.invitation', + 'coip.apps.membership', + 'coip.apps.name', +) |