Port to Django 5.2

This commit is contained in:
2025-10-05 18:05:08 +01:00
parent fa60c4421f
commit e8355dba90
31 changed files with 496 additions and 437 deletions

View File

@@ -26,21 +26,23 @@ DEBUG = env('DEBUG', cast=bool, default=True)
STAGING = env('STAGING', cast=bool, default=False)
CI = env('CI', cast=bool, default=False)
ALLOWED_HOSTS = ['pyrigs.nottinghamtec.co.uk', 'rigs.nottinghamtec.co.uk', 'pyrigs.herokuapp.com']
if STAGING:
ALLOWED_HOSTS.append('.herokuapp.com')
ALLOWED_HOSTS = ['https://pyrigs.nottinghamtec.co.uk', 'https://rigs.nottinghamtec.co.uk']
if DEBUG:
ALLOWED_HOSTS.append('localhost')
ALLOWED_HOSTS.append('example.com')
ALLOWED_HOSTS.append('127.0.0.1')
ALLOWED_HOSTS.append('.app.github.dev')
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
CRSF_TRUSTED_ORIGINS = ALLOWED_HOSTS.copy()
CRSF_TRUSTED_ORIGINS.append("http://localhost:8000")
CRSF_TRUSTED_ORIGINS.append("http://localhost:8001")
ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
if not DEBUG:
SECURE_SSL_REDIRECT = True # Redirect all http requests to https
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SESSION_COOKIE_SECURE = env('SESSION_COOKIE_SECURE_ENABLED', True)
CSRF_COOKIE_SECURE = env('CSRF_COOKIE_SECURE_ENABLED', True)
SECURE_HSTS_PRELOAD = True
INTERNAL_IPS = ['127.0.0.1']
@@ -257,6 +259,7 @@ TEMPLATES = [
"django.template.context_processors.tz",
"django.template.context_processors.request",
"django.contrib.messages.context_processors.messages",
"RIGS.views.is_ajax",
],
'debug': DEBUG
},
@@ -269,10 +272,3 @@ TERMS_OF_HIRE_URL = "http://www.nottinghamtec.co.uk/terms.pdf"
AUTHORISATION_NOTIFICATION_ADDRESS = 'productions@nottinghamtec.co.uk'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SESSION_COOKIE_SECURE = env('SESSION_COOKIE_SECURE_ENABLED', True)
CSRF_COOKIE_SECURE = env('CSRF_COOKIE_SECURE_ENABLED', True)
SECURE_HSTS_PRELOAD = True

View File

@@ -36,8 +36,8 @@ urlpatterns = [
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
import debug_toolbar
# import debug_toolbar
urlpatterns += [
path('__debug__/', include(debug_toolbar.urls)),
# path('__debug__/', include(debug_toolbar.urls)),
path('bootstrap/', TemplateView.as_view(template_name="bootstrap.html")),
]

View File

@@ -9,7 +9,7 @@ from functools import reduce
from itertools import chain
from io import BytesIO
from PyPDF2 import PdfFileMerger, PdfFileReader
from PyPDF2 import PdfMerger, PdfReader
from z3c.rml import rml2pdf
from django.conf import settings
@@ -32,7 +32,7 @@ from training import models as training_models
def is_ajax(request):
return request.headers.get('x-requested-with') == 'XMLHttpRequest'
return {"is_ajax": request.headers.get('x-requested-with') == 'XMLHttpRequest'}
def get_related(form, context): # Get some other objects to include in the form. Used when there are errors but also nice and quick.
@@ -333,10 +333,10 @@ def get_info_string(user):
def render_pdf_response(template, context, append_terms):
merger = PdfFileMerger()
merger = PdfMerger()
rml = template.render(context)
buffer = rml2pdf.parseString(rml)
merger.append(PdfFileReader(buffer))
merger.append(PdfReader(buffer))
buffer.close()
if append_terms:

View File

@@ -39,6 +39,8 @@ class EventForm(forms.ModelForm):
@property
def _get_items_json(self):
items = {}
if self.instance.pk is None:
return items
for item in self.instance.items.all():
data = serializers.serialize('json', [item])
struct = simplejson.loads(data)

View File

@@ -5,7 +5,7 @@ import urllib.request
from io import BytesIO
import datetime
from PyPDF2 import PdfFileReader, PdfFileMerger
from PyPDF2 import PdfReader, PdfMerger
from django.conf import settings
from django.contrib.staticfiles import finders
from django.core.cache import cache
@@ -31,12 +31,12 @@ def send_eventauthorisation_success_email(instance):
}
template = get_template('event_print.xml')
merger = PdfFileMerger()
merger = PdfMerger()
rml = template.render(context)
buffer = rml2pdf.parseString(rml)
merger.append(PdfFileReader(buffer))
merger.append(PdfReader(buffer))
buffer.close()
terms = urllib.request.urlopen(settings.TERMS_OF_HIRE_URL)

