Merge pull request #691 from ae-utbm/update-django

Update django (3.2 => 4.2)
This commit is contained in:
thomas girod 2024-07-04 12:40:23 +02:00 committed by GitHub
commit 47fec973bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 1229 additions and 1102 deletions

View File

@ -207,11 +207,11 @@ class Club(models.Model):
cache.set(f"sith_club_{self.unix_name}", self)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
# Invalidate the cache of this club and of its memberships
for membership in self.members.ongoing().select_related("user"):
cache.delete(f"membership_{self.id}_{membership.user.id}")
cache.delete(f"sith_club_{self.unix_name}")
super().delete(*args, **kwargs)
def __str__(self):
return self.name

View File

@ -46,6 +46,8 @@ class ClubTest(TestCase):
def setUpTestData(cls):
# subscribed users - initial members
cls.skia = User.objects.get(username="skia")
# by default, Skia is in the AE, which creates side effect
cls.skia.memberships.all().delete()
cls.richard = User.objects.get(username="rbatsbak")
cls.comptable = User.objects.get(username="comptable")
cls.sli = User.objects.get(username="sli")
@ -62,38 +64,32 @@ class ClubTest(TestCase):
cls.public = User.objects.get(username="public")
cls.ae = Club.objects.filter(pk=SITH_MAIN_CLUB_ID)[0]
def setUp(self):
# by default, Skia is in the AE, which creates side effect
self.skia.memberships.all().delete()
# create a fake club
self.club = Club.objects.create(
cls.club = Club.objects.create(
name="Fake Club",
unix_name="fake-club",
address="5 rue de la République, 90000 Belfort",
)
self.members_url = reverse(
"club:club_members", kwargs={"club_id": self.club.id}
)
cls.members_url = reverse("club:club_members", kwargs={"club_id": cls.club.id})
a_month_ago = now() - timedelta(days=30)
yesterday = now() - timedelta(days=1)
Membership.objects.create(
club=self.club, user=self.skia, start_date=a_month_ago, role=3
club=cls.club, user=cls.skia, start_date=a_month_ago, role=3
)
Membership.objects.create(club=self.club, user=self.richard, role=1)
Membership.objects.create(club=cls.club, user=cls.richard, role=1)
Membership.objects.create(
club=self.club, user=self.comptable, start_date=a_month_ago, role=10
club=cls.club, user=cls.comptable, start_date=a_month_ago, role=10
)
# sli was a member but isn't anymore
Membership.objects.create(
club=self.club,
user=self.sli,
club=cls.club,
user=cls.sli,
start_date=a_month_ago,
end_date=yesterday,
role=2,
)
def setUp(self):
cache.clear()
@ -176,14 +172,11 @@ class MembershipQuerySetTest(ClubTest):
# should delete the subscriptions of skia and comptable
self.club.members.ongoing().board().delete()
assert (
cache.get(f"membership_{mem_skia.club_id}_{mem_skia.user_id}")
== "not_member"
)
assert (
cache.get(f"membership_{mem_comptable.club_id}_{mem_comptable.user_id}")
== "not_member",
for membership in (mem_skia, mem_comptable):
cached_mem = cache.get(
f"membership_{membership.club_id}_{membership.user_id}"
)
assert cached_mem == "not_member"
class ClubModelTest(ClubTest):

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2 on 2024-06-26 09:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("core", "0037_auto_20211105_1708"),
]
operations = [
migrations.AlterField(
model_name="preferences",
name="receive_weekmail",
field=models.BooleanField(
default=False, verbose_name="receive the Weekmail"
),
),
]

View File

@ -162,8 +162,9 @@
<div>
{% trans %}Not subscribed{% endtrans %}
{% if user.is_board_member %}
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">{% trans %}New subscription{% endtrans
%}</a>
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">
{% trans %}New subscription{% endtrans %}
</a>
{% endif %}
{% endif %}
</div>

View File

@ -133,8 +133,9 @@
</p>
{%- elif user.is_root -%}
<p>
<a href="{{ url('core:password_root_change', user_id=form.instance.id) }}">{%- trans -%}Change user password{%-
endtrans -%}</a>
<a href="{{ url('core:password_root_change', user_id=form.instance.id) }}">
{%- trans -%}Change user password{%- endtrans -%}
</a>
</p>
{%- endif -%}

View File

