black backend

This commit is contained in:
Paul Mathieu 2025-08-07 12:09:27 +02:00
parent 684987dfd5
commit ba34b2d647
14 changed files with 296 additions and 203 deletions

View File

@ -6,7 +6,7 @@ import sys
def main(): def main():
"""Run administrative tasks.""" """Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zetikettes.settings') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zetikettes.settings")
try: try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError as exc: except ImportError as exc:
@ -18,5 +18,5 @@ def main():
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class TiketteConfig(AppConfig): class TiketteConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = "django.db.models.BigAutoField"
name = 'tikette' name = "tikette"

View File

@ -1,9 +1,10 @@
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse from django.http import HttpResponse
def cors_everywhere(get_response): def cors_everywhere(get_response):
def middleware(request): def middleware(request):
if request.method == 'OPTIONS': if request.method == "OPTIONS":
response = HttpResponse() response = HttpResponse()
else: else:
response = get_response(request) response = get_response(request)

View File

@ -8,64 +8,120 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = []
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Tikategory', name="Tikategory",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.CharField(max_length=50)), "id",
('landscape', models.BooleanField()), models.BigAutoField(
('prototempalte', models.FileField(upload_to='')), auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=50)),
("landscape", models.BooleanField()),
("prototempalte", models.FileField(upload_to="")),
], ],
options={ options={
'verbose_name_plural': 'tikategoriez', "verbose_name_plural": "tikategoriez",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Tisub', name="Tisub",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.CharField(max_length=50)), "id",
('descritpion', models.TextField()), models.BigAutoField(
('default', models.TextField()), auto_created=True,
('type', models.CharField(choices=[('ST', 'Short Text'), ('LT', 'Long Text'), ('C', 'Color'), ('YM', 'Year Month'), ('B', 'Boolean')], default='ST', max_length=2)), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=50)),
("descritpion", models.TextField()),
("default", models.TextField()),
(
"type",
models.CharField(
choices=[
("ST", "Short Text"),
("LT", "Long Text"),
("C", "Color"),
("YM", "Year Month"),
("B", "Boolean"),
],
default="ST",
max_length=2,
),
),
], ],
options={ options={
'verbose_name_plural': 'tisubz', "verbose_name_plural": "tisubz",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Tizer', name="Tizer",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('email', models.CharField()), "id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("email", models.CharField()),
], ],
options={ options={
'verbose_name_plural': 'tizerz', "verbose_name_plural": "tizerz",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Tikette', name="Tikette",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('title', models.CharField(max_length=100)), "id",
('designation', models.CharField(max_length=100)), models.BigAutoField(
('ingredients', models.TextField()), auto_created=True,
('description', models.TextField()), primary_key=True,
('color', models.CharField(max_length=6)), serialize=False,
('ab', models.CharField(choices=[('inline', 'Visible'), ('none', 'Invisible')], max_length=7)), verbose_name="ID",
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tikette.tikategory')), ),
),
("title", models.CharField(max_length=100)),
("designation", models.CharField(max_length=100)),
("ingredients", models.TextField()),
("description", models.TextField()),
("color", models.CharField(max_length=6)),
(
"ab",
models.CharField(
choices=[("inline", "Visible"), ("none", "Invisible")],
max_length=7,
),
),
(
"category",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="tikette.tikategory",
),
),
], ],
options={ options={
'verbose_name_plural': 'tikettz', "verbose_name_plural": "tikettz",
}, },
), ),
migrations.AddField( migrations.AddField(
model_name='tikategory', model_name="tikategory",
name='subs', name="subs",
field=models.ManyToManyField(to='tikette.tisub'), field=models.ManyToManyField(to="tikette.tisub"),
), ),
] ]

View File

@ -1,5 +1,6 @@
from django.db import models from django.db import models
class Tisub(models.Model): class Tisub(models.Model):
class Type(models.TextChoices): class Type(models.TextChoices):
SHORT_TEXT = "ST" SHORT_TEXT = "ST"
@ -27,7 +28,7 @@ class Tikategory(models.Model):
subs = models.ManyToManyField(Tisub) subs = models.ManyToManyField(Tisub)
# For now we'll hardcode the following:xi # For now we'll hardcode the following:xi
# [designation, ingredients, description, color, AB, designation_fontsize] # [designation, ingredients, description, color, AB, designation_fontsize]
#protosubs = models.ManyToManyField(Tisub, related_name="protosubs") # protosubs = models.ManyToManyField(Tisub, related_name="protosubs")
prototempalte = models.FileField() prototempalte = models.FileField()
def __str__(self): def __str__(self):

View File

@ -11,13 +11,18 @@ DESIGNATION_FONTSIZE = 42.6667
def inkscapize(svg_in, pdf_out): def inkscapize(svg_in, pdf_out):
png_out = tempfile.mktemp(suffix='.png') png_out = tempfile.mktemp(suffix=".png")
try: try:
cmd = ['inkscape', '--export-type=png', f'--export-filename={png_out}', cmd = [
f'--export-dpi={DEFAULT_DPI}', svg_in] "inkscape",
"--export-type=png",
f"--export-filename={png_out}",
f"--export-dpi={DEFAULT_DPI}",
svg_in,
]
subprocess.check_call(cmd) subprocess.check_call(cmd)
cmd = ['convert', png_out, pdf_out] cmd = ["convert", png_out, pdf_out]
subprocess.check_call(cmd) subprocess.check_call(cmd)
finally: finally:
if os.path.exists(png_out): if os.path.exists(png_out):
@ -25,7 +30,7 @@ def inkscapize(svg_in, pdf_out):
def generate(template, subs, out_dir, landscape=False): def generate(template, subs, out_dir, landscape=False):
""" Generate a sticker sheet. """Generate a sticker sheet.
template: file name for the sticker template template: file name for the sticker template
subs: dict-like with key-value template subtitution fields subs: dict-like with key-value template subtitution fields
@ -34,24 +39,25 @@ def generate(template, subs, out_dir, landscape=False):
""" """
# default designation font size # default designation font size
subs['designation_fontsize'] = subs.get('designation_fontsize', subs["designation_fontsize"] = subs.get(
DESIGNATION_FONTSIZE) "designation_fontsize", DESIGNATION_FONTSIZE
)
# fill in sticker details # fill in sticker details
sticker_out = tempfile.mktemp(suffix='.svg') sticker_out = tempfile.mktemp(suffix=".svg")
try: try:
with open(sticker_out, 'w') as stickout: with open(sticker_out, "w") as stickout:
makesticker(os.path.join(out_dir, template), stickout, subs) makesticker(os.path.join(out_dir, template), stickout, subs)
# make sticker sheet # make sticker sheet
planche_out = tempfile.mktemp(suffix='.svg') planche_out = tempfile.mktemp(suffix=".svg")
with open(sticker_out, 'r') as stickin: with open(sticker_out, "r") as stickin:
with open(planche_out, 'w') as planchout: with open(planche_out, "w") as planchout:
makeplanche(stickin, planchout, landscape=landscape) makeplanche(stickin, planchout, landscape=landscape)
# process to printable pdf # process to printable pdf
pdf_out = tempfile.mktemp(dir=out_dir, suffix='.pdf') pdf_out = tempfile.mktemp(dir=out_dir, suffix=".pdf")
inkscapize(planche_out, pdf_out) inkscapize(planche_out, pdf_out)
return os.path.basename(pdf_out) return os.path.basename(pdf_out)
@ -59,5 +65,5 @@ def generate(template, subs, out_dir, landscape=False):
finally: finally:
if os.path.exists(sticker_out): if os.path.exists(sticker_out):
os.unlink(sticker_out) os.unlink(sticker_out)
if 'planche_out' in locals() and os.path.exists(planche_out): if "planche_out" in locals() and os.path.exists(planche_out):
os.unlink(planche_out) os.unlink(planche_out)

View File

@ -5,47 +5,54 @@ from pathlib import Path
from string import Template from string import Template
import sys import sys
DEFAULT_SHEET_TEMPLATE = Path(__file__).parent / 'planche.svg.in' DEFAULT_SHEET_TEMPLATE = Path(__file__).parent / "planche.svg.in"
def parse_args(): def parse_args():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(description="Make a sheet with 12 stickers")
description='Make a sheet with 12 stickers') parser.add_argument(
parser.add_argument('--template', "--template",
'-t', "-t",
default=DEFAULT_SHEET_TEMPLATE, default=DEFAULT_SHEET_TEMPLATE,
help='path to the sheet template') help="path to the sheet template",
parser.add_argument('--out', )
'-o', parser.add_argument(
default=sys.stdout, "--out",
type=argparse.FileType('w'), "-o",
help='output path (default: stdout)') default=sys.stdout,
parser.add_argument('--landscape', type=argparse.FileType("w"),
action='store_true', help="output path (default: stdout)",
help='input sticker is in landscape orientation') )
parser.add_argument('sticker', parser.add_argument(
type=argparse.FileType('r'), "--landscape",
default=sys.stdin, action="store_true",
nargs='?', help="input sticker is in landscape orientation",
help='path to the sticker SVG (default: stdin)') )
parser.add_argument(
"sticker",
type=argparse.FileType("r"),
default=sys.stdin,
nargs="?",
help="path to the sticker SVG (default: stdin)",
)
return parser.parse_args() return parser.parse_args()
def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE ,landscape=False): def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE, landscape=False):
with open(template) as tpl: with open(template) as tpl:
tpl_data = tpl.read() tpl_data = tpl.read()
lines = sticker.readlines() lines = sticker.readlines()
if lines[0].startswith('<?xml'): if lines[0].startswith("<?xml"):
lines = lines[1:] lines = lines[1:]
sticker_data = ''.join(lines) sticker_data = "".join(lines)
rotate = "translate(102, 0) rotate(90)" if not landscape else "" rotate = "translate(102, 0) rotate(90)" if not landscape else ""
subs = { subs = {
'sticker': sticker_data, "sticker": sticker_data,
'rotate': rotate, "rotate": rotate,
} }
out.write(Template(tpl_data).substitute(subs)) out.write(Template(tpl_data).substitute(subs))

View File

@ -7,22 +7,25 @@ import typing
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description='Fill in sticker details') parser = argparse.ArgumentParser(description="Fill in sticker details")
parser.add_argument('--out', parser.add_argument(
'-o', "--out",
default=sys.stdout, "-o",
type=argparse.FileType('w'), default=sys.stdout,
help='output path (default: stdout)') type=argparse.FileType("w"),
parser.add_argument('--dluo', help="output path (default: stdout)",
'-d', )
required=True, parser.add_argument(
help='Date Limite d\'Utilisation Optimale') "--dluo", "-d", required=True, help="Date Limite d'Utilisation Optimale"
parser.add_argument('--lot', '-l', required=True, help='Numéro de lot') )
parser.add_argument('--quantite', '-q', required=False, help='Quantité (volume ou masse)') parser.add_argument("--lot", "-l", required=True, help="Numéro de lot")
parser.add_argument('--teneur', '-t', required=False, help='Teneur en sucre') parser.add_argument(
parser.add_argument('--fruit', '-f', required=False, help='Quantité de fruits') "--quantite", "-q", required=False, help="Quantité (volume ou masse)"
parser.add_argument('--size', '-s', required=False, help='Masse de produit') )
parser.add_argument('sticker', help='path to the sticker template') parser.add_argument("--teneur", "-t", required=False, help="Teneur en sucre")
parser.add_argument("--fruit", "-f", required=False, help="Quantité de fruits")
parser.add_argument("--size", "-s", required=False, help="Masse de produit")
parser.add_argument("sticker", help="path to the sticker template")
return parser.parse_args() return parser.parse_args()
@ -30,9 +33,9 @@ def parse_args():
def makesticker(sticker: str, out: typing.IO, subs: dict): def makesticker(sticker: str, out: typing.IO, subs: dict):
with open(sticker) as fin: with open(sticker) as fin:
lines = fin.readlines() lines = fin.readlines()
if lines[0].startswith('<?xml'): if lines[0].startswith("<?xml"):
lines = lines[1:] lines = lines[1:]
sticker_data = ''.join(lines) sticker_data = "".join(lines)
out.write(Template(sticker_data).substitute(subs)) out.write(Template(sticker_data).substitute(subs))
@ -40,12 +43,12 @@ def makesticker(sticker: str, out: typing.IO, subs: dict):
if __name__ == "__main__": if __name__ == "__main__":
args = vars(parse_args()) args = vars(parse_args())
subs = { subs = {
'dluo': args.pop('dluo'), "dluo": args.pop("dluo"),
'lot': args.pop('lot'), "lot": args.pop("lot"),
'teneur': args.pop('teneur'), "teneur": args.pop("teneur"),
'f': args.pop('fruit'), "f": args.pop("fruit"),
'q': args.pop('quantite'), "q": args.pop("quantite"),
'size': args.pop('size'), "size": args.pop("size"),
} }
args['subs'] = subs args["subs"] = subs
makesticker(**args) makesticker(**args)

View File

@ -14,15 +14,19 @@ from .models import Tikette, Tikategory, Tizer
def ok(payload=None): def ok(payload=None):
return JsonResponse({'status': 'ok', **(payload or {})}) return JsonResponse({"status": "ok", **(payload or {})})
def post_please(f): def post_please(f):
def __f(request): def __f(request):
if request.method != "POST": if request.method != "POST":
return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'}, return JsonResponse(
status=405, headers={'Allow': 'POST'}) {"status": "notok", "message": "this isn't the way"},
status=405,
headers={"Allow": "POST"},
)
return f(request) return f(request)
return __f return __f
@ -30,20 +34,21 @@ def auth_only(f):
def __f(request): def __f(request):
# check that email is valid # check that email is valid
# exp? # exp?
if 'user_data' not in request.session: if "user_data" not in request.session:
raise PermissionDenied('Not logged in') raise PermissionDenied("Not logged in")
email = request.session['user_data']['email'] email = request.session["user_data"]["email"]
resp = Tizer.objects.filter(email=email) resp = Tizer.objects.filter(email=email)
if not resp: if not resp:
raise PermissionDenied('User not found') raise PermissionDenied("User not found")
return f(request) return f(request)
return __f return __f
def quirk_bold_allergens(ingredients): def quirk_bold_allergens(ingredients):
out = [] out = []
for ing in (x.strip() for x in ingredients.split(',')): for ing in (x.strip() for x in ingredients.split(",")):
if ing.startswith('*'): if ing.startswith("*"):
out.append(f'<tspan style="font-weight:bold">{ing[1:]}</tspan>') out.append(f'<tspan style="font-weight:bold">{ing[1:]}</tspan>')
else: else:
out.append(ing) out.append(ing)
@ -51,40 +56,48 @@ def quirk_bold_allergens(ingredients):
def handler403(request, exception): def handler403(request, exception):
return JsonResponse({'status': 'notok', 'message': 'permission denied'}, status=403) return JsonResponse({"status": "notok", "message": "permission denied"}, status=403)
def handler404(request, exception): def handler404(request, exception):
return JsonResponse({'status': 'notok', 'message': 'endpoint not found'}, status=404) return JsonResponse(
{"status": "notok", "message": "endpoint not found"}, status=404
)
@auth_only @auth_only
@ensure_csrf_cookie @ensure_csrf_cookie
def get_list(request): def get_list(request):
tikettes = [{ tikettes = [
'id': x.id, {
'title': x.title, "id": x.id,
'category': x.category.name, "title": x.title,
'category_id': x.category.id, "category": x.category.name,
'prototempalte': x.category.prototempalte.name, "category_id": x.category.id,
'landscape': x.category.landscape, "prototempalte": x.category.prototempalte.name,
'designation': x.designation, "landscape": x.category.landscape,
'ingredients': x.ingredients, "designation": x.designation,
'description': x.description, "ingredients": x.ingredients,
'ab': x.ab, "description": x.description,
'color': x.color, "ab": x.ab,
'subs': {x.name: x.default for x in x.category.subs.all()}, "color": x.color,
} for x in Tikette.objects.all()] "subs": {x.name: x.default for x in x.category.subs.all()},
return ok({'tikettes': tikettes}) }
for x in Tikette.objects.all()
]
return ok({"tikettes": tikettes})
@auth_only @auth_only
def get_categories(request): def get_categories(request):
tikats = [{ tikats = [
'id': x.id, {
'name': x.name, "id": x.id,
} for x in Tikategory.objects.all()] "name": x.name,
return ok({'tikats': tikats}) }
for x in Tikategory.objects.all()
]
return ok({"tikats": tikats})
@auth_only @auth_only
@ -92,17 +105,20 @@ def get_categories(request):
def generate(request): def generate(request):
payload = json.loads(request.body) payload = json.loads(request.body)
subs = dict(payload['subs']) subs = dict(payload["subs"])
for key in ('designation', 'ingredients', 'description', 'color', 'AB'): for key in ("designation", "ingredients", "description", "color", "AB"):
subs[key] = payload[key] subs[key] = payload[key]
subs['ingredients'] = quirk_bold_allergens(subs['ingredients']) subs["ingredients"] = quirk_bold_allergens(subs["ingredients"])
pdfpath = stickersheet.generate(template=payload['template'], subs=subs, pdfpath = stickersheet.generate(
out_dir=settings.TIKETTE_OUT_DIR, template=payload["template"],
landscape=payload['landscape']) subs=subs,
out_dir=settings.TIKETTE_OUT_DIR,
landscape=payload["landscape"],
)
return ok({'file': pdfpath}) return ok({"file": pdfpath})
@auth_only @auth_only
@ -128,7 +144,7 @@ def deletetikette(request):
@post_please @post_please
def signin(request): def signin(request):
payload = json.loads(request.body) payload = json.loads(request.body)
token = payload['token'] token = payload["token"]
try: try:
user_data = id_token.verify_oauth2_token( user_data = id_token.verify_oauth2_token(
@ -136,13 +152,13 @@ def signin(request):
) )
except ValueError: except ValueError:
raise raise
return JsonResponse({'status': 'notok'}, status=403) return JsonResponse({"status": "notok"}, status=403)
request.session['user_data'] = user_data request.session["user_data"] = user_data
return ok(user_data) return ok(user_data)
def signout(request): def signout(request):
del request.session['user_data'] del request.session["user_data"]
return ok() return ok()

View File

@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zetikettes.settings') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zetikettes.settings")
application = get_asgi_application() application = get_asgi_application()

View File

@ -15,75 +15,75 @@ from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
#TIKETTE_OUT_DIR = BASE_DIR / 'data' # TIKETTE_OUT_DIR = BASE_DIR / 'data'
TIKETTE_OUT_DIR = Path('/data') TIKETTE_OUT_DIR = Path("/data")
MEDIA_ROOT = TIKETTE_OUT_DIR MEDIA_ROOT = TIKETTE_OUT_DIR
MEDIA_URL = '/data/' MEDIA_URL = "/data/"
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-64qxpe55#9wy=5@#dl0)3w7ywxh48m!f&!slp9e7v4lh@hjdct' SECRET_KEY = "django-insecure-64qxpe55#9wy=5@#dl0)3w7ywxh48m!f&!slp9e7v4lh@hjdct"
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False DEBUG = False
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ["*"]
CSRF_TRUSTED_ORIGINS = ['https://*.ponteilla.net'] CSRF_TRUSTED_ORIGINS = ["https://*.ponteilla.net"]
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'django.contrib.admin', "django.contrib.admin",
'django.contrib.auth', "django.contrib.auth",
'django.contrib.contenttypes', "django.contrib.contenttypes",
'django.contrib.sessions', "django.contrib.sessions",
'django.contrib.messages', "django.contrib.messages",
'django.contrib.staticfiles', "django.contrib.staticfiles",
'tikette', "tikette",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', "django.middleware.security.SecurityMiddleware",
'django.contrib.sessions.middleware.SessionMiddleware', "django.contrib.sessions.middleware.SessionMiddleware",
'django.middleware.common.CommonMiddleware', "django.middleware.common.CommonMiddleware",
'django.middleware.csrf.CsrfViewMiddleware', "django.middleware.csrf.CsrfViewMiddleware",
'django.contrib.auth.middleware.AuthenticationMiddleware', "django.contrib.auth.middleware.AuthenticationMiddleware",
'django.contrib.messages.middleware.MessageMiddleware', "django.contrib.messages.middleware.MessageMiddleware",
'django.middleware.clickjacking.XFrameOptionsMiddleware', "django.middleware.clickjacking.XFrameOptionsMiddleware",
'tikette.middleware.cors_everywhere', "tikette.middleware.cors_everywhere",
] ]
ROOT_URLCONF = 'zetikettes.urls' ROOT_URLCONF = "zetikettes.urls"
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', "BACKEND": "django.template.backends.django.DjangoTemplates",
'DIRS': [], "DIRS": [],
'APP_DIRS': True, "APP_DIRS": True,
'OPTIONS': { "OPTIONS": {
'context_processors': [ "context_processors": [
'django.template.context_processors.debug', "django.template.context_processors.debug",
'django.template.context_processors.request', "django.template.context_processors.request",
'django.contrib.auth.context_processors.auth', "django.contrib.auth.context_processors.auth",
'django.contrib.messages.context_processors.messages', "django.contrib.messages.context_processors.messages",
], ],
}, },
}, },
] ]
WSGI_APPLICATION = 'zetikettes.wsgi.application' WSGI_APPLICATION = "zetikettes.wsgi.application"
# Database # Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases # https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { "default": {
'ENGINE': 'django.db.backends.sqlite3', "ENGINE": "django.db.backends.sqlite3",
'NAME': TIKETTE_OUT_DIR / 'db.sqlite3', "NAME": TIKETTE_OUT_DIR / "db.sqlite3",
} }
} }
@ -93,16 +93,16 @@ DATABASES = {
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
}, },
{ {
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
}, },
] ]
@ -110,9 +110,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/ # https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = "en-us"
TIME_ZONE = 'UTC' TIME_ZONE = "UTC"
USE_I18N = True USE_I18N = True
@ -122,14 +122,16 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/ # https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = '/zetikettes/srv/static/' STATIC_URL = "/zetikettes/srv/static/"
STATIC_ROOT = 'www_static' STATIC_ROOT = "www_static"
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# not a secret # not a secret
GOOGLE_OAUTH_CLIENT_ID = '634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com' GOOGLE_OAUTH_CLIENT_ID = (
"634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com"
)

View File

@ -14,6 +14,7 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
@ -23,16 +24,16 @@ from django.views.generic.base import TemplateView
import tikette.views import tikette.views
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path("admin/", admin.site.urls),
path('list', tikette.views.get_list), path("list", tikette.views.get_list),
path('categories', tikette.views.get_categories), path("categories", tikette.views.get_categories),
path('generate', tikette.views.generate), path("generate", tikette.views.generate),
path('newtikette', tikette.views.newtikette), path("newtikette", tikette.views.newtikette),
path('deletetikette', tikette.views.deletetikette), path("deletetikette", tikette.views.deletetikette),
path('updatetikette', tikette.views.newtikette), # yes, we use newtikette path("updatetikette", tikette.views.newtikette), # yes, we use newtikette
path('signin', tikette.views.signin), path("signin", tikette.views.signin),
path('signout', tikette.views.signout), path("signout", tikette.views.signout),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
handler403 = 'tikette.views.handler403' handler403 = "tikette.views.handler403"
handler404 = 'tikette.views.handler404' handler404 = "tikette.views.handler404"

View File

@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zetikettes.settings') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zetikettes.settings")
application = get_wsgi_application() application = get_wsgi_application()

View File

@ -1,2 +1,2 @@
const backend_api = '/zetikettes/srv/' const backend_api = "/zetikettes/srv/"
const google_oauth_client_id = '634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com'; const google_oauth_client_id = '634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com';