View File

@@ -1,5 +1,5 @@
Hi {{object.event.mic.get_full_name|default_if_none:"somebody"}},
Just to let you know your event N{{object.eventdisplay_id}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.event.last_edited_at}}.
Just to let you know your event N{{object.event.pk|stringformat:"05d"}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.event.last_edited_at}}.
The TEC Rig Information Gathering System

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% load markdown_tags %}
{% load static %}
@@ -18,7 +18,7 @@
{% block content %}
<div class="row my-3 py-3">
{% if not request.is_ajax %}
{% if not is_ajax %}
{% if perms.RIGS.view_event %}
<div class="col-sm-12 text-right">
{% include 'partials/event_detail_buttons.html' %}
@@ -49,7 +49,7 @@
</div>
{% endif %}
{% endif %}
{% if not request.is_ajax and perms.RIGS.view_event %}
{% if not is_ajax and perms.RIGS.view_event %}
<div class="col-sm-12 text-right">
{% include 'partials/event_detail_buttons.html' %}
</div>
@@ -69,16 +69,16 @@
</div>
</div>
</div>
{% include 'partials/crew_list.html' %}
{% if not request.is_ajax and perms.RIGS.view_event %}
{% if not is_ajax and perms.RIGS.view_event %}
<div class="col-sm-12 text-right">
{% include 'partials/event_detail_buttons.html' %}
</div>
{% endif %}
{% endif %}
{% if not request.is_ajax and perms.RIGS.view_event %}
{% if not is_ajax and perms.RIGS.view_event %}
<div class="col-sm-12 text-right">
{% include 'partials/last_edited.html' with target="event_history" %}
</div>
@@ -86,7 +86,7 @@
</div>
{% endblock %}
{% if request.is_ajax %}
{% if is_ajax %}
{% block footer %}
{% if perms.RIGS.view_event %}
{% include 'partials/last_edited.html' with target="event_history" %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% load static %}
{% load button from filters %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% block title %}TEC Email Address Required{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% load help_text from filters %}
{% load profile_by_index from filters %}
{% load yesnoi from filters %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% load static %}
{% load help_text from filters %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% load static %}
{% load button from filters %}
@@ -28,7 +28,7 @@
<form id="checkin" role="form" method="POST" action="{{ form.action|default:request.path }}">
<input type="hidden" name="{{ form.event.name }}" id="{{ form.event.id_for_label }}"
value="{{event.pk}}"/>
{% if not request.is_ajax and self.request.user.pk is form.event.mic.pk %}
{% if not is_ajax and self.request.user.pk is form.event.mic.pk %}
<div class="form-group">
<label for="{{ form.person.id_for_label }}"
class="col-sm-4 col-form-label">{{ form.person.label }}</label>
@@ -86,7 +86,7 @@
</div>
</div>
{% endif %}
{% if not request.is_ajax %}
{% if not is_ajax %}
<div class="row mt-3">
<div class="col-sm-12 text-right">
{% button 'submit' %}

View File

@@ -0,0 +1,59 @@
{% extends 'base_rigs.html' %}
{% load paginator from filters %}
{% load help_text from filters %}
{% load verbose_name from filters %}
{% load get_field from filters %}
{% block title %}{{ title }} List{% endblock %}
{% block content %}
<div class="row">
<div class="col-12">
<h2>{{title}} List</h2>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="table-responsive">
<table class="table mb-0 table-sm">
<thead>
<tr>
<th scope="col">Event</th>
{# mmm hax #}
{% if object_list.0 != None %}
{% for field in object_list.0.fieldz %}
<th scope="col">{{ object_list.0|verbose_name:field|title }}</th>
{% endfor %}
{% endif %}
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr class="{% if object.reviewed_by %}table-success{%endif%}">
{# General #}
<th scope="row"><a href="{% url 'event_detail' object.event.pk %}">{{ object.event }}</a><br><small>{{ object.event.get_status_display }}</small></th>
{% for field in object_list.0.fieldz %}
<td>{{ object|get_field:field }}</td>
{% endfor %}
{# Buttons #}
<td>
{% include 'partials/hs_status.html' %}
</td>
</tr>
{% empty %}
<tr class="bg-warning">
<td colspan="6">Nothing found</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% if is_paginated %}
<div class="row justify-content-center">
{% paginator %}
</div>
{% endif %}
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% load help_text from filters %}
{% load profile_by_index from filters %}
{% load yesnoi from filters %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% load static %}
{% load help_text from filters %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% load filters %}
{% block content %}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_rigs.html' %}
{% load widget_tweaks %}
{% load static %}
{% load help_text from filters %}

View File

@@ -1,7 +1,7 @@
<div class="row">
<label for="{{ formitem.id_for_label }}"
<label for="{{ formitem.0.id_for_label }}"
class="col-8 control-label">{{ formitem.help_text|safe }}</label>
<div class="col-4 pb-3" id="{{ formitem.id_for_label|slice:'-2' }}">
<div class="col-4 pb-3" id="{{ formitem.0.id_for_label|slice:'-2' }}">
{% for radio in formitem %}
<div class="custom-control custom-radio">
{{ radio.tag }}

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_assets.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_assets.html' %}
{% load widget_tweaks %}
{% block content %}
@@ -79,7 +79,7 @@
</div>
</div>
</div>
{% if not request.is_ajax %}
{% if not is_ajax %}
<div class="form-group form-row pull-right">
<button class="btn btn-success" type="submit" form="asset_audit_form" id="id_mark_audited">Mark Audited</button>
</div>

View File

@@ -16,7 +16,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import get_object_or_404
from django.template.loader import get_template
from PyPDF2 import PdfFileMerger, PdfFileReader
from PyPDF2 import PdfMerger, PdfReader
from PIL import Image, ImageDraw, ImageFont, ImageOps
from barcode import Code39
from barcode.writer import ImageWriter
@@ -417,11 +417,11 @@ class GenerateLabels(generic.View):
# 'images3': images[3::4],
'filename': name
}
merger = PdfFileMerger()
merger = PdfMerger()
rml = template.render(context)
buffer = rml2pdf.parseString(rml)
merger.append(PdfFileReader(buffer))
merger.append(PdfReader(buffer))
buffer.close()
merged = BytesIO()

