Skip to content

Commit 45df021

Browse files
hamishwilleebsmth
andauthored
Migrate to Django v5.0.2 (#137)
* Add migration * Update Python to 5.0.2 * Add generated template info across * Ran format on settings.py * Fix up logout form * Fix typo in create Bookinstance * Fix up name of bookinstances to copies * Improve layout of layout form * move import libraries to right place * Update bootstrap used * Add unique constraints * Genre function ordering to match text * Improve the All Bookinstances rendering - not in doc so can do * Update requirements to latest * Update urls.py - fix up 4.2 URL to 5.0 --------- Co-authored-by: Brian Thomas Smith <[email protected]>
1 parent b7fa69b commit 45df021

File tree

10 files changed

+116
-40
lines changed

10 files changed

+116
-40
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Generated by Django 5.0.2 on 2024-02-23 01:19
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('catalog', '0025_auto_20220222_0623'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='book',
16+
name='author',
17+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, to='catalog.author'),
18+
),
19+
migrations.AlterField(
20+
model_name='genre',
21+
name='name',
22+
field=models.CharField(help_text='Enter a book genre (e.g. Science Fiction, French Poetry etc.)', max_length=200, unique=True),
23+
),
24+
migrations.AlterField(
25+
model_name='language',
26+
name='name',
27+
field=models.CharField(help_text="Enter the book's natural language (e.g. English, French, Japanese etc.)", max_length=200, unique=True),
28+
),
29+
]

catalog/models.py

+22-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
# Create your models here.
44

55
from django.urls import reverse # To generate URLS by reversing URL patterns
6-
6+
from django.db.models import UniqueConstraint
7+
from django.db.models.functions import Lower
78

89
class Genre(models.Model):
910
"""Model representing a book genre (e.g. Science Fiction, Non Fiction)."""
@@ -13,14 +14,22 @@ class Genre(models.Model):
1314
help_text="Enter a book genre (e.g. Science Fiction, French Poetry etc.)"
1415
)
1516

16-
def get_absolute_url(self):
17-
"""Returns the url to access a particular genre instance."""
18-
return reverse('genre-detail', args=[str(self.id)])
19-
2017
def __str__(self):
2118
"""String for representing the Model object (in Admin site etc.)"""
2219
return self.name
2320

21+
def get_absolute_url(self):
22+
"""Returns the url to access a particular genre instance."""
23+
return reverse('genre-detail', args=[str(self.id)])
24+
25+
class Meta:
26+
constraints = [
27+
UniqueConstraint(
28+
Lower('name'),
29+
name='genre_name_case_insensitive_unique',
30+
violation_error_message = "Genre already exists (case insensitive match)"
31+
),
32+
]
2433

2534
class Language(models.Model):
2635
"""Model representing a Language (e.g. English, French, Japanese, etc.)"""
@@ -36,6 +45,14 @@ def __str__(self):
3645
"""String for representing the Model object (in Admin site etc.)"""
3746
return self.name
3847

48+
class Meta:
49+
constraints = [
50+
UniqueConstraint(
51+
Lower('name'),
52+
name='language_name_case_insensitive_unique',
53+
violation_error_message = "Language already exists (case insensitive match)"
54+
),
55+
]
3956

4057
class Book(models.Model):
4158
"""Model representing a book (but not a specific copy of a book)."""

catalog/static/css/styles.css

+8
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@
44
list-style: none;
55
}
66

7+
#logout-form {
8+
display: inline;
9+
}
10+
#logout-form button {
11+
padding: 0;
12+
margin: 0;
13+
}
14+

catalog/templates/base_generic.html

+9-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
{% block title %}<title>Local Library</title>{% endblock %}
66
<meta charset="utf-8">
77
<meta name="viewport" content="width=device-width, initial-scale=1">
8-
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
9-
8+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
109
<!-- Add additional CSS in static file -->
1110
{% load static %}
1211
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
@@ -31,7 +30,12 @@
3130
{% if user.is_authenticated %}
3231
<li>User: {{ user.get_username }}</li>
3332
<li><a href="{% url 'my-borrowed' %}">My borrowed</a></li>
34-
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li>
33+
<li>
34+
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
35+
{% csrf_token %}
36+
<button type="submit" class="btn btn-link">Logout</button>
37+
</form>
38+
</li>
3539
{% else %}
3640
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li>
3741
{% endif %}
@@ -55,10 +59,10 @@
5559
<li><a href="{% url 'book-create' %}">Create book</a></li>
5660
{% endif %}
5761
{% if perms.catalog.add_bookinstance %}
58-
<li><a href="{% url 'bookinstance-create' %}">create BookInstance</a></li>
62+
<li><a href="{% url 'bookinstance-create' %}">Create copy of book</a></li>
5963
{% endif %}
6064
</ul>
61-
{% endif %}
65+
{% endif %}
6266