@ -28,6 +28,7 @@ from django.conf import settings
from django.core.files.base import ContentFile
from django.utils import timezone
from PIL import ExifTags
from PIL.Image import Resampling
def get_git_revision_short_hash() -> str:
@ -109,7 +110,8 @@ def resize_image(im, edge, format):
(w, h) = im.size
(width, height) = scale_dimension(w, h, long_edge=edge)
content = BytesIO()
im = im.resize((width, height), PIL.Image.ANTIALIAS)
# use the lanczos filter for antialiasing
im = im.resize((width, height), Resampling.LANCZOS)
try:
im.save(
fp=content,

View File

@ -2,9 +2,9 @@
from __future__ import unicode_literals
import datetime
from datetime import timezone
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
@ -17,7 +17,9 @@ class Migration(migrations.Migration):
field=models.DateTimeField(
verbose_name="activity time",
auto_now=True,
default=datetime.datetime(2016, 8, 26, 17, 5, 31, 202824, tzinfo=utc),
default=datetime.datetime(
2016, 8, 26, 17, 5, 31, 202824, tzinfo=timezone.utc
),
),
preserve_default=False,
)

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2 on 2024-06-26 09:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("counter", "0020_auto_20221215_1709")]
operations = [
migrations.RenameField(
model_name="cashregistersummaryitem",
old_name="check",
new_name="is_check",
),
migrations.AlterField(
model_name="cashregistersummaryitem",
name="is_check",
field=models.BooleanField(
default=False,
help_text="True if this is a bank check, else False",
verbose_name="check",
),
),
]

View File

@ -19,8 +19,8 @@ import base64
import os
import random
import string
from datetime import date, datetime, timedelta
from typing import Optional, Tuple
from datetime import date, datetime, timedelta, timezone
from typing import Tuple
from dict2xml import dict2xml
from django.conf import settings
@ -534,7 +534,7 @@ class Counter(models.Model):
.order_by("-perm_sum")
)
def get_top_customers(self, since: Optional[date] = None) -> QuerySet:
def get_top_customers(self, since: datetime | date | None = None) -> QuerySet:
"""
Return a QuerySet querying the money spent by customers of this counter
since the specified date, ordered by descending amount of money spent.
@ -543,9 +543,13 @@ class Counter(models.Model):
- the full name (first name + last name) of the customer
- the nickname of the customer
- the amount of money spent by the customer
:param since: timestamp from which to perform the calculation
"""
if since is None:
since = get_start_of_semester()
if isinstance(since, date):
since = datetime(since.year, since.month, since.day, tzinfo=timezone.utc)
return (
self.sellings.filter(date__gte=since)
.annotate(
@ -568,19 +572,18 @@ class Counter(models.Model):
.order_by("-selling_sum")
)
def get_total_sales(self, since=None) -> CurrencyField:
def get_total_sales(self, since: datetime | date | None = None) -> CurrencyField:
"""
Compute and return the total turnover of this counter
since the date specified in parameter (by default, since the start of the current
semester)
:param since: timestamp from which to perform the calculation
:type since: datetime | date | None
:return: Total revenue earned at this counter
"""
if since is None:
since = get_start_of_semester()
if isinstance(since, date):
since = datetime.combine(since, datetime.min.time())
since = datetime(since.year, since.month, since.day, tzinfo=timezone.utc)
total = self.sellings.filter(date__gte=since).aggregate(
total=Sum(F("quantity") * F("unit_price"), output_field=CurrencyField())
)["total"]
@ -927,25 +930,25 @@ class CashRegisterSummary(models.Model):
if name[:5] == "check":
checks = self.items.filter(check=True).order_by("value").all()
if name == "ten_cents":
return self.items.filter(value=0.1, check=False).first()
return self.items.filter(value=0.1, is_check=False).first()
elif name == "twenty_cents":
return self.items.filter(value=0.2, check=False).first()
return self.items.filter(value=0.2, is_check=False).first()
elif name == "fifty_cents":
return self.items.filter(value=0.5, check=False).first()
return self.items.filter(value=0.5, is_check=False).first()
elif name == "one_euro":
return self.items.filter(value=1, check=False).first()
return self.items.filter(value=1, is_check=False).first()
elif name == "two_euros":
return self.items.filter(value=2, check=False).first()
return self.items.filter(value=2, is_check=False).first()
elif name == "five_euros":
return self.items.filter(value=5, check=False).first()
return self.items.filter(value=5, is_check=False).first()
elif name == "ten_euros":
return self.items.filter(value=10, check=False).first()
return self.items.filter(value=10, is_check=False).first()
elif name == "twenty_euros":
return self.items.filter(value=20, check=False).first()
return self.items.filter(value=20, is_check=False).first()
elif name == "fifty_euros":
return self.items.filter(value=50, check=False).first()
return self.items.filter(value=50, is_check=False).first()
elif name == "hundred_euros":
return self.items.filter(value=100, check=False).first()
return self.items.filter(value=100, is_check=False).first()
elif name == "check_1":
return checks[0] if 0 < len(checks) else None
elif name == "check_2":
@ -993,7 +996,11 @@ class CashRegisterSummaryItem(models.Model):
)
value = CurrencyField(_("value"))
quantity = models.IntegerField(_("quantity"), default=0)
check = models.BooleanField(_("check"), default=False)
is_check = models.BooleanField(
_("check"),
default=False,
help_text=_("True if this is a bank check, else False"),
)
class Meta:
verbose_name = _("cash register summary item")

