mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Django project, first models
This commit is contained in:
10
src/.gitignore
vendored
Normal file
10
src/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
*.sqlite3
|
||||
*.db
|
||||
*.py[cod]
|
||||
*.swp
|
||||
*.aux
|
||||
*.log
|
||||
*.toc
|
||||
*~
|
||||
.ropeproject
|
||||
__pycache__/
|
||||
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
10
src/manage.py
Executable file
10
src/manage.py
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tixl.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
2
src/requirements.txt
Normal file
2
src/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Django>=1.7
|
||||
pyflakes
|
||||
0
src/tixl/__init__.py
Normal file
0
src/tixl/__init__.py
Normal file
96
src/tixl/settings.py
Normal file
96
src/tixl/settings.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Django settings for tixl project.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/dev/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/dev/ref/settings/
|
||||
"""
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '0ro^46+8k#dv3ej=oen-2ww)i30#$$^&x&eajyj&_&h)$nc6@5'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
TEMPLATE_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',
|
||||
'tixlbase',
|
||||
'tixlcontrol',
|
||||
'tixlpresale',
|
||||
)
|
||||
|
||||
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 = 'tixl.urls'
|
||||
|
||||
WSGI_APPLICATION = 'tixl.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/dev/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Authentication
|
||||
|
||||
AUTH_USER_MODEL = 'tixlbase.User'
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/dev/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
pass
|
||||
10
src/tixl/urls.py
Normal file
10
src/tixl/urls.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.conf.urls import patterns, include, url
|
||||
from django.contrib import admin
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Examples:
|
||||
# url(r'^$', 'tixl.views.home', name='home'),
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
14
src/tixl/wsgi.py
Normal file
14
src/tixl/wsgi.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
WSGI config for tixl 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/dev/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tixl.settings")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
||||
0
src/tixlbase/__init__.py
Normal file
0
src/tixlbase/__init__.py
Normal file
3
src/tixlbase/admin.py
Normal file
3
src/tixlbase/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
101
src/tixlbase/migrations/0001_initial.py
Normal file
101
src/tixlbase/migrations/0001_initial.py
Normal file
@@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('password', models.CharField(verbose_name='password', max_length=128)),
|
||||
('last_login', models.DateTimeField(verbose_name='last login', default=django.utils.timezone.now)),
|
||||
('is_superuser', models.BooleanField(verbose_name='superuser status', default=False, help_text='Designates that this user has all permissions without explicitly assigning them.')),
|
||||
('identifier', models.CharField(unique=True, max_length=255)),
|
||||
('username', models.CharField(max_length=120)),
|
||||
('email', models.EmailField(blank=True, null=True, db_index=True, max_length=75)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('is_staff', models.BooleanField(default=False)),
|
||||
('date_joined', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('slug', models.CharField(db_index=True, max_length=50)),
|
||||
('locale', models.CharField(max_length=10)),
|
||||
('currency', models.CharField(max_length=10)),
|
||||
('date_from', models.DateTimeField()),
|
||||
('date_to', models.DateTimeField(blank=True, null=True)),
|
||||
('show_date_to', models.BooleanField(default=True)),
|
||||
('show_times', models.BooleanField(default=True)),
|
||||
('presale_end', models.DateTimeField(blank=True, null=True)),
|
||||
('presale_start', models.DateTimeField(blank=True, null=True)),
|
||||
('payment_term_days', models.IntegerField(default=14)),
|
||||
('payment_term_last', models.DateTimeField(blank=True, null=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('date_from', 'name'),
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Organizer',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('slug', models.CharField(unique=True, db_index=True, max_length=50)),
|
||||
('owner', models.ForeignKey(blank=True, null=True, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='organizer',
|
||||
field=models.ForeignKey(to='tixlbase.Organizer', related_name='events'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='event',
|
||||
unique_together=set([('organizer', 'slug')]),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='event',
|
||||
field=models.ForeignKey(to='tixlbase.Event', blank=True, null=True, related_name='users'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(verbose_name='groups', related_name='user_set', related_query_name='user', blank=True, to='auth.Group', help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='user_permissions',
|
||||
field=models.ManyToManyField(verbose_name='user permissions', related_name='user_set', related_query_name='user', blank=True, to='auth.Permission', help_text='Specific permissions for this user.'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='user',
|
||||
unique_together=set([('event', 'username')]),
|
||||
),
|
||||
]
|
||||
0
src/tixlbase/migrations/__init__.py
Normal file
0
src/tixlbase/migrations/__init__.py
Normal file
153
src/tixlbase/models.py
Normal file
153
src/tixlbase/models.py
Normal file
@@ -0,0 +1,153 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||
|
||||
|
||||
class UserManager(BaseUserManager):
|
||||
"""
|
||||
This is the user manager for our custom user model. See the User
|
||||
model documentation to see what's so special about our user model.
|
||||
"""
|
||||
|
||||
def create_user(self, email, password=None):
|
||||
user = self.model(email=email)
|
||||
user.set_password(user)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
def create_superuser(self, email, password=None):
|
||||
if password is None:
|
||||
raise Exception("You must provide a password")
|
||||
user = self.model(email=email)
|
||||
user.is_staff = True
|
||||
user.is_superuser = True
|
||||
user.set_password(user)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
class User(AbstractBaseUser, PermissionsMixin):
|
||||
"""
|
||||
This is the user model used by tixl for authentication.
|
||||
Handling users is somehow complicated, as we try to have two
|
||||
classes of users in one system:
|
||||
(1) We want global users who can just login into tixl and
|
||||
buy tickets for multiple events -- we also need those
|
||||
global users for event organizers who should not need
|
||||
multiple users for managing multiple events.
|
||||
(2) We want local users who exist only in the scope of a
|
||||
certain event
|
||||
The hard part is to find a primary key to identify all of these
|
||||
users. Letting the users choose usernames is a bad idea, as
|
||||
the primary key needs to be unique and there is no reason for a
|
||||
local user to block a name for all time. Using e-mail addresses
|
||||
is not a good idea either, for two reasons: First, a user might
|
||||
have multiple local users (so they are not unique), and second,
|
||||
it should be possible to create anonymous users without having
|
||||
to supply an e-mail address.
|
||||
Therefore, we use an abstract "identifier" field as the primary
|
||||
key. The identifier is:
|
||||
(1) the e-mail address for global users. An e-mail address
|
||||
is and should be required for them and global users use
|
||||
their e-mail address for login.
|
||||
(2) "{username}@{event.id}.event.tixl" for local users, who
|
||||
use their username to login on the event page.
|
||||
The model's save() method automatically fills the identifier field
|
||||
according to this scheme when it is empty. The __str__() method
|
||||
returns the identifier.
|
||||
|
||||
The is_staff field is only True for system operators.
|
||||
"""
|
||||
|
||||
identifier = models.CharField(max_length=255, unique=True)
|
||||
username = models.CharField(max_length=120)
|
||||
event = models.ForeignKey('Event', related_name="users",
|
||||
null=True, blank=True)
|
||||
email = models.EmailField(unique=False, db_index=True,
|
||||
null=True, blank=True)
|
||||
is_active = models.BooleanField(default=True)
|
||||
is_staff = models.BooleanField(default=False)
|
||||
date_joined = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
objects = UserManager()
|
||||
|
||||
def __str__(self):
|
||||
return self.identifier
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.identifier is None:
|
||||
if self.event is None:
|
||||
self.identifier = self.email
|
||||
else:
|
||||
self.identifier = "%s@%d.event.tixl" % (self.username, self.event.id)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
USERNAME_FIELD = 'identifier'
|
||||
REQUIRED_FIELDS = ['username']
|
||||
|
||||
class Meta:
|
||||
unique_together = (("event", "username"),)
|
||||
|
||||
|
||||
class Organizer(models.Model):
|
||||
"""
|
||||
This model represents an entity organizing events, like a company,
|
||||
an organization or a person. It has one user as owner (who has
|
||||
registered it) and can have any number of users with admin
|
||||
authorization. Any organizer has a unique slug, which is a short
|
||||
name (alphanumeric, all lowercase) being used in URLs.
|
||||
"""
|
||||
|
||||
name = models.CharField(max_length=200)
|
||||
slug = models.CharField(max_length=50,
|
||||
unique=True,
|
||||
db_index=True)
|
||||
owner = models.ForeignKey(User, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
"""
|
||||
This model represents an event. An event is anything you can buy
|
||||
tickets for. It belongs to one orgnaizer and has a name and a slug,
|
||||
the latter being a short, alphanumeric, all-lowercase name being
|
||||
used in URLs. The slug has to be unique among the events of the same
|
||||
organizer.
|
||||
|
||||
An event can hold several properties, such as a default locale and
|
||||
currency.
|
||||
|
||||
The event has date_from and date_to field which mark the actual
|
||||
datetime of the event itself. The show_date_to and show_times
|
||||
fields are used to control the display of these dates. (Without
|
||||
show_times only days are shown, now times.)
|
||||
|
||||
The presale_start and presale_end fields mark the time frame in
|
||||
which tickets are sold for this event. These two dates override
|
||||
every other restrictions to ticket sale if set.
|
||||
|
||||
The payment_term_days field holds the number of days after
|
||||
submitting a ticket order, in which the ticket has to be paid.
|
||||
The payment_term_last is the day all orders must be paid by, no
|
||||
matter when they were ordered (and thus, ignoring payment_term_days).
|
||||
"""
|
||||
|
||||
organizer = models.ForeignKey(Organizer, related_name="events")
|
||||
name = models.CharField(max_length=200)
|
||||
slug = models.CharField(max_length=50,
|
||||
db_index=True)
|
||||
locale = models.CharField(max_length=10)
|
||||
currency = models.CharField(max_length=10)
|
||||
date_from = models.DateTimeField()
|
||||
date_to = models.DateTimeField(null=True, blank=True)
|
||||
show_date_to = models.BooleanField(default=True)
|
||||
show_times = models.BooleanField(default=True)
|
||||
presale_end = models.DateTimeField(null=True, blank=True)
|
||||
presale_start = models.DateTimeField(null=True, blank=True)
|
||||
payment_term_days = models.IntegerField(default=14)
|
||||
payment_term_last = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = (("organizer", "slug"),)
|
||||
ordering = ("date_from", "name")
|
||||
3
src/tixlbase/tests.py
Normal file
3
src/tixlbase/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
3
src/tixlbase/views.py
Normal file
3
src/tixlbase/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
0
src/tixlcontrol/__init__.py
Normal file
0
src/tixlcontrol/__init__.py
Normal file
3
src/tixlcontrol/admin.py
Normal file
3
src/tixlcontrol/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
0
src/tixlcontrol/migrations/__init__.py
Normal file
0
src/tixlcontrol/migrations/__init__.py
Normal file
3
src/tixlcontrol/tests.py
Normal file
3
src/tixlcontrol/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
3
src/tixlcontrol/views.py
Normal file
3
src/tixlcontrol/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
0
src/tixlpresale/__init__.py
Normal file
0
src/tixlpresale/__init__.py
Normal file
3
src/tixlpresale/admin.py
Normal file
3
src/tixlpresale/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
0
src/tixlpresale/migrations/__init__.py
Normal file
0
src/tixlpresale/migrations/__init__.py
Normal file
3
src/tixlpresale/tests.py
Normal file
3
src/tixlpresale/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
3
src/tixlpresale/views.py
Normal file
3
src/tixlpresale/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Reference in New Issue
Block a user