6367
{% endblock %}
6468
</div>

catalog/templates/catalog/bookinstance_list.html

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ <h1>Book Copies in Library</h1>
66
<ul>
77
{% for bookinst in bookinstance_list %}
88
<li class="{% if bookinst.is_overdue %}text-danger{% endif %}">
9-
<a href="{% url 'bookinstance-detail' bookinst.pk %}">{{bookinst.book.title}}</a> ({{ bookinst.due_back }}) {% if user.is_staff %}- {{ bookinst.borrower }}{% endif %} {% if perms.catalog.can_mark_returned %}- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a> {% endif %}
9+
<a href="{% url 'bookinstance-detail' bookinst.pk %}">{{bookinst.book.title}}</a> ({{ bookinst.get_status_display }})
10+
{% if bookinst.status != 'a' %}: {{ bookinst.due_back }} {% endif %}
11+
{% if bookinst.status == 'o' %}
12+
{% if user.is_staff %}- {{ bookinst.borrower }}{% endif %} {% if perms.catalog.can_mark_returned %}- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a> {% endif %}
13+
{% endif %}
1014
</li>
1115
{% empty %}
1216
<li>There are no book copies available.</li>

locallibrary/asgi.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for locallibrary project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'locallibrary.settings')
15+
16+
application = get_asgi_application()

locallibrary/settings.py