View File

@ -1204,35 +1204,35 @@ class CashRegisterSummaryForm(forms.Form):
cash_summary=summary,
value=cd["check_1_value"],
quantity=cd["check_1_quantity"],
check=True,
is_check=True,
).save()
if cd["check_2_quantity"]:
CashRegisterSummaryItem(
cash_summary=summary,
value=cd["check_2_value"],
quantity=cd["check_2_quantity"],
check=True,
is_check=True,
).save()
if cd["check_3_quantity"]:
CashRegisterSummaryItem(
cash_summary=summary,
value=cd["check_3_value"],
quantity=cd["check_3_quantity"],
check=True,
is_check=True,
).save()
if cd["check_4_quantity"]:
CashRegisterSummaryItem(
cash_summary=summary,
value=cd["check_4_value"],
quantity=cd["check_4_quantity"],
check=True,
is_check=True,
).save()
if cd["check_5_quantity"]:
CashRegisterSummaryItem(
cash_summary=summary,
value=cd["check_5_value"],
quantity=cd["check_5_quantity"],
check=True,
is_check=True,
).save()
if summary.items.count() < 1:
summary.delete()

View File

@ -2,12 +2,12 @@
from __future__ import unicode_literals
import datetime
from datetime import timezone
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
@ -226,7 +226,9 @@ class Migration(migrations.Migration):
"last_read_date",
models.DateTimeField(
verbose_name="last read date",
default=datetime.datetime(1999, 1, 1, 0, 0, tzinfo=utc),
default=datetime.datetime(
1999, 1, 1, 0, 0, tzinfo=timezone.utc
),
),
),
(

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2 on 2024-06-26 09:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pedagogy", "0002_auto_20190827_2251"),
]
operations = [
migrations.AlterField(
model_name="uv",
name="language",
field=models.CharField(
choices=[
("FR", "French"),
("EN", "English"),
("DE", "German"),
("SP", "Spanish"),
],
default="FR",
max_length=10,
verbose_name="language",
),
),
]

29
poetry.lock generated
View File

@ -413,19 +413,19 @@ files = [
[[package]]
name = "django"
version = "3.2.25"
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
version = "4.2.13"
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
optional = false
python-versions = ">=3.6"
python-versions = ">=3.8"
files = [
{file = "Django-3.2.25-py3-none-any.whl", hash = "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38"},
{file = "Django-3.2.25.tar.gz", hash = "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777"},
{file = "Django-4.2.13-py3-none-any.whl", hash = "sha256:a17fcba2aad3fc7d46fdb23215095dbbd64e6174bf4589171e732b18b07e426a"},
{file = "Django-4.2.13.tar.gz", hash = "sha256:837e3cf1f6c31347a1396a3f6b65688f2b4bb4a11c580dcb628b5afe527b68a5"},
]
[package.dependencies]
asgiref = ">=3.3.2,<4"
pytz = "*"
sqlparse = ">=0.2.2"
asgiref = ">=3.6.0,<4"
sqlparse = ">=0.3.1"
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
[package.extras]
argon2 = ["argon2-cffi (>=19.1.0)"]
@ -1776,6 +1776,17 @@ files = [
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "tzdata"
version = "2024.1"
description = "Provider of IANA time zone data"
optional = false
python-versions = ">=2"
files = [
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
]
[[package]]
name = "urllib3"
version = "2.2.2"
@ -1842,4 +1853,4 @@ filelock = ">=3.4"
[metadata]
lock-version = "2.0"
python-versions = "^3.10,<3.12"
content-hash = "7f807b6216c032932ac20e2bdac462c7a2c4e8db328cdd3536281d6fbc009776"
content-hash = "b090426042093af41cfbbced92a1a47bf0834ce88865dc7f51d0b7b04fda99a7"

View File

@ -21,7 +21,7 @@ license = "GPL-3.0-only"
[tool.poetry.dependencies]
python = "^3.10,<3.12" # Version is held back by mistune
Django = "^3.2"
Django = "^4.2.13"
Pillow = "^9.2"
mistune = "^0.8.4"
django-jinja = "^2.10"

View File

@ -187,6 +187,7 @@ TEMPLATES = [
},
},
]
FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
HAYSTACK_CONNECTIONS = {
"default": {
@ -248,8 +249,6 @@ TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
@ -690,7 +689,6 @@ if DEBUG:
"sith.toolbar_debug.TemplatesPanel",
"debug_toolbar.panels.cache.CachePanel",
"debug_toolbar.panels.signals.SignalsPanel",
"debug_toolbar.panels.logging.LoggingPanel",
"debug_toolbar.panels.redirects.RedirectsPanel",
]
SASS_INCLUDE_FOLDERS = ["core/static/"]