View File

@@ -5,87 +5,79 @@ description = "A Django-based event booking system designed for use by TEC PA an
readme = "README.md"
requires-python = "~=3.10.0"
dependencies = [
"ansicolors~=1.1.8",
"asgiref~=3.3.1",
"backports.tempfile~=1.0",
"backports.weakref~=1.0.post1",
"beautifulsoup4~=4.9.3",
"Brotli~=1.0.9",
"cachetools~=4.2.1",
"chardet~=4.0.0",
"configparser~=5.0.1",
"contextlib2~=0.6.0.post1",
"cssselect~=1.1.0",
"cssutils~=1.0.2",
"dj-database-url~=0.5.0",
"dj-static~=0.0.6",
"Django~=3.2",
"django-debug-toolbar~=4.0.0",
"django-filter~=2.4.0",
"django-ical~=1.7.1",
"django-recurrence~=1.10.3",
"django-registration-redux~=2.9",
"django-reversion~=3.0.9",
"django-widget-tweaks~=1.4.8",
"django-htmlmin~=0.11.0",
"ansicolors",
"asgiref",
"beautifulsoup4",
"Brotli",
"cachetools",
"chardet",
"configparser",
"contextlib2",
"cssselect",
"cssutils",
"dj-database-url",
"dj-static",
"Django~=5.2",
"django-filter",
"django-ical",
"django-recurrence",
"django-registration-redux",
"django-reversion",
"django-widget-tweaks",
"django-htmlmin",
"envparse",
"gunicorn~=22.0.0",
"icalendar~=4.0.7",
"idna~=3.7",
"Markdown~=3.3.3",
"msgpack~=1.0.2",
"pep517~=0.9.1",
"Pillow~=10.0.1",
"premailer~=3.7.0",
"progress~=1.5",
"psutil~=5.8.0",
"gunicorn",
"icalendar",
"idna",
"Markdown",
"msgpack",
"pep517",
"Pillow",
"premailer",
"progress",
"psutil",
"psycopg2-binary",
"Pygments~=2.15.0",
"pyparsing~=2.4.7",
"PyPDF2~=1.27.5",
"PyPOM~=2.2.4",
"python-dateutil~=2.8.1",
"pytoml~=0.1.21",
"pytz~=2020.5",
"Pygments",
"pyparsing",
"PyPDF2",
"pytoml",
"pytz",
"reportlab",
"requests~=2.32.3",
"retrying~=1.3.3",
"simplejson~=3.17.2",
"six~=1.15.0",
"soupsieve~=2.1",
"sqlparse~=0.5.0",
"static3~=0.7.0",
"svg2rlg~=0.3",
"tini~=3.0.1",
"tornado~=6.3",
"urllib3~=1.26.19",
"whitenoise~=5.2.0",
"yolk~=0.4.3",
"zipp~=3.4.0",
"zope.component~=4.6.2",
"zope.deferredimport~=4.3.1",
"zope.deprecation~=4.4.0",
"zope.event~=4.5.0",
"zope.hookable~=5.0.1",
"zope.proxy~=4.3.5",
"zope.schema~=6.0.1",
"retrying",
"simplejson",
"soupsieve",
"sqlparse",
"static3",
"svg2rlg",
"tornado",
"urllib3",
"whitenoise",
"yolk",
"zipp",
"zope.component",
"zope.deferredimport",
"zope.deprecation",
"zope.event",
"zope.hookable",
"zope.proxy",
"zope.schema",
"sentry-sdk",
"diff-match-patch",
"python-barcode",
"django-hCaptcha",
"importlib-metadata",
"django-hcaptcha",
"z3c.rml",
"pikepdf",
"django-queryable-properties",
"django-mass-edit",
"selenium~=4.9.1",
"selenium",
"zope.interface",
]
[dependency-groups]
dev = [
"pycodestyle~=2.9.1",
"PyPOM",
"pycodestyle",
"coveralls",
"django-coverage-plugin",
"pytest-cov",

View File

@@ -76,7 +76,7 @@
{% endfor %}
{% endif %}
{% endblock %}
{% if page_title and not request.is_ajax %}
{% if page_title and not is_ajax %}
<h2>{{page_title|safe}}</h2>
{% endif %}
{% block content %}{% endblock %}

View File

@@ -46,7 +46,7 @@
{% include associated2|safe %}
{% endif %}
{% if not request.is_ajax %}
{% if not is_ajax %}
<div class="row py-2">
<div class="col-sm-12 text-right">
{% if can_edit %}
@@ -59,7 +59,7 @@
</div>
{% endif %}
{% endblock %}
{% if request.is_ajax %}
{% if is_ajax %}
{% block footer %}
<div class="row py-2">
<div class="col-sm-12 text-right">

View File

@@ -17,11 +17,11 @@
{% endif %}
{% for page in page_numbers %}
{% ifequal page page_obj.number %}
{% if page == page_obj.number %}
<li class="page-item active"><a class="page-link" href="#">{{ page }}</a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?{% url_replace request 'page' page %}" class="page">{{ page }}</a></li>
{% endifequal %}
{% endif %}
{% endfor %}
{% if show_last %}

View File

@@ -1,10 +1,10 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base.html" %}
{% block title %}Search Help{% endblock %}
{% block content %}
<div class="row">
{% if not request.is_ajax %}
{% if not is_ajax %}
<div class="col-sm-12">
<h1>Search Help</h1>
</div>

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_training.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_training.html' %}
{% load static %}
{% load widget_tweaks %}
@@ -37,7 +37,7 @@
<label for="depth" class="col-sm-2 col-form-label">Depth</label>
{% render_field form.depth|add_class:'form-control col-sm'|attr:'required' %}
</div>
{% if not request.is_ajax %}
{% if not is_ajax %}
<button type="submit" class="btn btn-primary">Save</button>
{% endif %}
</form>

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_training.html' %}
{% extends is_ajax|yesno:'base_ajax.html,base_training.html' %}
{% load static %}
{% load widget_tweaks %}
@@ -51,7 +51,7 @@
{% render_field form.notes|add_class:'form-control' rows=3 %}
</div>
</div>
{% if not request.is_ajax %}
{% if not is_ajax %}
<div class="col-sm-12 text-right pr-0">
{% button 'submit' %}
</div>

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
{% load static %}
{% load linkornone from filters %}
@@ -41,7 +41,7 @@
{% endblock %}
{% block content %}
{% if not request.is_ajax and object.pk == user.pk %}
{% if not is_ajax and object.pk == user.pk %}
<div class="row py-3">
<div class="col text-right">
<div class="btn-group">
@@ -85,7 +85,7 @@
</div>
</div>
</div>
{% if not request.is_ajax and object.pk == user.pk %}
{% if not is_ajax and object.pk == user.pk %}
<div class="col-lg-8 col-12">
<div class="card">
<div class="card-header">Personal iCal Details</div>

View File

@@ -3,8 +3,7 @@ from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy
from django.views import generic
from django.views.decorators.csrf import csrf_exempt
from RIGS import models
from django.conf import settings
# This view should be exempt from requiring CSRF token.
@@ -28,7 +27,7 @@ class LoginEmbed(LoginView):
class ProfileDetail(generic.DetailView):
template_name = "profile_detail.html"
model = models.Profile
model = settings.AUTH_USER_MODEL
def get_queryset(self):
try:
@@ -48,7 +47,7 @@ class ProfileDetail(generic.DetailView):
class ProfileUpdateSelf(generic.UpdateView):
template_name = "profile_form.html"
model = models.Profile
model = settings.AUTH_USER_MODEL
fields = ['first_name', 'last_name', 'email', 'initials', 'phone', 'dark_theme']
def get_queryset(self):

617
uv.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
{% extends request.is_ajax|yesno:"base_ajax_nomodal.html,base_rigs.html" %}
{% extends is_ajax|yesno:"base_ajax_nomodal.html,base_rigs.html" %}
{% load static %}
{% load humanize %}