layout restructure
6
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
# Compressed / cached static files
|
||||
src/static/CACHE/
|
||||
# Static & media files
|
||||
staticfiles/
|
||||
static/CACHE/
|
||||
media/
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
@ -3,4 +3,5 @@ from django.apps import AppConfig
|
||||
|
||||
class ApiConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'api'
|
||||
name = 'apps.api'
|
||||
label = "apps_api"
|
@ -3,4 +3,5 @@ from django.apps import AppConfig
|
||||
|
||||
class MainappConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'mainapp'
|
||||
name = 'apps.home'
|
||||
label = "apps_home"
|
234
apps/home/migrations/0001_initial.py
Normal file
@ -0,0 +1,234 @@
|
||||
# Generated by Django 5.0.6 on 2024-11-05 11:39
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Angler',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('redact', models.BooleanField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AnglerGroupType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CompetitorType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FishType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LeagueRule',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MatchType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Sponsor',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('url', models.URLField()),
|
||||
('image', models.ImageField(upload_to='')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Venue',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('description', models.CharField(max_length=384)),
|
||||
('extra_notes', models.CharField(max_length=1028)),
|
||||
('created_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('updated_at', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
|
||||
('profile_picture', models.ImageField(upload_to='')),
|
||||
('banner_picture', models.ImageField(upload_to='')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VenueAddress',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('street_number', models.IntegerField()),
|
||||
('street_address', models.CharField(max_length=256)),
|
||||
('town', models.CharField(max_length=256)),
|
||||
('county', models.CharField(max_length=256)),
|
||||
('post_code', models.CharField(max_length=32)),
|
||||
('satnav_post_code', models.CharField(max_length=32)),
|
||||
('country', models.CharField(max_length=128)),
|
||||
('latitude', models.DecimalField(decimal_places=16, max_digits=22)),
|
||||
('longitude', models.DecimalField(decimal_places=16, max_digits=22)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VenueContacts',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('phone_number', models.CharField(max_length=64)),
|
||||
('email_address', models.EmailField(max_length=254)),
|
||||
('website_url', models.URLField()),
|
||||
('facebook_url', models.URLField()),
|
||||
('twitter_url', models.URLField()),
|
||||
('instagram_url', models.URLField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VenueType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WatersType',
|
||||
fields=[
|
||||
('name', models.CharField(max_length=128)),
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AnglerGroup',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('anglers', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.angler')),
|
||||
('type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.anglergrouptype')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Match',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('description', models.CharField(max_length=384)),
|
||||
('meeting_point', models.CharField(max_length=1024)),
|
||||
('use_metric', models.BooleanField()),
|
||||
('allow_in_tournaments', models.BooleanField()),
|
||||
('start_datetime', models.DateTimeField()),
|
||||
('end_datetime', models.DateTimeField()),
|
||||
('draw_datetime', models.DateTimeField()),
|
||||
('competitor_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.competitortype')),
|
||||
('type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.matchtype')),
|
||||
('venue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.venue')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='League',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('description', models.CharField(max_length=384)),
|
||||
('extra_notes', models.CharField(max_length=1028)),
|
||||
('profile_picture', models.ImageField(upload_to='')),
|
||||
('banner_picture', models.ImageField(upload_to='')),
|
||||
('anglers', models.ManyToManyField(to='apps_home.angler')),
|
||||
('rules', models.ManyToManyField(to='apps_home.leaguerule')),
|
||||
('matches', models.ManyToManyField(to='apps_home.match')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LeagueResult',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('total_weight', models.CharField(max_length=64)),
|
||||
('matches', models.IntegerField()),
|
||||
('date', models.DateField(default=django.utils.timezone.now)),
|
||||
('angler', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.angler')),
|
||||
('league', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.league')),
|
||||
('sponsor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apps_home.sponsor')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='venue',
|
||||
name='address',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.venueaddress'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='venue',
|
||||
name='contacts',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.venuecontacts'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='venue',
|
||||
name='type',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.venuetype'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Waters',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('pegs_from', models.IntegerField()),
|
||||
('pegs_to', models.IntegerField()),
|
||||
('map', models.ImageField(upload_to='')),
|
||||
('fish_types', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.fishtype')),
|
||||
('type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.waterstype')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='venue',
|
||||
name='waters',
|
||||
field=models.ManyToManyField(to='apps_home.waters'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='match',
|
||||
name='waters',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apps_home.waters'),
|
||||
),
|
||||
]
|
@ -61,7 +61,7 @@ class Waters(models.Model):
|
||||
map = models.ImageField()
|
||||
|
||||
type = models.ForeignKey(to=WatersType, on_delete=models.CASCADE)
|
||||
fish_types = models.ForeignKey()
|
||||
fish_types = models.ForeignKey(to=FishType, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -127,6 +127,33 @@ class Venue(models.Model):
|
||||
|
||||
# region Leagues & Matches
|
||||
|
||||
class CompetitorType(GenericTypeModel):
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
|
||||
class MatchType(GenericTypeModel):
|
||||
id = models.AutoField(primary_key=True)
|
||||
|
||||
|
||||
class Match(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=128)
|
||||
description = models.CharField(max_length=384)
|
||||
|
||||
venue = models.ForeignKey(to=Venue, on_delete=models.CASCADE)
|
||||
waters = models.ForeignKey(to=Waters, on_delete=models.CASCADE) # can only select waters from the matching venue
|
||||
|
||||
meeting_point = models.CharField(max_length=1024)
|
||||
use_metric = models.BooleanField()
|
||||
allow_in_tournaments = models.BooleanField()
|
||||
|
||||
start_datetime = models.DateTimeField()
|
||||
end_datetime = models.DateTimeField()
|
||||
draw_datetime = models.DateTimeField()
|
||||
|
||||
type = models.ForeignKey(to=MatchType, on_delete=models.CASCADE)
|
||||
competitor_type = models.ForeignKey(to=CompetitorType, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class LeagueRule(models.Model):
|
||||
pass
|
||||
@ -141,11 +168,17 @@ class League(models.Model):
|
||||
profile_picture = models.ImageField()
|
||||
banner_picture = models.ImageField()
|
||||
|
||||
matches = models.ForeignKey()
|
||||
anglers = models.ForeignKey()
|
||||
results = models.ManyToManyField()
|
||||
matches = models.ManyToManyField(to=Match)
|
||||
anglers = models.ManyToManyField(to=Angler)
|
||||
rules = models.ManyToManyField(to=LeagueRule)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return LeagueResult.objects.filter(league=self)
|
||||
|
||||
|
||||
class Sponsor(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
@ -11,6 +11,6 @@ import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Results.settings')
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||
|
||||
application = get_asgi_application()
|
210
core/settings.py
Normal file
@ -0,0 +1,210 @@
|
||||
"""
|
||||
Django settings for Results project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 4.1.5.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/4.1/ref/settings/
|
||||
"""
|
||||
|
||||
import json
|
||||
import environ
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
VERSION = "0.0.0"
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / "subdir".
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
# Environment Variables
|
||||
env = environ.Env(DEBUG=(bool, True))
|
||||
environ.Env.read_env(BASE_DIR / ".env")
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = env("RESULTS_SYSTEM__SECRET_KEY", default="unsecure-default-secret-key")
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = env("RESULTS_SYSTEM__DEBUG").lower() == "true"
|
||||
|
||||
CSRF_TRUSTED_ORIGINS = [
|
||||
"http://localhost",
|
||||
"http://127.0.0.1",
|
||||
"https://" + env("RESULTS_SYSTEM__HOST", default="127.0.0.1")
|
||||
]
|
||||
ALLOWED_HOSTS = [
|
||||
host.replace("http://", "").replace("https://", "")
|
||||
for host in CSRF_TRUSTED_ORIGINS
|
||||
]
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"rest_framework",
|
||||
"compressor",
|
||||
"apps.api",
|
||||
"apps.home",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "core.urls"
|
||||
APPEND_SLASH = True
|
||||
|
||||
LOGIN_URL = "/login/"
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
LOGOUT_REDIRECT_URL = "/"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [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 = "core.wsgi.application"
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
|
||||
|
||||
DB_ENGINE = env("RESULTS_SYSTEM__DB_ENGINE", default=None)
|
||||
|
||||
if not DB_ENGINE:
|
||||
db_data = {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": "db.sqlite3"
|
||||
}
|
||||
else:
|
||||
db_data = {
|
||||
"ENGINE": env("DB_ENGINE"),
|
||||
"NAME": env("DB_NAME"),
|
||||
"USER": env("DB_USER"),
|
||||
"PASSWORD": env("DB_PASS"),
|
||||
"HOST": env("DB_HOST"),
|
||||
"PORT": env("DB_PORT")
|
||||
}
|
||||
|
||||
DATABASES = { "default": db_data }
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" },
|
||||
{ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator" },
|
||||
{ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator" },
|
||||
{ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator" },
|
||||
]
|
||||
|
||||
|
||||
# Logging
|
||||
# https://docs.djangoproject.com/en/5.0/topics/logging/
|
||||
|
||||
LOGGING_DIR = BASE_DIR / "logs"
|
||||
LOGGING_DIR.mkdir(exist_ok=True)
|
||||
|
||||
with open(LOGGING_DIR / "config.json", "r", encoding="utf-8") as file:
|
||||
LOGGING = json.load(file)
|
||||
|
||||
LOGGING["handlers"]["file"]["filename"] = LOGGING_DIR / f"{timezone.now()}.log"
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = "en-gb"
|
||||
TIME_ZONE = "Europe/London"
|
||||
USE_I18N = True
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.1/howto/static-files/
|
||||
|
||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||
STATIC_URL = "/static/"
|
||||
STATICFILES_DIRS = (BASE_DIR / "static",)
|
||||
STATICFILES_FINDERS = (
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
"compressor.finders.CompressorFinder",
|
||||
)
|
||||
|
||||
|
||||
# Compressors
|
||||
|
||||
COMPRESS_ENABLED = True
|
||||
COMPRESS_OFFLINE = not DEBUG
|
||||
COMPRESS_PRECOMPILERS = [("text/x-scss", "django_libsass.SassCompiler")]
|
||||
COMPRESS_CSS_FILTERS = ["compressor.filters.css_default.CssAbsoluteIdentifier"]
|
||||
# LIBSASS_ADDITIONAL_INCLUDE_PATHS = [str(BASE_DIR / "static/bootstrap-5.3.3/scss")]
|
||||
|
||||
|
||||
# Media Files
|
||||
|
||||
MEDIA_ROOT = BASE_DIR / "media"
|
||||
MEDIA_URL = "/media/"
|
||||
|
||||
|
||||
# region Rest Framework
|
||||
# https://www.django-rest-framework.org/
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_THROTTLE_CLASSES": [
|
||||
"rest_framework.throttling.AnonRateThrottle",
|
||||
"rest_framework.throttling.UserRateThrottle"
|
||||
],
|
||||
"DEFAULT_THROTTLE_RATES": {
|
||||
"anon": "100/day",
|
||||
"user": "10000/hour"
|
||||
},
|
||||
"DEFAULT_RENDERER_CLASSES": [
|
||||
"apps.api.renderers.FixedJSONRenderer",
|
||||
# "rest_framework.renderers.AdminRenderer",
|
||||
"rest_framework.renderers.BrowsableAPIRenderer"
|
||||
],
|
||||
"EXCEPTION_HANDLER": "apps.api.exceptions.conflict_exception_handler"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
@ -19,5 +19,5 @@ from django.urls import path, include
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
# path('api/', include('api.urls')),
|
||||
path('', include('mainapp.urls')),
|
||||
path('', include('apps.home.urls')),
|
||||
]
|
@ -11,6 +11,6 @@ import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Results.settings')
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||
|
||||
application = get_wsgi_application()
|
54
logs/config.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": false,
|
||||
"formatters": {
|
||||
"simple": {
|
||||
"format": "[%(module)s|%(levelname)s] %(message)s"
|
||||
},
|
||||
"detail": {
|
||||
"format": "[%(asctime)s] [%(levelname)s] [%(module)s]: %(message)s"
|
||||
},
|
||||
"complex": {
|
||||
"format": "[%(levelname)s|%(name)s|L%(lineno)d] %(asctime)s %(message)s",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%S%z"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"file": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.FileHandler",
|
||||
"formatter": "complex"
|
||||
},
|
||||
"stdout": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "simple",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
"queue_handler": {
|
||||
"respect_handler_level": true,
|
||||
"class": "logging.handlers.QueueHandler",
|
||||
"handlers": [
|
||||
"file",
|
||||
"stdout"
|
||||
]
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"root": {
|
||||
"level": "DEBUG",
|
||||
"handlers": [
|
||||
"queue_handler"
|
||||
]
|
||||
},
|
||||
"apps": {
|
||||
"level": "DEBUG"
|
||||
},
|
||||
"django": {
|
||||
"level": "INFO"
|
||||
},
|
||||
"django.request": {
|
||||
"level": "ERROR"
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import sys
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Results.settings')
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
BIN
requirements.txt
@ -1,155 +0,0 @@
|
||||
"""
|
||||
Django settings for Results project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 4.1.5.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/4.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-==z9@atc)#1c@%@+txwiie=3qk)9r92antn3b$v#4o8r2q63&d'
|
||||
|
||||
# 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',
|
||||
# 'rest_framework_datatables'
|
||||
'rest_framework',
|
||||
'mainapp',
|
||||
'api',
|
||||
'compressor',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'Results.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [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 = 'Results.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.1/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATICFILES_DIRS = [BASE_DIR / 'static/']
|
||||
STATICFILES_FINDERS = ["compressor.finders.CompressorFinder"]
|
||||
|
||||
# Compressors
|
||||
|
||||
COMPRESS_OFFLINE = True
|
||||
LIBSASS_OUTPUT_STYLE = "compressed"
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
("text/x-scss", "django_libsass.SassCompiler"),
|
||||
)
|
||||
COMPRESS_ROOT = BASE_DIR / 'static/'
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
# Rest Framework for Data Table
|
||||
|
||||
#REST_FRAMEWORK = {
|
||||
# 'DEFAULT_RENDERER_CLASSES': (
|
||||
# 'rest_framework.renderers.JSONRenderer',
|
||||
# 'rest_framework.renderers.BrowsableAPIRenderer',
|
||||
# 'rest_framework_datatables.renderers.DatatablesRenderer',
|
||||
# ),
|
||||
# 'DEFAULT_FILTER_BACKENDS': (
|
||||
# 'rest_framework_datatables.filters.DatatablesFilterBackend',
|
||||
# ),
|
||||
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesPageNumberPagination',
|
||||
# 'PAGE_SIZE': 50,
|
||||
#}
|
@ -1,40 +0,0 @@
|
||||
# Generated by Django 4.1.5 on 2023-05-15 11:20
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Section',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('character', models.CharField(max_length=3, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Team',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.PositiveIntegerField(unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Member',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('first_name', models.CharField(max_length=255)),
|
||||
('last_name', models.CharField(max_length=255)),
|
||||
('peg_number', models.PositiveIntegerField(null=True, unique=True)),
|
||||
('section', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='members', to='mainapp.section')),
|
||||
('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='members', to='mainapp.team')),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,45 +0,0 @@
|
||||
# Generated by Django 4.1.5 on 2023-10-22 21:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Venue',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('extra_notes', models.TextField(blank=True)),
|
||||
('venue_type', models.CharField(choices=[('FISHERY', 'Fishery'), ('CLUB', 'Club'), ('PRIVATE', 'Private')], max_length=50)),
|
||||
('phone_number', models.CharField(max_length=100)),
|
||||
('email_address', models.EmailField(max_length=254)),
|
||||
('website_url', models.URLField()),
|
||||
('street_address', models.CharField(max_length=100)),
|
||||
('city', models.CharField(max_length=255)),
|
||||
('provence', models.CharField(max_length=100)),
|
||||
('postal_code', models.CharField(max_length=20)),
|
||||
('country', models.CharField(max_length=100)),
|
||||
('latitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('longitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
||||
('twitter_url', models.URLField(blank=True)),
|
||||
('instagram_url', models.URLField(blank=True)),
|
||||
('facebook_url', models.URLField(blank=True)),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Member',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Section',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Team',
|
||||
),
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
# Generated by Django 4.1.5 on 2023-10-23 22:17
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0002_venue_delete_member_delete_section_delete_team'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Waters',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('description', models.TextField(max_length=255)),
|
||||
('pegs_min', models.IntegerField()),
|
||||
('pegs_max', models.IntegerField()),
|
||||
('water_type', models.CharField(choices=[('CW', 'Commercial Water'), ('NSW', 'Natural Still Water'), ('C', 'Canal'), ('R', 'River'), ('L', 'Loch')], max_length=50)),
|
||||
('fish_type', models.CharField(choices=[('C', 'Coarse'), ('SC', 'Specimen Carp'), ('G', 'Game'), ('P', 'Predator')], max_length=50)),
|
||||
('venue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mainapp.venue')),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,23 +0,0 @@
|
||||
# Generated by Django 4.1.5 on 2023-11-06 20:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0003_waters'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='venue',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, max_length=500),
|
||||
),
|
||||
]
|
@ -1,88 +0,0 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-26 20:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0004_venue_active_alter_venue_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='city',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='country',
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, max_length=500, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='email_address',
|
||||
field=models.EmailField(blank=True, max_length=254, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='extra_notes',
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='facebook_url',
|
||||
field=models.URLField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='instagram_url',
|
||||
field=models.URLField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='phone_number',
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='postal_code',
|
||||
field=models.CharField(blank=True, max_length=20, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='provence',
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='street_address',
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='twitter_url',
|
||||
field=models.URLField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='venue_type',
|
||||
field=models.CharField(blank=True, choices=[('FISHERY', 'Fishery'), ('CLUB', 'Club'), ('PRIVATE', 'Private')], max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='venue',
|
||||
name='website_url',
|
||||
field=models.URLField(blank=True, null=True),
|
||||
),
|
||||
]
|
@ -1,23 +0,0 @@
|
||||
# Generated by Django 5.0.6 on 2024-11-05 09:51
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0005_alter_venue_city_alter_venue_country_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='waters',
|
||||
name='venue',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Venue',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Waters',
|
||||
),
|
||||
]
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 504 B After Width: | Height: | Size: 504 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 677 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 784 B After Width: | Height: | Size: 784 B |
Before Width: | Height: | Size: 560 B After Width: | Height: | Size: 560 B |
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 581 B After Width: | Height: | Size: 581 B |
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 436 B |
Before Width: | Height: | Size: 560 B After Width: | Height: | Size: 560 B |
Before Width: | Height: | Size: 458 B After Width: | Height: | Size: 458 B |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B |