+19-21
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""
22
Django settings for locallibrary project.
33
4-
Generated by 'django-admin startproject' using Django 4.2.3.
4+
Generated by 'django-admin startproject' using Django 5.0.2.
55
66
For more information on this file, see
7-
https://docs.djangoproject.com/en/4.2/topics/settings/
7+
https://docs.djangoproject.com/en/5.0/topics/settings/
88
99
For the full list of settings and their values, see
10-
https://docs.djangoproject.com/en/4.2/ref/settings/
10+
https://docs.djangoproject.com/en/5.0/ref/settings/
1111
"""
1212

1313
from pathlib import Path
@@ -17,27 +17,29 @@
1717

1818

1919
# Add support for env variables from file if defined
20-
import os
2120
from dotenv import load_dotenv
21+
import os
2222
env_path = load_dotenv(os.path.join(BASE_DIR, '.env'))
2323
load_dotenv(env_path)
2424

2525
# Quick-start development settings - unsuitable for production
26-
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
26+
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
2727

2828
# SECURITY WARNING: keep the secret key used in production secret!
2929
# SECRET_KEY = 'django-insecure-&psk#na5l=p3q8_a+-$4w1f^lt3lx1c@d*p4x$ymm_rn7pwb87'
30-
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-&psk#na5l=p3q8_a+-$4w1f^lt3lx1c@d*p4x$ymm_rn7pwb87')
30+
SECRET_KEY = os.environ.get(
31+
'DJANGO_SECRET_KEY', 'django-insecure-&psk#na5l=p3q8_a+-$4w1f^lt3lx1c@d*p4x$ymm_rn7pwb87')
3132

3233
# SECURITY WARNING: don't run with debug turned on in production!
33-
#DEBUG = True
34-
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
34+
DEBUG = True
35+
# DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
3536

3637
# Set hosts to allow any app on Railway and the local testing URL
37-
ALLOWED_HOSTS = ['.railway.app','.pythonanywhere.com','127.0.0.1']
38+
ALLOWED_HOSTS = ['.railway.app', '.pythonanywhere.com', '127.0.0.1']
3839

3940
# Set CSRF trusted origins to allow any app on Railway and the local testing URL
40-
CSRF_TRUSTED_ORIGINS = ['https://*.railway.app','https://*.pythonanywhere.com']
41+
CSRF_TRUSTED_ORIGINS = ['https://*.railway.app',
42+
'https://*.pythonanywhere.com']
4143

4244

4345
# Application definition
@@ -50,7 +52,7 @@
5052
'django.contrib.messages',
5153
'django.contrib.staticfiles',
5254
# Add our new application
53-
'catalog.apps.CatalogConfig', #This object was created for us in /catalog/apps.py
55+
'catalog.apps.CatalogConfig', # This object was created for us in /catalog/apps.py
5456
]
5557

5658
MIDDLEWARE = [
@@ -86,7 +88,7 @@
8688

8789

8890
# Database
89-
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
91+
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
9092

9193
DATABASES = {
9294
'default': {
@@ -97,7 +99,7 @@
9799

98100

99101
# Password validation
100-
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
102+
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
101103

102104
AUTH_PASSWORD_VALIDATORS = [
103105
{
@@ -116,7 +118,7 @@
116118

117119

118120
# Internationalization
119-
# https://docs.djangoproject.com/en/4.2/topics/i18n/
121+
# https://docs.djangoproject.com/en/5.0/topics/i18n/
120122

121123
LANGUAGE_CODE = 'en-us'
122124

@@ -127,18 +129,14 @@
127129
USE_TZ = True
128130

129131

130-
131132
# Redirect to home URL after login (Default redirects to /accounts/profile/)
132133
LOGIN_REDIRECT_URL = '/'
133134

134135
# Add to test email:
135136
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
136137

137-
138-
139138
# Update database configuration from $DATABASE_URL environment variable (if defined)
140139
import dj_database_url
141-
142140
if 'DATABASE_URL' in os.environ:
143141
DATABASES['default'] = dj_database_url.config(
144142
conn_max_age=500,
@@ -147,9 +145,9 @@
147145

148146

149147
# Static files (CSS, JavaScript, Images)
150-
# https://docs.djangoproject.com/en/4.2/howto/static-files/
148+
# https://docs.djangoproject.com/en/5.0/howto/static-files/
151149
# The absolute path to the directory where collectstatic will collect static files for deployment.
152-
STATIC_ROOT = BASE_DIR / 'staticfiles' #. os.path.join(BASE_DIR, 'staticfiles')
150+
STATIC_ROOT = BASE_DIR / 'staticfiles'
153151
# The URL to use when referring to static files (where they will be served from)
154152
STATIC_URL = '/static/'
155153

@@ -164,6 +162,6 @@
164162
}
165163

166164
# Default primary key field type
167-
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
165+
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
168166

169167
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

locallibrary/urls.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
URL configuration for locallibrary project.
33
44
The `urlpatterns` list routes URLs to views. For more information please see:
5-
https://docs.djangoproject.com/en/4.2/topics/http/urls/
5+
https://docs.djangoproject.com/en/5.0/topics/http/urls/
66
Examples:
77
Function views
88
1. Add an import: from my_app import views
@@ -39,15 +39,15 @@
3939
urlpatterns+= static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
4040

4141

42-
#Add URL maps to redirect the base URL to our application
42+
# Add URL maps to redirect the base URL to our application
4343
from django.views.generic import RedirectView
4444
urlpatterns += [
4545
path('', RedirectView.as_view(url='/catalog/', permanent=True)),
4646
]
4747

4848

4949

50-
#Add Django site authentication urls (for login, logout, password management)
50+
# Add Django site authentication urls (for login, logout, password management)
5151
urlpatterns += [
5252
path('accounts/', include('django.contrib.auth.urls')),
5353
]

locallibrary/wsgi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
It exposes the WSGI callable as a module-level variable named ``application``.
55
66
For more information on this file, see
7-
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
7+
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
88
"""
99

1010
import os

requirements.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Django==4.2.11
2-
dj-database-url==2.0.0
1+
Django==5.0.2
2+
dj-database-url==2.1.0
33
gunicorn==21.2.0
4-
psycopg2-binary==2.9.6
4+
psycopg2-binary==2.9.9
55
wheel==0.38.1
6-
whitenoise==6.5.0
6+
whitenoise==6.6.0
77
python-dotenv==1.0.1

0 commit comments

Comments
 (0)