Commit cb22aa2c authored by frekk's avatar frekk
Browse files

initial commit of django gms

parent aa3a1750
......@@ -71,3 +71,5 @@ typings/
# Ignore temporary backup files created by vim
*~
*.swp
*.pyc
GMS - The Gumby Management System
=================================
Written by David Adam <[email protected]>
Derived from MemberDB by Danni Madeley
GETTING STARTED EACH YEAR
=========================
To set up a new database,
(as root on mussel)
mussel:~# su - postgres
[email protected]:~$ psql
postgres=# create database uccmemberdb_20XX;
postgres=# GRANT ALL on DATABASE uccmemberdb_20XX to uccmemberdb;
Adjust /services/gms/gms/settings_local.py to point to the new database (usually
changing the databse name is enough).
If you want to make changes to the data you collect, now is the time to do it.
Edit /service/gms/memberdb/models.py
In /services/gms, run `python manage.py makemigrations` to prepare the databae
updates.
mussel:~# cd /services/gms/
mussel:/services/gms# python manage.py validate
0 errors found
mussel:/services/gms# python manage.py syncdb
...
You just installed Django's auth system, which means you don't have any
superusers defined.
Would you like to create one now? (yes/no): no
Now restart MemberDB by runing
mussel:/services/gms# touch gms/wsgi.wsgi
Now go ahead and log in to the website. It will be totally fresh, with all
committee members being made superusers on first login.
If you would like to allow non-committee users to help out with data entry,
ask them to log in. After the login attempt is denied, you will be able to
find their name in the Auth/Users area of the site. Turn on their staff status
and allow them access to the memberdb permissions.
A CSV download function has been added - select the members you want to
download in the administration interface, then choose Download as CSV file
from the Actions menu.
version = (1, 2, 7)
version_string = '.'.join(map(str, version))
This diff is collapsed.
This diff is collapsed.
# Copyright (c) 2009, Peter Sagerson
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
This is an ldap.dn replacement for old versions of python-ldap. It contains
(often naive) implementations of the methods we care about.
"""
def escape_dn_chars(dn):
"Old versions of python-ldap won't get DN escaping. Use with care."
return dn
from django.conf import settings
from django.db import models
# Support for testing Django 1.5's custom user models.
try:
from django.contrib.auth.models import AbstractBaseUser
except ImportError:
from django.contrib.auth.models import User
TestUser = User
else:
class TestUser(AbstractBaseUser):
identifier = models.CharField(max_length=40, unique=True, db_index=True)
USERNAME_FIELD = 'identifier'
def get_full_name(self):
return self.identifier
def get_short_name(self):
return self.identifier
class TestProfile(models.Model):
"""
A user profile model for use by unit tests. This has nothing to do with the
authentication backend itself.
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL)
is_special = models.BooleanField(default=False)
populated = models.BooleanField(default=False)
This diff is collapsed.
"""
Django settings for UCC Gumby Management System (GMS) project.
For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# import local settings
from gms.settings_local import *
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['secure.ucc.asn.au',]
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'memberdb',
)
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',
)
ROOT_URLCONF = 'gms.urls'
WSGI_APPLICATION = 'gms.wsgi.application'
DATE_INPUT_FORMATS = ("%d-%m-%y")
# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
LANGUAGE_CODE = 'en-au'
TIME_ZONE = 'Australia/Perth'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/members/media/'
STATIC_ROOT = '/services/gms/static'
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)
import ldap
from django_auth_ldap.config import LDAPSearch, PosixGroupType
AUTH_LDAP_SERVER_URI = 'ldaps://mussel.ucc.gu.uwa.edu.au/'
AUTH_LDAP_USER_DN_TEMPLATE = 'uid=%(user)s,ou=People,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au'
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=group,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)")
AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr='cn')
# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_staff": "cn=committee,ou=group,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
"is_superuser": "cn=committee,ou=group,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
}
AUTH_LDAP_ALWAYS_UPDATE_USER = False
AUTH_LDAP_MIRROR_GROUPS = True
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',
],
},
},
]
# Django settings for uccmemberdb project.
DEBUG = True
ADMINS = (
('UCC Committee', '[email protected]'),
('David Adam', '[email protected]'),
)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': '/home/frekk/Documents/projects/usermgmt-ucc/uccportal/.db/members.db', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}
# Make this unique, and don't share it with anybody.
SECRET_KEY = 'oB8fVqxJPfeL0MomVCwExU13H3ajZd9vWFgCpL5RMuhR4JOqSXemYasppIdimhLk'
ALLOWED_HOSTS = ['secure.ucc.asn.au']
from django.conf.urls import include, url
from django.contrib import admin
admin.site.site_header = "Gumby Management System"
admin.site.site_title = "UCC Gumby Management System"
admin.site.index_title = "Membership Database"
urlpatterns = (
# Examples:
# url(r'^$', 'gms.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^', include(admin.site.urls)),
)
wsgi.wsgi
\ No newline at end of file
"""
WSGI config for gms 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.7/howto/deployment/wsgi/
"""
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gms.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gms.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
default_app_config = 'memberdb.apps.MemberConfig'
import csv
from collections import OrderedDict
from functools import wraps
from django.db.models import FieldDoesNotExist
from django.http import HttpResponse
from functools import singledispatch # included in Python 3.4+
def prep_field(obj, field):
"""
(for download_as_csv action)
Returns the field as a unicode string. If the field is a callable, it
attempts to call it first, without arguments.
"""
if '__' in field:
bits = field.split('__')
field = bits.pop()
for bit in bits:
obj = getattr(obj, bit, None)
if obj is None:
return ""
attr = getattr(obj, field)
output = attr() if callable(attr) else attr
return unicode(output).encode('utf-8') if output is not None else ""
@singledispatch
def download_as_csv(modeladmin, request, queryset):
"""
Generic csv export admin action.
Example:
class ExampleModelAdmin(admin.ModelAdmin):
raw_id_fields = ('field1',)
list_display = ('field1', 'field2', 'field3',)
actions = [download_as_csv,]
download_as_csv_fields = [
'field1',
('foreign_key1__foreign_key2__name', 'label2'),
('field3', 'label3'),
],
download_as_csv_header = True
"""
fields = getattr(modeladmin, 'download_as_csv_fields', None)
exclude = getattr(modeladmin, 'download_as_csv_exclude', None)
header = getattr(modeladmin, 'download_as_csv_header', True)
verbose_names = getattr(modeladmin, 'download_as_csv_verbose_names', True)
opts = modeladmin.model._meta
def fname(field):
if verbose_names:
return unicode(field.verbose_name).capitalize()
else:
return field.name
# field_names is a map of {field lookup path: field label}
if exclude:
field_names = OrderedDict(
(f.name, fname(f)) for f in opts.fields if f not in exclude
)
elif fields:
field_names = OrderedDict()
for spec in fields:
if isinstance(spec, (list, tuple)):
field_names[spec[0]] = spec[1]
else:
try:
f, _, _, _ = opts.get_field_by_name(spec)
except FieldDoesNotExist:
field_names[spec] = spec
else:
field_names[spec] = fname(f)
else:
field_names = OrderedDict(
(f.name, fname(f)) for f in opts.fields
)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % (
unicode(opts).replace('.', '_')
)
writer = csv.writer(response)
if header:
writer.writerow(field_names.values())
for obj in queryset:
writer.writerow([prep_field(obj, field) for field in field_names.keys()])
return response
download_as_csv.short_description = "Download selected objects as CSV file"
@download_as_csv.register(str)
def _(description):
"""
(overridden dispatcher)
Factory function for making a action with custom description.
Example:
class ExampleModelAdmin(admin.ModelAdmin):
raw_id_fields = ('field1',)
list_display = ('field1', 'field2', 'field3',)
actions = [download_as_csv("Export Special Report"),]
download_as_csv_fields = [
'field1',
('foreign_key1__foreign_key2__name', 'label2'),
('field3', 'label3'),
],
download_as_csv_header = True
"""
@wraps(download_as_csv)
def wrapped_action(modeladmin, request, queryset):
return download_as_csv(modeladmin, request, queryset)
wrapped_action.short_description = description
return wrapped_action
from django.contrib import admin
from memberdb.models import Member
from memberdb.actions import download_as_csv
class MemberAdmin(admin.ModelAdmin):
list_display = ('real_name', 'username', 'guild_member')
list_filter = ['guild_member', 'membership_type']
search_fields = ('real_name', 'username', )
actions = [download_as_csv]
admin.site.register(Member, MemberAdmin)
from django.apps import AppConfig
class MemberConfig(AppConfig):
name = 'memberdb'
verbose_name = "Current Members"
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import datetime
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='Member',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('real_name', models.CharField(max_length=200, verbose_name=b'Real Name')),
('username', models.CharField(max_length=16, verbose_name=b'Username', blank=True)),
('address', models.TextField(verbose_name=b'Postal Address', blank=True)),
('membership_type', models.IntegerField(verbose_name=b'Membership Type', choices=[(1, b"O' Day Special"), (2, b'Student'), (3, b'Non Student')])),
('guild_member', models.BooleanField(default=False, verbose_name=b'Guild Member')),
('phone_number', models.CharField(default=False, max_length=14, verbose_name=b'Phone Number', blank=True)),
('email_address', models.CharField(default=False, max_length=200, verbose_name=b'Email Address', blank=True)),
('student_no', models.CharField(default=False, max_length=10, verbose_name=b'Student Number', blank=True)),
('date_of_birth', models.DateField(null=True, verbose_name=b'Date of Birth', blank=True)),
('gender', models.IntegerField(default=1, verbose_name=b'Gender', choices=[(1, b'Male'), (2, b'Female'), (3, b'Other'), (4, b'Undefined')])),
('signed_up', models.DateField(default=datetime.date(2015, 2, 20), verbose_name=b'Signed up')),
],
options={
},
bases=(models.Model,),
),
]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment