From f7f7ccaf09b65b66e0c995e6df53888288411770 Mon Sep 17 00:00:00 2001
From: Hamish Willee
Date: Wed, 28 Feb 2024 16:13:14 +1100
Subject: [PATCH] Django 5 update (From Django 4) (#32406)
* Add info about Django 5 update
* Global search-replace of django urls from 4 to 5
* Dev env complete
* Creating a skeleton website
* Add more changes to skeleton tute
* Models - update to mention constraints, as these are useful
* Bootstrap, logout form, fixes for url to django-githubrepo base
* Updates requirements and remainder of forms
---
.../server-side/django/admin_site/index.md | 22 +--
.../django/authentication/index.md | 103 ++++++++------
.../server-side/django/deployment/index.md | 39 ++---
.../django/development_environment/index.md | 33 +++--
.../django/django_assessment_blog/index.md | 2 +-
.../learn/server-side/django/forms/index.md | 134 +++++++++---------
.../server-side/django/generic_views/index.md | 46 +++---
.../server-side/django/home_page/index.md | 36 ++---
.../server-side/django/introduction/index.md | 2 +-
.../learn/server-side/django/models/index.md | 81 ++++++-----
.../server-side/django/sessions/index.md | 16 +--
.../django/skeleton_website/index.md | 102 +++++++------
.../learn/server-side/django/testing/index.md | 28 ++--
.../django/web_application_security/index.md | 18 +--
14 files changed, 357 insertions(+), 305 deletions(-)
diff --git a/files/en-us/learn/server-side/django/admin_site/index.md b/files/en-us/learn/server-side/django/admin_site/index.md
index 89b8e4af0ff7a82..3f2a95201ce3497 100644
--- a/files/en-us/learn/server-side/django/admin_site/index.md
+++ b/files/en-us/learn/server-side/django/admin_site/index.md
@@ -31,13 +31,13 @@ Now that we've created models for the [LocalLibrary](/en-US/docs/Learn/Server-si
The Django admin _application_ can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the _right_ data. The admin application can also be useful for managing data in production, depending on the type of website. The Django project recommends it only for internal data management (i.e. just for use by admins, or people internal to your organization), as the model-centric approach is not necessarily the best possible interface for all users, and exposes a lot of unnecessary detail about the models.
-All the configuration required to include the admin application in your website was done automatically when you [created the skeleton project](/en-US/docs/Learn/Server-side/Django/skeleton_website) (for information about actual dependencies needed, see the [Django docs here](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/)). As a result, all you **must** do to add your models to the admin application is to _register_ them. At the end of this article we'll provide a brief demonstration of how you might further configure the admin area to better display our model data.
+All the configuration required to include the admin application in your website was done automatically when you [created the skeleton project](/en-US/docs/Learn/Server-side/Django/skeleton_website) (for information about actual dependencies needed, see the [Django docs here](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/)). As a result, all you **must** do to add your models to the admin application is to _register_ them. At the end of this article we'll provide a brief demonstration of how you might further configure the admin area to better display our model data.
After registering the models we'll show how to create a new "superuser", login to the site, and create some books, authors, book instances, and genres. These will be useful for testing the views and templates we'll start creating in the next tutorial.
## Registering models
-First, open **admin.py** in the catalog application (**/locallibrary/catalog/admin.py**). It currently looks like this — note that it already imports `django.contrib.admin`:
+First, open **admin.py** in the catalog application (**/django-locallibrary-tutorial/catalog/admin.py**). It currently looks like this — note that it already imports `django.contrib.admin`:
```python
from django.contrib import admin
@@ -138,13 +138,13 @@ You can further customize the interface to make it even easier to use. Some of t
In this section we're going to look at a few changes that will improve the interface for our _LocalLibrary_, including adding more information to `Book` and `Author` model lists, and improving the layout of their edit views. We won't change the `Language` and `Genre` model presentation because they only have one field each, so there is no real benefit in doing so!
-You can find a complete reference of all the admin site customization choices in [The Django Admin site](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/) (Django Docs).
+You can find a complete reference of all the admin site customization choices in [The Django Admin site](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/) (Django Docs).
### Register a ModelAdmin class
-To change how a model is displayed in the admin interface you define a [ModelAdmin](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#modeladmin-objects) class (which describes the layout) and register it with the model.
+To change how a model is displayed in the admin interface you define a [ModelAdmin](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#modeladmin-objects) class (which describes the layout) and register it with the model.
-Let's start with the `Author` model. Open **admin.py** in the catalog application (**/locallibrary/catalog/admin.py**). Comment out your original registration (prefix it with a #) for the `Author` model:
+Let's start with the `Author` model. Open **admin.py** in the catalog application (**/django-locallibrary-tutorial/catalog/admin.py**). Comment out your original registration (prefix it with a #) for the `Author` model:
```python
# admin.site.register(Author)
@@ -186,7 +186,7 @@ Currently all of our admin classes are empty (see `pass`) so the admin behavior
### Configure list views
-The _LocalLibrary_ currently lists all authors using the object name generated from the model `__str__()` method. This is fine when you only have a few authors, but once you have many you may end up having duplicates. To differentiate them, or just because you want to show more interesting information about each author, you can use [list_display](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display) to add additional fields to the view.
+The _LocalLibrary_ currently lists all authors using the object name generated from the model `__str__()` method. This is fine when you only have a few authors, but once you have many you may end up having duplicates. To differentiate them, or just because you want to show more interesting information about each author, you can use [list_display](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display) to add additional fields to the view.
Replace your `AuthorAdmin` class with the code below. The field names to be displayed in the list are declared in a _tuple_ in the required order, as shown (these are the same names as specified in your original model).
@@ -270,7 +270,7 @@ In your website go to the author detail view — it should now appear as shown b
#### Sectioning the detail view
-You can add "sections" to group related model information within the detail form, using the [fieldsets](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets) attribute.
+You can add "sections" to group related model information within the detail form, using the [fieldsets](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets) attribute.
In the `BookInstance` model we have information related to what the book is (i.e. `name`, `imprint`, and `id`) and when it will be available (`status`, `due_back`). We can add these to our `BookInstanceAdmin` class as shown below, using the `fieldsets` property.
@@ -299,7 +299,7 @@ Now navigate to a book instance view in your website; the form should appear as
Sometimes it can make sense to be able to add associated records at the same time. For example, it may make sense to have both the book information and information about the specific copies you've got on the same detail page.
-You can do this by declaring [inlines](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.inlines), of type [TabularInline](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.TabularInline) (horizontal layout) or [StackedInline](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.StackedInline) (vertical layout, just like the default model layout). You can add the `BookInstance` information inline to our `Book` detail by specifying `inlines` in your `BookAdmin`:
+You can do this by declaring [inlines](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.inlines), of type [TabularInline](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.TabularInline) (horizontal layout) or [StackedInline](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.StackedInline) (vertical layout, just like the default model layout). You can add the `BookInstance` information inline to our `Book` detail by specifying `inlines` in your `BookAdmin`:
```python
class BooksInstanceInline(admin.TabularInline):
@@ -316,7 +316,7 @@ Now navigate to a view for a `Book` in your website — at the bottom you should
![Admin Site - Book with Inlines](admin_improved_book_detail_inlines.png)
-In this case all we've done is declare our tabular inline class, which just adds all fields from the _inlined_ model. You can specify all sorts of additional information for the layout, including the fields to display, their order, whether they are read only or not, etc. (see [TabularInline](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.TabularInline) for more information).
+In this case all we've done is declare our tabular inline class, which just adds all fields from the _inlined_ model. You can specify all sorts of additional information for the layout, including the fields to display, their order, whether they are read only or not, etc. (see [TabularInline](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/#django.contrib.admin.TabularInline) for more information).
> **Note:** There are some painful limits in this functionality! In the screenshot above we have three existing book instances, followed by three placeholders for new book instances (which look very similar!). It would be better to have NO spare book instances by default and just add them with the **Add another Book instance** link, or to be able to just list the `BookInstance`s as non-readable links from here. The first option can be done by setting the `extra` attribute to `0` in `BooksInstanceInline` model, try it by yourself.
@@ -333,7 +333,7 @@ That's it! You've now learned how to set up the administration site in both its
## Further reading
-- [Writing your first Django app, part 2: Introducing the Django Admin](https://docs.djangoproject.com/en/4.2/intro/tutorial02/#introducing-the-django-admin) (Django docs)
-- [The Django Admin site](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/) (Django Docs)
+- [Writing your first Django app, part 2: Introducing the Django Admin](https://docs.djangoproject.com/en/5.0/intro/tutorial02/#introducing-the-django-admin) (Django docs)
+- [The Django Admin site](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/) (Django Docs)
{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/authentication/index.md b/files/en-us/learn/server-side/django/authentication/index.md
index 052d4919d316a2b..aee01849ec571ef 100644
--- a/files/en-us/learn/server-side/django/authentication/index.md
+++ b/files/en-us/learn/server-side/django/authentication/index.md
@@ -43,7 +43,7 @@ The authentication was enabled automatically when we [created the skeleton websi
> **Note:** The necessary configuration was all done for us when we created the app using the `django-admin startproject` command. The database tables for users and model permissions were created when we first called `python manage.py migrate`.
-The configuration is set up in the `INSTALLED_APPS` and `MIDDLEWARE` sections of the project file (**locallibrary/locallibrary/settings.py**), as shown below:
+The configuration is set up in the `INSTALLED_APPS` and `MIDDLEWARE` sections of the project file (**django-locallibrary-tutorial/locallibrary/settings.py**), as shown below:
```python
INSTALLED_APPS = [
@@ -97,7 +97,7 @@ Our superuser is already authenticated and has all permissions, so we'll need to
> user.save()
> ```
>
-> For more information, see [Using a custom user model when starting a project](https://docs.djangoproject.com/en/4.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project) (Django docs).
+> For more information, see [Using a custom user model when starting a project](https://docs.djangoproject.com/en/5.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project) (Django docs).
Below we'll first create a group and then a user. Even though we don't have any permissions to add for our library members yet, if we need to later, it will be much easier to add them once to the group than individually to each member.
@@ -144,7 +144,7 @@ In this section, we show how to integrate the default system into the _LocalLibr
### Project URLs
-Add the following to the bottom of the project urls.py file (**locallibrary/locallibrary/urls.py**) file:
+Add the following to the bottom of the project urls.py file (**django-locallibrary-tutorial/locallibrary/urls.py**) file:
```python
# Add Django site authentication urls (for login, logout, password management)
@@ -155,10 +155,10 @@ urlpatterns += [
```
Navigate to the `http://127.0.0.1:8000/accounts/` URL (note the trailing forward slash!).
-Django will show an error that it could not find this URL, and list all the URLs it tried.
-From this you can see the URLs that will work, for example:
+Django will show an error that it could not find a mapping for this URL, and list all the URLs that it tried.
+From this you can see the URLs that will work once we have created templates.
-> **Note:** Using the above method adds the following URLs with names in square brackets, which can be used to reverse the URL mappings. You don't have to implement anything else — the above URL mapping automatically maps the below mentioned URLs.
+> **Note:** Adding the `accounts/` path as shown above adds the following URLs, along with names (given in square brackets) that can be used to reverse the URL mappings. You don't have to implement anything else — the above URL mapping automatically maps the below mentioned URLs.
>
> ```python
> accounts/ login/ [name='login']
@@ -179,7 +179,7 @@ Exception Type: TemplateDoesNotExist
Exception Value: registration/login.html
```
-The next step is to create a registration directory on the search path and then add the **login.html** file.
+The next step is to create a directory for the templates named "registration" and then add the **login.html** file.
### Template directory
@@ -190,7 +190,7 @@ For this site, we'll put our HTML pages in the **templates/registration/** direc
> **Note:** Your folder structure should now look like the below:
>
> ```plain
-> locallibrary/ # Django project folder
+> django-locallibrary-tutorial/ # Django top level project folder
> catalog/
> locallibrary/
> templates/
@@ -198,9 +198,9 @@ For this site, we'll put our HTML pages in the **templates/registration/** direc
> ```
To make the **templates** directory visible to the template loader we need to add it in the template search path.
-Open the project settings (**/locallibrary/locallibrary/settings.py**).
+Open the project settings (**/django-locallibrary-tutorial/locallibrary/settings.py**).
-Then import the `os` module (add the following line near the top of the file).
+Then import the `os` module (add the following line near the top of the file if it isn't already present).
```python
import os # needed by code below
@@ -222,7 +222,7 @@ Update the `TEMPLATES` section's `'DIRS'` line as shown:
> **Warning:** The authentication templates provided in this article are a very basic/slightly modified version of the Django demonstration login templates. You may need to customize them for your own use!
-Create a new HTML file called /**locallibrary/templates/registration/login.html** and give it the following contents:
+Create a new HTML file called /**django-locallibrary-tutorial/templates/registration/login.html** and give it the following contents:
```django
{% extends "base_generic.html" %}
@@ -272,7 +272,7 @@ Navigate back to the login page (`http://127.0.0.1:8000/accounts/login/`) once y
If you log in using valid credentials, you'll be redirected to another page (by default this will be `http://127.0.0.1:8000/accounts/profile/`). The problem is that, by default, Django expects that upon logging in you will want to be taken to a profile page, which may or may not be the case. As you haven't defined this page yet, you'll get another error!
-Open the project settings (**/locallibrary/locallibrary/settings.py**) and add the text below to the bottom. Now when you log in you should be redirected to the site homepage by default.
+Open the project settings (**/django-locallibrary-tutorial/locallibrary/settings.py**) and add the text below to the bottom. Now when you log in you should be redirected to the site homepage by default.
```python
# Redirect to home URL after login (Default redirects to /accounts/profile/)
@@ -281,9 +281,10 @@ LOGIN_REDIRECT_URL = '/'
### Logout template
-If you navigate to the logout URL (`http://127.0.0.1:8000/accounts/logout/`) then you'll see some odd behavior — your user will be logged out sure enough, but you'll be taken to the **Admin** logout page. That's not what you want, if only because the login link on that page takes you to the Admin login screen (and that is only available to users who have the `is_staff` permission).
+If you navigate to the logout URL (`http://127.0.0.1:8000/accounts/logout/`) then you'll get an error because Django 5 does not allow logout using `GET`, only `POST`.
+We'll add a form you can use to logout in a minute, but first we'll create the page that users are taken to after logging out.
-Create and open **/locallibrary/templates/registration/logged_out.html**. Copy in the text below:
+Create and open **/django-locallibrary-tutorial/templates/registration/logged_out.html**. Copy in the text below:
```django
{% extends "base_generic.html" %}
@@ -294,7 +295,7 @@ Create and open **/locallibrary/templates/registration/logged_out.html**. Copy i
{% endblock %}
```
-This template is very simple. It just displays a message informing you that you have been logged out, and provides a link that you can press to go back to the login screen. If you go to the logout URL again you should see this page:
+This template is very simple. It just displays a message informing you that you have been logged out, and provides a link that you can press to go back to the login screen. The screen renders like this (after logout):
![Library logout page v1](library_logout.png)
@@ -306,7 +307,7 @@ The following templates can be used as a starting point.
#### Password reset form
-This is the form used to get the user's email address (for sending the password reset email). Create **/locallibrary/templates/registration/password_reset_form.html**, and give it the following contents:
+This is the form used to get the user's email address (for sending the password reset email). Create **/django-locallibrary-tutorial/templates/registration/password_reset_form.html**, and give it the following contents:
```django
{% extends "base_generic.html" %}
@@ -325,7 +326,7 @@ This is the form used to get the user's email address (for sending the password
#### Password reset done
-This form is displayed after your email address has been collected. Create **/locallibrary/templates/registration/password_reset_done.html**, and give it the following contents:
+This form is displayed after your email address has been collected. Create **/django-locallibrary-tutorial/templates/registration/password_reset_done.html**, and give it the following contents:
```django
{% extends "base_generic.html" %}
@@ -337,7 +338,7 @@ This form is displayed after your email address has been collected. Create **/lo
#### Password reset email
-This template provides the text of the HTML email containing the reset link that we will send to users. Create **/locallibrary/templates/registration/password_reset_email.html**, and give it the following contents:
+This template provides the text of the HTML email containing the reset link that we will send to users. Create **/django-locallibrary-tutorial/templates/registration/password_reset_email.html**, and give it the following contents:
```django
Someone asked for password reset for email \{{ email }}. Follow the link below:
@@ -346,7 +347,7 @@ Someone asked for password reset for email \{{ email }}. Follow the link below:
#### Password reset confirm
-This page is where you enter your new password after clicking the link in the password reset email. Create **/locallibrary/templates/registration/password_reset_confirm.html**, and give it the following contents:
+This page is where you enter your new password after clicking the link in the password reset email. Create **/django-locallibrary-tutorial/templates/registration/password_reset_confirm.html**, and give it the following contents:
```django
{% extends "base_generic.html" %}
@@ -382,7 +383,7 @@ This page is where you enter your new password after clicking the link in the pa
#### Password reset complete
-This is the last password-reset template, which is displayed to notify you when the password reset has succeeded. Create **/locallibrary/templates/registration/password_reset_complete.html**, and give it the following contents:
+This is the last password-reset template, which is displayed to notify you when the password reset has succeeded. Create **/django-locallibrary-tutorial/templates/registration/password_reset_complete.html**, and give it the following contents:
```django
{% extends "base_generic.html" %}
@@ -395,22 +396,20 @@ This is the last password-reset template, which is displayed to notify you when
### Testing the new authentication pages
-Now that you've added the URL configuration and created all these templates, the authentication pages should now just work!
-
-You can test the new authentication pages by attempting to log in to and then log out of your superuser account using these URLs:
-
-- `http://127.0.0.1:8000/accounts/login/`
-- `http://127.0.0.1:8000/accounts/logout/`
+Now that you've added the URL configuration and created all these templates, the authentication pages (other than logout) should now just work!
+You can test the new authentication pages by first attempting to log in to your superuser account using the URL `http://127.0.0.1:8000/accounts/login/`.
You'll be able to test the password reset functionality from the link in the login page. **Be aware that Django will only send reset emails to addresses (users) that are already stored in its database!**
+Note that you won't be able to test account logout yet, because logout requests must be sent as a `POST` rather than a `GET` request.
+
> **Note:** The password reset system requires that your website supports email, which is beyond the scope of this article, so this part **won't work yet**. To allow testing, put the following line at the end of your settings.py file. This logs any emails sent to the console (so you can copy the password reset link from the console).
>
> ```python
> EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
> ```
>
-> For more information, see [Sending email](https://docs.djangoproject.com/en/4.2/topics/email/) (Django docs).
+> For more information, see [Sending email](https://docs.djangoproject.com/en/5.0/topics/email/) (Django docs).
## Testing against authenticated users
@@ -422,27 +421,46 @@ You can get information about the currently logged in user in templates with the
Typically you will first test against the `\{{ user.is_authenticated }}` template variable to determine whether the user is eligible to see specific content. To demonstrate this, next we'll update our sidebar to display a "Login" link if the user is logged out, and a "Logout" link if they are logged in.
-Open the base template (**/locallibrary/catalog/templates/base_generic.html**) and copy the following text into the `sidebar` block, immediately before the `endblock` template tag.
+Open the base template (**/django-locallibrary-tutorial/catalog/templates/base_generic.html**) and copy the following text into the `sidebar` block, immediately before the `endblock` template tag.
```django
```
As you can see, we use `if` / `else` / `endif` template tags to conditionally display text based on whether `\{{ user.is_authenticated }}` is true. If the user is authenticated then we know that we have a valid user, so we call `\{{ user.get_username }}` to display their name.
-We create the login and logout link URLs using the `url` template tag and the names of the respective URL configurations. Note also how we have appended `?next=\{{ request.path }}` to the end of the URLs. What this does is add a URL parameter `next` containing the address (URL) of the _current_ page, to the end of the linked URL. After the user has successfully logged in/out, the views will use this "`next`" value to redirect the user back to the page where they first clicked the login/logout link.
+We create the login link URL using the `url` template tag and the name of the `login` URL configuration. Note also how we have appended `?next=\{{ request.path }}` to the end of the URL. What this does is add a URL parameter `next` containing the address (URL) of the _current_ page, to the end of the linked URL. After the user has successfully logged in, the view will use this "`next`" value to redirect the user back to the page where they first clicked the login link.
+
+The logout template code is different, because from Django 5 to logout you must `POST` to the `admin:logout` URL, using a form with a button.
+By default this would render as a button, but you can style the button to display as a link.
+For this example we're using _Bootstrap_, so we make the button look like a link by applying `class="btn btn-link"`.
+YOu also also need to append the following styles to **/django-locallibrary-tutorial/catalog/static/css/styles.css** in order to correctly position the logout link next to all the other sidebar links:
+
+```css
+#logout-form {
+ display: inline;
+}
+#logout-form button {
+ padding: 0;
+ margin: 0;
+}
+```
-> **Note:** Try it out! If you're on the home page and you click Login/Logout in the sidebar, then after the operation completes you should end up back on the same page.
+Try it out by clicking the Login/Logout links in the sidebar.
### Testing in views
@@ -475,7 +493,7 @@ class MyView(LoginRequiredMixin, View):
redirect_field_name = 'redirect_to'
```
-For additional detail, check out the [Django docs here](https://docs.djangoproject.com/en/4.2/topics/auth/default/#limiting-access-to-logged-in-users).
+For additional detail, check out the [Django docs here](https://docs.djangoproject.com/en/5.0/topics/auth/default/#limiting-access-to-logged-in-users).
## Example — listing the current user's books
@@ -494,7 +512,7 @@ from django.conf import settings
```
Next, add the `borrower` field to the `BookInstance` model, setting the user model for the key as the value of the setting `AUTH_USER_MODEL`.
-Since we have not overridden the setting with a [custom user model](https://docs.djangoproject.com/en/4.2/topics/auth/customizing/) this maps to the default `User` model from `django.contrib.auth.models`.
+Since we have not overridden the setting with a [custom user model](https://docs.djangoproject.com/en/5.0/topics/auth/customizing/) this maps to the default `User` model from `django.contrib.auth.models`.
```python
borrower = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
@@ -638,7 +656,7 @@ When the development server is running, you should now be able to view the list
The very last step is to add a link for this new page into the sidebar. We'll put this in the same section where we display other information for the logged in user.
-Open the base template (**/locallibrary/catalog/templates/base_generic.html**) and add the "My Borrowed" line to the sidebar in the position shown below.
+Open the base template (**/django-locallibrary-tutorial/catalog/templates/base_generic.html**) and add the "My Borrowed" line to the sidebar in the position shown below.
```django
@@ -647,7 +665,12 @@ Open the base template (**/locallibrary/catalog/templates/base_generic.html**) a
{% endif %}
@@ -764,8 +787,8 @@ In our next article, we'll look at how you can use Django forms to collect user
## See also
-- [User authentication in Django](https://docs.djangoproject.com/en/4.2/topics/auth/) (Django docs)
-- [Using the (default) Django authentication system](https://docs.djangoproject.com/en/4.2/topics/auth/default/) (Django docs)
-- [Introduction to class-based views > Decorating class-based views](https://docs.djangoproject.com/en/4.2/topics/class-based-views/intro/#decorating-class-based-views) (Django docs)
+- [User authentication in Django](https://docs.djangoproject.com/en/5.0/topics/auth/) (Django docs)
+- [Using the (default) Django authentication system](https://docs.djangoproject.com/en/5.0/topics/auth/default/) (Django docs)
+- [Introduction to class-based views > Decorating class-based views](https://docs.djangoproject.com/en/5.0/topics/class-based-views/intro/#decorating-class-based-views) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/deployment/index.md b/files/en-us/learn/server-side/django/deployment/index.md
index a1f19234f98c54e..23d4549d242bade 100644
--- a/files/en-us/learn/server-side/django/deployment/index.md
+++ b/files/en-us/learn/server-side/django/deployment/index.md
@@ -140,7 +140,7 @@ You can set the environment variable to "False" on Linux by issuing the followin
export DJANGO_DEBUG=False
```
-A full checklist of settings you might want to change is provided in [Deployment checklist](https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/) (Django docs). You can also list a number of these using the terminal command below:
+A full checklist of settings you might want to change is provided in [Deployment checklist](https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/) (Django docs). You can also list a number of these using the terminal command below:
```python
python3 manage.py check --deploy
@@ -202,7 +202,7 @@ The value `conn_max_age=500` makes the connection persistent, which is far more
##### psycopg2
-
@@ -253,7 +253,7 @@ While it will cause no harm, you might as well delete the duplicate previous ref
```python
# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/4.2/howto/static-files/
+# https://docs.djangoproject.com/en/5.0/howto/static-files/
# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = BASE_DIR / 'staticfiles'
@@ -328,12 +328,13 @@ After installing all the different dependencies above, your **requirements.txt**
Please delete any other dependencies not listed below, unless you've explicitly added them for this application.
```plain
-Django==4.2.3
-dj-database-url==2.0.0
-gunicorn==21.2.3
-psycopg2-binary==2.9.6
+Django==5.0.2
+dj-database-url==2.1.0
+gunicorn==21.2.0
+psycopg2-binary==2.9.9
wheel==0.38.1
-whitenoise==6.5.0
+whitenoise==6.6.0
+python-dotenv==1.0.1
```
### Update your application repository in GitHub
@@ -578,7 +579,7 @@ This is a Django security error that is raised because our source code is not ru
> **Note:** This kind of debug information is very useful when you're getting set up, but is a security risk in a deployed site.
> In the next section we'll show you how to disable this level of logging on the live site using [environment variables](#using_environment_variables_on_pythonanywhere).
-Open **/locallibrary/settings.py** in your GitHub project and change the [ALLOWED_HOSTS](https://docs.djangoproject.com/en/4.2/ref/settings/#allowed-hosts) setting to include your PythonAnywhere site URL:
+Open **/locallibrary/settings.py** in your GitHub project and change the [ALLOWED_HOSTS](https://docs.djangoproject.com/en/5.0/ref/settings/#allowed-hosts) setting to include your PythonAnywhere site URL:
```python
## For example, for a site URL at 'hamishwillee.pythonanywhere.com'
@@ -590,7 +591,7 @@ ALLOWED_HOSTS = ['hamishwillee.pythonanywhere.com', '127.0.0.1']
# ALLOWED_HOSTS = ['.pythonanywhere.com','127.0.0.1']
```
-Since the applications uses CSRF protection, you will also need to set the [CSRF_TRUSTED_ORIGINS](https://docs.djangoproject.com/en/4.2/ref/settings/#csrf-trusted-origins) key.
+Since the applications uses CSRF protection, you will also need to set the [CSRF_TRUSTED_ORIGINS](https://docs.djangoproject.com/en/5.0/ref/settings/#csrf-trusted-origins) key.
Open **/locallibrary/settings.py** and add a line like the one below:
```python
@@ -838,7 +839,7 @@ This is a Django security error that is raised because our source code is not ru
> **Note:** This kind of debug information is very useful when you're getting set up, but is a security risk in a deployed site.
> We'll show you how to disable it once the site is up and running.
-Open **/locallibrary/settings.py** in your GitHub project and change the [ALLOWED_HOSTS](https://docs.djangoproject.com/en/4.2/ref/settings/#allowed-hosts) setting to include your Railway site URL:
+Open **/locallibrary/settings.py** in your GitHub project and change the [ALLOWED_HOSTS](https://docs.djangoproject.com/en/5.0/ref/settings/#allowed-hosts) setting to include your Railway site URL:
```python
## For example, for a site URL at 'web-production-3640.up.railway.app'
@@ -850,7 +851,7 @@ ALLOWED_HOSTS = ['web-production-3640.up.railway.app', '127.0.0.1']
# ALLOWED_HOSTS = ['.railway.com','127.0.0.1']
```
-Since the applications uses CSRF protection, you will also need to set the [CSRF_TRUSTED_ORIGINS](https://docs.djangoproject.com/en/4.2/ref/settings/#csrf-trusted-origins) key.
+Since the applications uses CSRF protection, you will also need to set the [CSRF_TRUSTED_ORIGINS](https://docs.djangoproject.com/en/5.0/ref/settings/#csrf-trusted-origins) key.
Open **/locallibrary/settings.py** and add a line like the one below:
```python
@@ -984,7 +985,7 @@ The Railway client provides the logs command to show the tail of logs (a more fu
railway logs
```
-If you need more information than this can provide you will need to start looking into [Django Logging](https://docs.djangoproject.com/en/4.2/topics/logging/).
+If you need more information than this can provide you will need to start looking into [Django Logging](https://docs.djangoproject.com/en/5.0/topics/logging/).
## Summary
@@ -994,13 +995,13 @@ The next step is to read our last few articles, and then complete the assessment
## See also
-- [Deploying Django](https://docs.djangoproject.com/en/4.2/howto/deployment/) (Django docs)
+- [Deploying Django](https://docs.djangoproject.com/en/5.0/howto/deployment/) (Django docs)
- - [Deployment checklist](https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/) (Django docs)
- - [Deploying static files](https://docs.djangoproject.com/en/4.2/howto/static-files/deployment/) (Django docs)
- - [How to deploy with WSGI](https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/) (Django docs)
- - [How to use Django with Apache and mod_wsgi](https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/modwsgi/) (Django docs)
- - [How to use Django with Gunicorn](https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/gunicorn/) (Django docs)
+ - [Deployment checklist](https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/) (Django docs)
+ - [Deploying static files](https://docs.djangoproject.com/en/5.0/howto/static-files/deployment/) (Django docs)
+ - [How to deploy with WSGI](https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/) (Django docs)
+ - [How to use Django with Apache and mod_wsgi](https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/modwsgi/) (Django docs)
+ - [How to use Django with Gunicorn](https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/gunicorn/) (Django docs)
- Railway Docs
diff --git a/files/en-us/learn/server-side/django/development_environment/index.md b/files/en-us/learn/server-side/django/development_environment/index.md
index 0d047c5dc0a1b3c..360ee39a5f499e5 100644
--- a/files/en-us/learn/server-side/django/development_environment/index.md
+++ b/files/en-us/learn/server-side/django/development_environment/index.md
@@ -35,7 +35,7 @@ The development environment is an installation of Django on your local computer
The main tools that Django itself provides are a set of Python scripts for creating and working with Django projects, along with a simple _development web server_ that you can use to test local (i.e. on your computer, not on an external web server) Django web applications on your computer's web browser.
-There are other peripheral tools, which form part of the development environment, that we won't be covering here. These include things like a [text editor](/en-US/docs/Learn/Common_questions/Tools_and_setup/Available_text_editors) or IDE for editing code, and a source control management tool like [Git](https://git-scm.com/) for safely managing different versions of your code. We are assuming that you've already got a text editor installed.
+There are other peripheral tools, that often form part of the development environment, that we won't be covering here. These include things like a [text editor](/en-US/docs/Learn/Common_questions/Tools_and_setup/Available_text_editors) or IDE for editing code, linters for auto formatting, and so on. We are assuming that you've already got a text editor installed.
### What are the Django setup options?
@@ -60,9 +60,9 @@ In this article, we'll provide instructions for Windows, macOS, and Linux/Unix.
#### What version of Python should be used?
You can use any Python version supported by your target Django release.
-For Django 4.2 the allowed versions are Python 3.8 to 3.11 (see [FAQ:Installation](https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django)).
+For Django 5.0 the allowed versions are Python 3.10 to 3.12 (see [FAQ:Installation](https://docs.djangoproject.com/en/5.0/faq/install/#what-python-version-can-i-use-with-django)).
-The Django project _recommends_ (and "officially supports") using the newest available supported Python release.
+The Django project _recommends_ (and "officially supports") using the newest available version of the supported Python release.
#### Where can we download Django?
@@ -76,7 +76,7 @@ This article shows how to install Django from PyPi, in order to get the latest s
#### Which database?
-Django officially supports the PostgreSQL, MariaDB, MySQL, Oracle, and SQLite databases, and there are community libraries that provide varying levels of support for other popular SQL and NoSQL databases. We recommend that you select the same database for both production and development (although Django abstracts many of the database differences using its Object-Relational Mapper (ORM), there are still [potential issues](https://docs.djangoproject.com/en/4.2/ref/databases/) that are better to avoid).
+Django officially supports the PostgreSQL, MariaDB, MySQL, Oracle, and SQLite databases, and there are community libraries that provide varying levels of support for other popular SQL and NoSQL databases. We recommend that you select the same database for both production and development (although Django abstracts many of the database differences using its Object-Relational Mapper (ORM), there are still [potential issues](https://docs.djangoproject.com/en/5.0/ref/databases/) that are better to avoid).
For this article (and most of this module) we will be using the _SQLite_ database, which stores its data in a file. SQLite is intended for use as a lightweight database and can't support a high level of concurrency. It is, however, an excellent choice for applications that are primarily read-only.
@@ -103,14 +103,14 @@ This section briefly explains how you can check what versions of Python are pres
> **Note:** Depending on your platform, you may also be able to install Python/pip from the operating system's own package manager or via other mechanisms. For most platforms, you can download the required installation files from and install them using the appropriate platform-specific method.
-### Ubuntu 20.04
+### Ubuntu 22.04
-Ubuntu Linux 20.04 LTS includes Python 3.8.10 by default.
+Ubuntu Linux 22.04 LTS includes Python 3.10.12 by default.
You can confirm this by running the following command in the bash terminal:
```bash
python3 -V
-# Output: Python 3.8.10
+# Output: Python 3.10.12
```
However, the Python Package Index tool (_pip3_) you'll need to install packages for Python 3 (including Django) is **not** available by default.
@@ -120,9 +120,8 @@ You can install _pip3_ in the bash terminal using:
sudo apt install python3-pip
```
-> **Note:** Python 3.8 is the oldest version [supported by Django 4.2](https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django).
-> While Django recommend you update to the latest version, you don't _need_ to use the latest version for this tutorial.
-> If you want to update Python, then there are instructions on the internet.
+> **Note:** Python 3.10 is the oldest version [supported by Django 5.0](https://docs.djangoproject.com/en/5.0/faq/install/#what-python-version-can-i-use-with-django).
+> You don't _need_ to use the latest version of Python for this tutorial, but if you want to there are instructions on the internet.
### macOS
@@ -140,8 +139,8 @@ You can easily install Python 3 (along with the _pip3_ tool) from [python.org](h
1. Download the required installer:
1. Go to
- 2. Download the most recent [supported version](https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django) that works with Django 4.2.
- (at time of writing this is Python 3.11.4).
+ 2. Download the stable release of the most recent [supported version](https://docs.djangoproject.com/en/5.0/faq/install/#what-python-version-can-i-use-with-django) that works with Django 5.0.
+ (at time of writing this is Python 3.11.8).
2. Locate the file using _Finder_, and double-click the package file. Following the installation prompts.
@@ -160,8 +159,8 @@ Windows doesn't include Python by default, but you can easily install it (along
1. Download the required installer:
1. Go to
- 2. Download the most recent [supported version](https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django) that works with Django 4.2.
- (at time of writing this is Python 3.11.4).
+ 2. Download the stable release of the most recent [supported version](https://docs.djangoproject.com/en/5.0/faq/install/#what-python-version-can-i-use-with-django) that works with Django 5.0.
+ (at time of writing this is Python 3.11.8).
2. Install Python by double-clicking on the downloaded file and following the installation prompts
3. Be sure to check the box labeled "Add Python to PATH"
@@ -595,8 +594,8 @@ In the testing section you also briefly saw how we can create a new Django websi
## See also
-- [Quick Install Guide](https://docs.djangoproject.com/en/4.2/intro/install/) (Django docs)
-- [How to install Django — Complete guide](https://docs.djangoproject.com/en/4.2/topics/install/) (Django docs) — also covers how to remove Django
-- [How to install Django on Windows](https://docs.djangoproject.com/en/4.2/howto/windows/) (Django docs)
+- [Quick Install Guide](https://docs.djangoproject.com/en/5.0/intro/install/) (Django docs)
+- [How to install Django — Complete guide](https://docs.djangoproject.com/en/5.0/topics/install/) (Django docs) — also covers how to remove Django
+- [How to install Django on Windows](https://docs.djangoproject.com/en/5.0/howto/windows/) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/django_assessment_blog/index.md b/files/en-us/learn/server-side/django/django_assessment_blog/index.md
index 58d7d5fd2e92d6d..df7e3df644a2629 100644
--- a/files/en-us/learn/server-side/django/django_assessment_blog/index.md
+++ b/files/en-us/learn/server-side/django/django_assessment_blog/index.md
@@ -273,7 +273,7 @@ Some general hints:
4. The _add comment_ form can be created using a function-based view (and associated model and form) or using a generic `CreateView`. If you use a `CreateView` (recommended) then:
- You will also need to pass the name of the blog post to the comment page in the context (implement `get_context_data()` as discussed below).
- - The form should only display the comment "description" for user entry (date and associated blog post should not be editable). Since they won't be in the form itself, your code will need to set the comment's author in the `form_valid()` function so it can be saved into the model ([as described here](https://docs.djangoproject.com/en/4.2/topics/class-based-views/generic-editing/#models-and-request-user) — Django docs). In that same function we set the associated blog. A possible implementation is shown below (`pk` is a blog id passed in from the URL/URL configuration).
+ - The form should only display the comment "description" for user entry (date and associated blog post should not be editable). Since they won't be in the form itself, your code will need to set the comment's author in the `form_valid()` function so it can be saved into the model ([as described here](https://docs.djangoproject.com/en/5.0/topics/class-based-views/generic-editing/#models-and-request-user) — Django docs). In that same function we set the associated blog. A possible implementation is shown below (`pk` is a blog id passed in from the URL/URL configuration).
```python
def form_valid(self, form):
diff --git a/files/en-us/learn/server-side/django/forms/index.md b/files/en-us/learn/server-side/django/forms/index.md
index 327a590c1db5914..722f8b7e77e0dd2 100644
--- a/files/en-us/learn/server-side/django/forms/index.md
+++ b/files/en-us/learn/server-side/django/forms/index.md
@@ -121,7 +121,7 @@ The `Form` class is the heart of Django's form handling system. It specifies the
The declaration syntax for a `Form` is very similar to that for declaring a `Model`, and shares the same field types (and some similar parameters). This makes sense because in both cases we need to ensure that each field handles the right types of data, is constrained to valid data, and has a description for display/documentation.
-Form data is stored in an application's forms.py file, inside the application directory. Create and open the file **locallibrary/catalog/forms.py**. To create a `Form`, we import the `forms` library, derive from the `Form` class, and declare the form's fields. A very basic form class for our library book renewal form is shown below — add this to your new file:
+Form data is stored in an application's forms.py file, inside the application directory. Create and open the file **django-locallibrary-tutorial/catalog/forms.py**. To create a `Form`, we import the `forms` library, derive from the `Form` class, and declare the form's fields. A very basic form class for our library book renewal form is shown below — add this to your new file:
```python
from django import forms
@@ -132,51 +132,51 @@ class RenewBookForm(forms.Form):
#### Form fields
-In this case, we have a single [`DateField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#datefield) for entering the renewal date that will render in HTML with a blank value, the default label "_Renewal date:_", and some helpful usage text: "_Enter a date between now and 4 weeks (default 3 weeks)._" As none of the other optional arguments are specified the field will accept dates using the [input_formats](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#django.forms.DateField.input_formats): YYYY-MM-DD (2016-11-06), MM/DD/YYYY (02/26/2016), MM/DD/YY (10/25/16), and will be rendered using the default [widget](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#widget): [DateInput](https://docs.djangoproject.com/en/4.2/ref/forms/widgets/#django.forms.DateInput).
+In this case, we have a single [`DateField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#datefield) for entering the renewal date that will render in HTML with a blank value, the default label "_Renewal date:_", and some helpful usage text: "_Enter a date between now and 4 weeks (default 3 weeks)._" As none of the other optional arguments are specified the field will accept dates using the [input_formats](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#django.forms.DateField.input_formats): YYYY-MM-DD (2024-11-06), MM/DD/YYYY (02/26/2024), MM/DD/YY (10/25/24), and will be rendered using the default [widget](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#widget): [DateInput](https://docs.djangoproject.com/en/5.0/ref/forms/widgets/#django.forms.DateInput).
There are many other types of form fields, which you will largely recognize from their similarity to the equivalent model field classes:
-- [`BooleanField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#booleanfield)
-- [`CharField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#charfield)
-- [`ChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#choicefield)
-- [`TypedChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#typedchoicefield)
-- [`DateField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#datefield)
-- [`DateTimeField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#datetimefield)
-- [`DecimalField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#decimalfield)
-- [`DurationField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#durationfield)
-- [`EmailField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#emailfield)
-- [`FileField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#filefield)
-- [`FilePathField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#filepathfield)
-- [`FloatField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#floatfield)
-- [`ImageField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#imagefield)
-- [`IntegerField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#integerfield)
-- [`GenericIPAddressField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#genericipaddressfield)
-- [`MultipleChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#multiplechoicefield)
-- [`TypedMultipleChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#typedmultiplechoicefield)
-- [`NullBooleanField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#nullbooleanfield)
-- [`RegexField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#regexfield)
-- [`SlugField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#slugfield)
-- [`TimeField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#timefield)
-- [`URLField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#urlfield)
-- [`UUIDField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#uuidfield)
-- [`ComboField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#combofield)
-- [`MultiValueField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#multivaluefield)
-- [`SplitDateTimeField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#splitdatetimefield)
-- [`ModelMultipleChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#modelmultiplechoicefield)
-- [`ModelChoiceField`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#modelchoicefield)
+- [`BooleanField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#booleanfield)
+- [`CharField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#charfield)
+- [`ChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#choicefield)
+- [`TypedChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#typedchoicefield)
+- [`DateField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#datefield)
+- [`DateTimeField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#datetimefield)
+- [`DecimalField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#decimalfield)
+- [`DurationField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#durationfield)
+- [`EmailField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#emailfield)
+- [`FileField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#filefield)
+- [`FilePathField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#filepathfield)
+- [`FloatField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#floatfield)
+- [`ImageField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#imagefield)
+- [`IntegerField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#integerfield)
+- [`GenericIPAddressField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#genericipaddressfield)
+- [`MultipleChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#multiplechoicefield)
+- [`TypedMultipleChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#typedmultiplechoicefield)
+- [`NullBooleanField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#nullbooleanfield)
+- [`RegexField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#regexfield)
+- [`SlugField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#slugfield)
+- [`TimeField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#timefield)
+- [`URLField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#urlfield)
+- [`UUIDField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#uuidfield)
+- [`ComboField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#combofield)
+- [`MultiValueField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#multivaluefield)
+- [`SplitDateTimeField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#splitdatetimefield)
+- [`ModelMultipleChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#modelmultiplechoicefield)
+- [`ModelChoiceField`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#modelchoicefield)
The arguments that are common to most fields are listed below (these have sensible default values):
-- [`required`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#required): If `True`, the field may not be left blank or given a `None` value. Fields are required by default, so you would set `required=False` to allow blank values in the form.
-- [`label`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#label): The label to use when rendering the field in HTML. If a [label](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#label) is not specified, Django will create one from the field name by capitalizing the first letter and replacing underscores with spaces (e.g. _Renewal date_).
-- [`label_suffix`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#label-suffix): By default, a colon is displayed after the label (e.g. Renewal date​**:**). This argument allows you to specify a different suffix containing other character(s).
-- [`initial`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#initial): The initial value for the field when the form is displayed.
-- [`widget`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#widget): The display widget to use.
-- [`help_text`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#help-text) (as seen in the example above): Additional text that can be displayed in forms to explain how to use the field.
-- [`error_messages`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#error-messages): A list of error messages for the field. You can override these with your own messages if needed.
-- [`validators`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#validators): A list of functions that will be called on the field when it is validated.
-- [`localize`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#localize): Enables the localization of form data input (see link for more information).
-- [`disabled`](https://docs.djangoproject.com/en/4.2/ref/forms/fields/#disabled): The field is displayed but its value cannot be edited if this is `True`. The default is `False`.
+- [`required`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#required): If `True`, the field may not be left blank or given a `None` value. Fields are required by default, so you would set `required=False` to allow blank values in the form.
+- [`label`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#label): The label to use when rendering the field in HTML. If a [label](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#label) is not specified, Django will create one from the field name by capitalizing the first letter and replacing underscores with spaces (e.g. _Renewal date_).
+- [`label_suffix`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#label-suffix): By default, a colon is displayed after the label (e.g. Renewal date​**:**). This argument allows you to specify a different suffix containing other character(s).
+- [`initial`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#initial): The initial value for the field when the form is displayed.
+- [`widget`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#widget): The display widget to use.
+- [`help_text`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#help-text) (as seen in the example above): Additional text that can be displayed in forms to explain how to use the field.
+- [`error_messages`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#error-messages): A list of error messages for the field. You can override these with your own messages if needed.
+- [`validators`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#validators): A list of functions that will be called on the field when it is validated.
+- [`localize`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#localize): Enables the localization of form data input (see link for more information).
+- [`disabled`](https://docs.djangoproject.com/en/5.0/ref/forms/fields/#disabled): The field is displayed but its value cannot be edited if this is `True`. The default is `False`.
#### Validation
@@ -214,15 +214,15 @@ There are two important things to note. The first is that we get our data using
This step gets us the data "cleaned" and sanitized of potentially unsafe input using the default validators, and converted into the correct standard type for the data (in this case a Python `datetime.datetime` object).
The second point is that if a value falls outside our range we raise a `ValidationError`, specifying the error text that we want to display in the form if an invalid value is entered.
-The example above also wraps this text in one of Django's [translation functions](https://docs.djangoproject.com/en/4.2/topics/i18n/translation/), `gettext_lazy()` (imported as `_()`), which is good practice if you want to translate your site later.
+The example above also wraps this text in one of Django's [translation functions](https://docs.djangoproject.com/en/5.0/topics/i18n/translation/), `gettext_lazy()` (imported as `_()`), which is good practice if you want to translate your site later.
-> **Note:** There are numerous other methods and examples for validating forms in [Form and field validation](https://docs.djangoproject.com/en/4.2/ref/forms/validation/) (Django docs). For example, in cases where you have multiple fields that depend on each other, you can override the [Form.clean()](https://docs.djangoproject.com/en/4.2/ref/forms/api/#django.forms.Form.clean) function and again raise a `ValidationError`.
+> **Note:** There are numerous other methods and examples for validating forms in [Form and field validation](https://docs.djangoproject.com/en/5.0/ref/forms/validation/) (Django docs). For example, in cases where you have multiple fields that depend on each other, you can override the [Form.clean()](https://docs.djangoproject.com/en/5.0/ref/forms/api/#django.forms.Form.clean) function and again raise a `ValidationError`.
That's all we need for the form in this example!
### URL configuration
-Before we create our view, let's add a URL configuration for the _renew-books_ page. Copy the following configuration to the bottom of **locallibrary/catalog/urls.py**:
+Before we create our view, let's add a URL configuration for the _renew-books_ page. Copy the following configuration to the bottom of **django-locallibrary-tutorial/catalog/urls.py**:
```python
urlpatterns += [
@@ -285,9 +285,9 @@ def renew_book_librarian(request, pk):
First, we import our form (`RenewBookForm`) and a number of other useful objects/methods used in the body of the view function:
-- [`get_object_or_404()`](https://docs.djangoproject.com/en/4.2/topics/http/shortcuts/#get-object-or-404): Returns a specified object from a model based on its primary key value, and raises an `Http404` exception (not found) if the record does not exist.
-- [`HttpResponseRedirect`](https://docs.djangoproject.com/en/4.2/ref/request-response/#django.http.HttpResponseRedirect): This creates a redirect to a specified URL (HTTP status code 302).
-- [`reverse()`](https://docs.djangoproject.com/en/4.2/ref/urlresolvers/#django.urls.reverse): This generates a URL from a URL configuration name and a set of arguments. It is the Python equivalent of the `url` tag that we've been using in our templates.
+- [`get_object_or_404()`](https://docs.djangoproject.com/en/5.0/topics/http/shortcuts/#get-object-or-404): Returns a specified object from a model based on its primary key value, and raises an `Http404` exception (not found) if the record does not exist.
+- [`HttpResponseRedirect`](https://docs.djangoproject.com/en/5.0/ref/request-response/#django.http.HttpResponseRedirect): This creates a redirect to a specified URL (HTTP status code 302).
+- [`reverse()`](https://docs.djangoproject.com/en/5.0/ref/urlresolvers/#django.urls.reverse): This generates a URL from a URL configuration name and a set of arguments. It is the Python equivalent of the `url` tag that we've been using in our templates.
- [`datetime`](https://docs.python.org/3/library/datetime.html): A Python library for manipulating dates and times.
In the view, we first use the `pk` argument in `get_object_or_404()` to get the current `BookInstance` (if this does not exist, the view will immediately exit and the page will display a "not found" error).
@@ -351,7 +351,7 @@ The final step in the form-handling part of the view is to redirect to another p
That's everything needed for the form handling itself, but we still need to restrict access to the view to just logged-in librarians who have permission to renew books. We use `@login_required` to require that the user is logged in, and the `@permission_required` function decorator with our existing `can_mark_returned` permission to allow access (decorators are processed in order). Note that we probably should have created a new permission setting in `BookInstance` ("`can_renew`"), but we will reuse the existing one to keep the example simple.
-The final view is therefore as shown below. Please copy this into the bottom of **locallibrary/catalog/views.py**.
+The final view is therefore as shown below. Please copy this into the bottom of **django-locallibrary-tutorial/catalog/views.py**.
```python
import datetime
@@ -484,7 +484,7 @@ It is also possible to have complete control over the rendering of each part of
- `\{{ form.renewal_date.id_for_label }}`: The id of the label.
- `\{{ form.renewal_date.help_text }}`: The field help text.
-For more examples of how to manually render forms in templates and dynamically loop over template fields, see [Working with forms > Rendering fields manually](https://docs.djangoproject.com/en/4.2/topics/forms/#rendering-fields-manually) (Django docs).
+For more examples of how to manually render forms in templates and dynamically loop over template fields, see [Working with forms > Rendering fields manually](https://docs.djangoproject.com/en/5.0/topics/forms/#rendering-fields-manually) (Django docs).
### Testing the page
@@ -542,7 +542,7 @@ The list of all books with renew links will look like this:
Creating a `Form` class using the approach described above is very flexible, allowing you to create whatever sort of form page you like and associate it with any model or models.
-However, if you just need a form to map the fields of a _single_ model then your model will already define most of the information that you need in your form: fields, labels, help text and so on. Rather than recreating the model definitions in your form, it is easier to use the [ModelForm](https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/) helper class to create the form from your model. This `ModelForm` can then be used within your views in exactly the same way as an ordinary `Form`.
+However, if you just need a form to map the fields of a _single_ model then your model will already define most of the information that you need in your form: fields, labels, help text and so on. Rather than recreating the model definitions in your form, it is easier to use the [ModelForm](https://docs.djangoproject.com/en/5.0/topics/forms/modelforms/) helper class to create the form from your model. This `ModelForm` can then be used within your views in exactly the same way as an ordinary `Form`.
A basic `ModelForm` containing the same field as our original `RenewBookForm` is shown below. All you need to do to create the form is add `class Meta` with the associated `model` (`BookInstance`) and a list of the model `fields` to include in the form.
@@ -561,7 +561,7 @@ class RenewBookModelForm(ModelForm):
>
> Neither approach is recommended because new fields added to the model are then automatically included in the form (without the developer necessarily considering possible security implications).
-> **Note:** This might not look all that much simpler than just using a `Form` (and it isn't in this case, because we just have one field). However, if you have a lot of fields, it can reduce the amount of code quite significantly!
+> **Note:** This might not look all that much simpler than just using a `Form` (and it isn't in this case, because we just have one field). However, if you have a lot of fields, it can considerably reduce the amount of code required!
The rest of the information comes from the model field definitions (e.g. labels, widgets, help text, error messages). If these aren't quite right, then we can override them in our `class Meta`, specifying a dictionary containing the field to change and its new value. For example, in this form, we might want a label for our field of "_Renewal date_" (rather than the default based on the field name: _Due Back_), and we also want our help text to be specific to this use case.
The `Meta` below shows you how to override these fields, and you can similarly set `widgets` and `error_messages` if the defaults aren't sufficient.
@@ -609,15 +609,15 @@ The class `RenewBookModelForm` above is now functionally equivalent to our origi
## Generic editing views
-The form handling algorithm we used in our function view example above represents an extremely common pattern in form editing views. Django abstracts much of this "boilerplate" for you, by creating [generic editing views](https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-editing/) for creating, editing, and deleting views based on models. Not only do these handle the "view" behavior, but they automatically create the form class (a `ModelForm`) for you from the model.
+The form handling algorithm we used in our function view example above represents an extremely common pattern in form editing views. Django abstracts much of this "boilerplate" for you, by creating [generic editing views](https://docs.djangoproject.com/en/5.0/ref/class-based-views/generic-editing/) for creating, editing, and deleting views based on models. Not only do these handle the "view" behavior, but they automatically create the form class (a `ModelForm`) for you from the model.
-> **Note:** In addition to the editing views described here, there is also a [FormView](https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-editing/#formview) class, which lies somewhere between our function view and the other generic views in terms of "flexibility" vs. "coding effort". Using `FormView`, you still need to create your `Form`, but you don't have to implement all of the standard form-handling patterns. Instead, you just have to provide an implementation of the function that will be called once the submission is known to be valid.
+> **Note:** In addition to the editing views described here, there is also a [FormView](https://docs.djangoproject.com/en/5.0/ref/class-based-views/generic-editing/#formview) class, which lies somewhere between our function view and the other generic views in terms of "flexibility" vs. "coding effort". Using `FormView`, you still need to create your `Form`, but you don't have to implement all of the standard form-handling patterns. Instead, you just have to provide an implementation of the function that will be called once the submission is known to be valid.
In this section, we're going to use generic editing views to create pages to add functionality to create, edit, and delete `Author` records from our library — effectively providing a basic reimplementation of parts of the Admin site (this could be useful if you need to offer admin functionality in a more flexible way than can be provided by the admin site).
### Views
-Open the views file (**locallibrary/catalog/views.py**) and append the following code block to the bottom of it:
+Open the views file (**django-locallibrary-tutorial/catalog/views.py**) and append the following code block to the bottom of it:
```python
from django.views.generic.edit import CreateView, UpdateView, DeleteView
@@ -657,16 +657,16 @@ We also restrict calling these views to only logged in users with the `add_autho
For the "create" and "update" cases you also need to specify the fields to display in the form (using the same syntax as for `ModelForm`). In this case, we show how to list them individually and the syntax to list "all" fields. You can also specify initial values for each of the fields using a dictionary of _field_name_/_value_ pairs (here we arbitrarily set the date of death for demonstration purposes — you might want to remove that). By default, these views will redirect on success to a page displaying the newly created/edited model item, which in our case will be the author detail view we created in a previous tutorial. You can specify an alternative redirect location by explicitly declaring parameter `success_url`.
The `AuthorDelete` class doesn't need to display any of the fields, so these don't need to be specified.
-We so set a `success_url` (as shown above), because there is no obvious default URL for Django to navigate to after successfully deleting the `Author`. Above we use the [`reverse_lazy()`](https://docs.djangoproject.com/en/4.2/ref/urlresolvers/#reverse-lazy) function to redirect to our author list after an author has been deleted — `reverse_lazy()` is a lazily executed version of `reverse()`, used here because we're providing a URL to a class-based view attribute.
+We so set a `success_url` (as shown above), because there is no obvious default URL for Django to navigate to after successfully deleting the `Author`. Above we use the [`reverse_lazy()`](https://docs.djangoproject.com/en/5.0/ref/urlresolvers/#reverse-lazy) function to redirect to our author list after an author has been deleted — `reverse_lazy()` is a lazily executed version of `reverse()`, used here because we're providing a URL to a class-based view attribute.
If deletion of authors should always succeed that would be it.
Unfortunately deleting an `Author` will cause an exception if the author has an associated book, because our [`Book` model](/en-US/docs/Learn/Server-side/Django/Models#book_model) specifies `on_delete=models.RESTRICT` for the author `ForeignKey` field.
-To handle this case the view overrides the [`form_valid()`](https://docs.djangoproject.com/en/4.2/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.form_valid) method so that if deleting the `Author` succeeds it redirects to the `success_url`, but if not, it just redirects back to the same form.
+To handle this case the view overrides the [`form_valid()`](https://docs.djangoproject.com/en/5.0/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.form_valid) method so that if deleting the `Author` succeeds it redirects to the `success_url`, but if not, it just redirects back to the same form.
We'll update the template below to make clear that you can't delete an `Author` instance that is used in any `Book`.
### URL configurations
-Open your URL configuration file (**locallibrary/catalog/urls.py**) and add the following configuration to the bottom of the file:
+Open your URL configuration file (**django-locallibrary-tutorial/catalog/urls.py**) and add the following configuration to the bottom of the file:
```python
urlpatterns += [
@@ -682,7 +682,7 @@ There is nothing particularly new here! You can see that the views are classes,
The "create" and "update" views use the same template by default, which will be named after your model: `model_name_form.html` (you can change the suffix to something other than **\_form** using the `template_name_suffix` field in your view, for example, `template_name_suffix = '_other_suffix'`)
-Create the template file `locallibrary/catalog/templates/catalog/author_form.html` and copy the text below.
+Create the template file `django-locallibrary-tutorial/catalog/templates/catalog/author_form.html` and copy the text below.
```django
{% extends "base_generic.html" %}
@@ -701,7 +701,7 @@ Create the template file `locallibrary/catalog/templates/catalog/author_form.htm
This is similar to our previous forms and renders the fields using a table. Note also how again we declare the `{% csrf_token %}` to ensure that our forms are resistant to CSRF attacks.
The "delete" view expects to find a template named with the format \_`model_name_confirm_delete.html` (again, you can change the suffix using `template_name_suffix` in your view).
-Create the template file `locallibrary/catalog/templates/catalog/author_confirm_delete.html` and copy the text below.
+Create the template file `django-locallibrary-tutorial/catalog/templates/catalog/author_confirm_delete.html` and copy the text below.
```django
{% extends "base_generic.html" %}
@@ -737,7 +737,7 @@ If not, it displays a form asking the user to confirm they want to delete the au
The final step is to hook the pages into the sidebar.
First we'll add a link for creating the author into the _base template_, so that it is visible in all pages for logged in users who are considered "staff" and who have permission to create authors (`catalog.add_author`).
-Open **/locallibrary/catalog/templates/base_generic.html** and add the lines that allow users with the permission to create the author (in the same block as the link that shows "All Borrowed" books).
+Open **/django-locallibrary-tutorial/catalog/templates/base_generic.html** and add the lines that allow users with the permission to create the author (in the same block as the link that shows "All Borrowed" books).
Remember to reference the URL using it's name `'author-create'` as shown below.
```django
@@ -817,13 +817,13 @@ There is a lot more that can be done with forms (check out our [See also](#see_a
## See also
-- [Working with forms](https://docs.djangoproject.com/en/4.2/topics/forms/) (Django docs)
-- [Writing your first Django app, part 4 > Writing a simple form](https://docs.djangoproject.com/en/4.2/intro/tutorial04/#write-a-simple-form) (Django docs)
-- [The Forms API](https://docs.djangoproject.com/en/4.2/ref/forms/api/) (Django docs)
-- [Form fields](https://docs.djangoproject.com/en/4.2/ref/forms/fields/) (Django docs)
-- [Form and field validation](https://docs.djangoproject.com/en/4.2/ref/forms/validation/) (Django docs)
-- [Form handling with class-based views](https://docs.djangoproject.com/en/4.2/topics/class-based-views/generic-editing/) (Django docs)
-- [Creating forms from models](https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/) (Django docs)
-- [Generic editing views](https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-editing/) (Django docs)
+- [Working with forms](https://docs.djangoproject.com/en/5.0/topics/forms/) (Django docs)
+- [Writing your first Django app, part 4 > Writing a simple form](https://docs.djangoproject.com/en/5.0/intro/tutorial04/#write-a-simple-form) (Django docs)
+- [The Forms API](https://docs.djangoproject.com/en/5.0/ref/forms/api/) (Django docs)
+- [Form fields](https://docs.djangoproject.com/en/5.0/ref/forms/fields/) (Django docs)
+- [Form and field validation](https://docs.djangoproject.com/en/5.0/ref/forms/validation/) (Django docs)
+- [Form handling with class-based views](https://docs.djangoproject.com/en/5.0/topics/class-based-views/generic-editing/) (Django docs)
+- [Creating forms from models](https://docs.djangoproject.com/en/5.0/topics/forms/modelforms/) (Django docs)
+- [Generic editing views](https://docs.djangoproject.com/en/5.0/ref/class-based-views/generic-editing/) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/generic_views/index.md b/files/en-us/learn/server-side/django/generic_views/index.md
index 25d64b09085ccc4..590203523990dde 100644
--- a/files/en-us/learn/server-side/django/generic_views/index.md
+++ b/files/en-us/learn/server-side/django/generic_views/index.md
@@ -68,7 +68,7 @@ class BookListView(generic.ListView):
model = Book
```
-That's it! The generic view will query the database to get all records for the specified model (`Book`) then render a template located at **/locallibrary/catalog/templates/catalog/book_list.html** (which we will create below). Within the template you can access the list of books with the template variable named `object_list` OR `book_list` (i.e. generically "`_list`").
+That's it! The generic view will query the database to get all records for the specified model (`Book`) then render a template located at **/django-locallibrary-tutorial/catalog/templates/catalog/book_list.html** (which we will create below). Within the template you can access the list of books with the template variable named `object_list` OR `book_list` (i.e. generically "`_list`").
> **Note:** This awkward path for the template location isn't a misprint — the generic views look for templates in `/application_name/the_model_name_list.html` (`catalog/book_list.html` in this case) inside the application's `/application_name/templates/` directory (`/catalog/templates/)`.
@@ -116,11 +116,11 @@ When doing this it is important to follow the pattern used above:
- Then add your new context information.
- Then return the new (updated) context.
-> **Note:** Check out [Built-in class-based generic views](https://docs.djangoproject.com/en/4.2/topics/class-based-views/generic-display/) (Django docs) for many more examples of what you can do.
+> **Note:** Check out [Built-in class-based generic views](https://docs.djangoproject.com/en/5.0/topics/class-based-views/generic-display/) (Django docs) for many more examples of what you can do.
### Creating the List View template
-Create the HTML file **/locallibrary/catalog/templates/catalog/book_list.html** and copy in the text below. As discussed above, this is the default template file expected by the generic class-based list view (for a model named `Book` in an application named `catalog`).
+Create the HTML file **/django-locallibrary-tutorial/catalog/templates/catalog/book_list.html** and copy in the text below. As discussed above, this is the default template file expected by the generic class-based list view (for a model named `Book` in an application named `catalog`).
Templates for generic views are just like any other templates (although of course the context/information passed to the template may differ).
As with our _index_ template, we extend our base template in the first line and then replace the block named `content`.
@@ -149,7 +149,7 @@ The view passes the context (list of books) by default as `object_list` and `boo
#### Conditional execution
-We use the [`if`](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#if), `else`, and `endif` template tags to check whether the `book_list` has been defined and is not empty.
+We use the [`if`](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#if), `else`, and `endif` template tags to check whether the `book_list` has been defined and is not empty.
If `book_list` is empty, then the `else` clause displays text explaining that there are no books to list.
If `book_list` is not empty, then we iterate through the list of books.
@@ -162,11 +162,11 @@ If `book_list` is not empty, then we iterate through the list of books.
```
The condition above only checks for one case, but you can test on additional conditions using the `elif` template tag (e.g. `{% elif var2 %}`).
-For more information about conditional operators see: [if](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#if), [ifequal/ifnotequal](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#ifequal-and-ifnotequal), and [ifchanged](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#ifchanged) in [Built-in template tags and filters](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/) (Django Docs).
+For more information about conditional operators see: [if](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#if), [ifequal/ifnotequal](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#ifequal-and-ifnotequal), and [ifchanged](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#ifchanged) in [Built-in template tags and filters](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/) (Django Docs).
#### For loops
-The template uses the [for](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#for) and `endfor` template tags to loop through the book list, as shown below.
+The template uses the [for](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#for) and `endfor` template tags to loop through the book list, as shown below.
Each iteration populates the `book` template variable with information for the current list item.
```django
@@ -206,7 +206,7 @@ We can also call _functions_ in the model from within our template — in this c
#### Update the base template
-Open the base template (**/locallibrary/catalog/templates/_base_generic.html_**) and insert **{% url 'books' %}** into the URL link for **All books**, as shown below. This will enable the link in all pages (we can successfully put this in place now that we've created the "books" URL mapper).
+Open the base template (**/django-locallibrary-tutorial/catalog/templates/_base_generic.html_**) and insert **{% url 'books' %}** into the URL link for **All books**, as shown below. This will enable the link in all pages (we can successfully put this in place now that we've created the "books" URL mapper).
```django
@@ -237,7 +237,7 @@ urlpatterns = [
For the _book-detail_ path the URL pattern uses a special syntax to capture the specific id of the book that we want to see.
The syntax is very simple: angle brackets define the part of the URL to be captured, enclosing the name of the variable that the view can use to access the captured data.
-For example, **\**, will capture the marked pattern and pass the value to the view as a variable "something". You can optionally precede the variable name with a [converter specification](https://docs.djangoproject.com/en/4.2/topics/http/urls/#path-converters) that defines the type of data (int, str, slug, uuid, path).
+For example, **\**, will capture the marked pattern and pass the value to the view as a variable "something". You can optionally precede the variable name with a [converter specification](https://docs.djangoproject.com/en/5.0/topics/http/urls/#path-converters) that defines the type of data (int, str, slug, uuid, path).
In this case we use `''` to capture the book id, which must be a specially formatted string and pass it to the view as a parameter named `pk` (short for primary key). This is the id that is being used to store the book uniquely in the database, as defined in the Book Model.
@@ -249,7 +249,7 @@ In this case we use `''` to capture the book id, which must be a special
> **Note:** You won't need this section to complete the tutorial! We provide it because knowing this option is likely to be useful in your Django-centric future.
-The pattern matching provided by `path()` is simple and useful for the (very common) cases where you just want to capture _any_ string or integer. If you need more refined filtering (for example, to filter only strings that have a certain number of characters) then you can use the [re_path()](https://docs.djangoproject.com/en/4.2/ref/urls/#django.urls.re_path) method.
+The pattern matching provided by `path()` is simple and useful for the (very common) cases where you just want to capture _any_ string or integer. If you need more refined filtering (for example, to filter only strings that have a certain number of characters) then you can use the [re_path()](https://docs.djangoproject.com/en/5.0/ref/urls/#django.urls.re_path) method.
This method is used just like `path()` except that it allows you to specify a pattern using a [Regular expression](https://docs.python.org/3/library/re.html). For example, the previous path could have been written as shown below:
@@ -401,7 +401,7 @@ You can capture multiple patterns in the one match, and hence encode lots of dif
#### Passing additional options in your URL maps
-One feature that we haven't used here, but which you may find valuable, is that you can pass a [dictionary containing additional options](https://docs.djangoproject.com/en/4.2/topics/http/urls/#views-extra-options) to the view (using the third un-named argument to the `path()` function). This approach can be useful if you want to use the same view for multiple resources, and pass data to configure its behavior in each case.
+One feature that we haven't used here, but which you may find valuable, is that you can pass a [dictionary containing additional options](https://docs.djangoproject.com/en/5.0/topics/http/urls/#views-extra-options) to the view (using the third un-named argument to the `path()` function). This approach can be useful if you want to use the same view for multiple resources, and pass data to configure its behavior in each case.
For example, given the path shown below, for a request to `/myurl/halibut/` Django will call `views.my_view(request, fish='halibut', my_template_name='some_path')`.
@@ -420,7 +420,7 @@ class BookDetailView(generic.DetailView):
model = Book
```
-That's it! All you need to do now is create a template called **/locallibrary/catalog/templates/catalog/book_detail.html**, and the view will pass it the database information for the specific `Book` record extracted by the URL mapper. Within the template you can access the book's details with the template variable named `object` OR `book` (i.e. generically "`the_model_name`").
+That's it! All you need to do now is create a template called **/django-locallibrary-tutorial/catalog/templates/catalog/book_detail.html**, and the view will pass it the database information for the specific `Book` record extracted by the URL mapper. Within the template you can access the book's details with the template variable named `object` OR `book` (i.e. generically "`the_model_name`").
If you need to, you can change the template used and the name of the context object used to reference the book in the template. You can also override methods to, for example, add additional information to the context.
@@ -455,7 +455,7 @@ def book_detail_view(request, primary_key):
### Creating the Detail View template
-Create the HTML file **/locallibrary/catalog/templates/catalog/book_detail.html** and give it the below content. As discussed above, this is the default template file name expected by the generic class-based _detail_ view (for a model named `Book` in an application named `catalog`).
+Create the HTML file **/django-locallibrary-tutorial/catalog/templates/catalog/book_detail.html** and give it the below content. As discussed above, this is the default template file name expected by the generic class-based _detail_ view (for a model named `Book` in an application named `catalog`).
```django
{% extends "base_generic.html" %}
@@ -533,7 +533,7 @@ This method is needed because you declare a `ForeignKey` (one-to many) field onl
> allow_empty_first_page=allow_empty_first_page, **kwargs)
> ```
>
-> That happens because the [paginator object](https://docs.djangoproject.com/en/4.2/topics/pagination/#paginator-objects) expects to see some ORDER BY being executed on your underlying database. Without it, it can't be sure the records being returned are actually in the right order!
+> That happens because the [paginator object](https://docs.djangoproject.com/en/5.0/topics/pagination/#paginator-objects) expects to see some ORDER BY being executed on your underlying database. Without it, it can't be sure the records being returned are actually in the right order!
>
> This tutorial hasn't covered **Pagination** (yet!), but since you can't use `sort_by()` and pass a parameter (the same with `filter()` described above) you will have to choose between three choices:
>
@@ -572,7 +572,7 @@ Astute readers will note that the method `BookInstance.get_status_display()` tha
\{{ copy.get_status_display }}
```
-This function is automatically created because `BookInstance.status` is a [choices field](https://docs.djangoproject.com/en/4.2/ref/models/fields/#choices).
+This function is automatically created because `BookInstance.status` is a [choices field](https://docs.djangoproject.com/en/5.0/ref/models/fields/#choices).
Django automatically creates a method `get_FOO_display()` for every choices field "`Foo`" in a model, which can be used to get the current value of the field.
## What does it look like?
@@ -612,7 +612,7 @@ The different pages are accessed using GET parameters — to access page 2 you w
Now that the data is paginated, we need to add support to the template to scroll through the results set. Because we might want paginate all list views, we'll add this to the base template.
-Open **/locallibrary/catalog/templates/_base_generic.html_** and find the "content block" (as shown below).
+Open **/django-locallibrary-tutorial/catalog/templates/_base_generic.html_** and find the "content block" (as shown below).
```django
{% block content %}{% endblock %}
@@ -640,7 +640,7 @@ Copy in the following pagination block immediately following the `{% endblock %}
{% endblock %}
```
-The `page_obj` is a [Paginator](https://docs.djangoproject.com/en/4.2/topics/pagination/#paginator-objects) object that will exist if pagination is being used on the current page. It allows you to get all the information about the current page, previous pages, how many pages there are, etc.
+The `page_obj` is a [Paginator](https://docs.djangoproject.com/en/5.0/topics/pagination/#paginator-objects) object that will exist if pagination is being used on the current page. It allows you to get all the information about the current page, previous pages, how many pages there are, etc.
We use `\{{ request.path }}` to get the current page URL for creating the pagination links. This is useful because it is independent of the object that we're paginating.
@@ -667,7 +667,7 @@ The code required for the URL mappers and the views should be virtually identica
>
> - Once you've created the URL mapper for the author list page you will also need to update the **All authors** link in the base template.
> Follow the [same process](#update_the_base_template) as we did when we updated the **All books** link.
-> - Once you've created the URL mapper for the author detail page, you should also update the [book detail view template](#creating_the_detail_view_template) (**/locallibrary/catalog/templates/catalog/book_detail.html**) so that the author link points to your new author detail page (rather than being an empty URL).
+> - Once you've created the URL mapper for the author detail page, you should also update the [book detail view template](#creating_the_detail_view_template) (**/django-locallibrary-tutorial/catalog/templates/catalog/book_detail.html**) so that the author link points to your new author detail page (rather than being an empty URL).
> The recommended way to do this is to call `get_absolute_url()` on the author model as shown below.
>
> ```django
@@ -693,11 +693,11 @@ In our next articles, we'll extend this library to support user accounts, and th
## See also
-- [Built-in class-based generic views](https://docs.djangoproject.com/en/4.2/topics/class-based-views/generic-display/) (Django docs)
-- [Generic display views](https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-display/) (Django docs)
-- [Introduction to class-based views](https://docs.djangoproject.com/en/4.2/topics/class-based-views/intro/) (Django docs)
-- [Built-in template tags and filters](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/) (Django docs)
-- [Pagination](https://docs.djangoproject.com/en/4.2/topics/pagination/) (Django docs)
-- [Making queries > Related objects](https://docs.djangoproject.com/en/4.2/topics/db/queries/#related-objects) (Django docs)
+- [Built-in class-based generic views](https://docs.djangoproject.com/en/5.0/topics/class-based-views/generic-display/) (Django docs)
+- [Generic display views](https://docs.djangoproject.com/en/5.0/ref/class-based-views/generic-display/) (Django docs)
+- [Introduction to class-based views](https://docs.djangoproject.com/en/5.0/topics/class-based-views/intro/) (Django docs)
+- [Built-in template tags and filters](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/) (Django docs)
+- [Pagination](https://docs.djangoproject.com/en/5.0/topics/pagination/) (Django docs)
+- [Making queries > Related objects](https://docs.djangoproject.com/en/5.0/topics/db/queries/#related-objects) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/home_page/index.md b/files/en-us/learn/server-side/django/home_page/index.md
index ede7f4b06af7131..90944f15f9aef55 100644
--- a/files/en-us/learn/server-side/django/home_page/index.md
+++ b/files/en-us/learn/server-side/django/home_page/index.md
@@ -78,7 +78,7 @@ urlpatterns += [
]
```
-> **Note:** Whenever Django encounters the import function [`django.urls.include()`](https://docs.djangoproject.com/en/4.2/ref/urls/#django.urls.include), it splits the URL string at the designated end character and sends the remaining substring to the included _URLconf_ module for further processing.
+> **Note:** Whenever Django encounters the import function [`django.urls.include()`](https://docs.djangoproject.com/en/5.0/ref/urls/#django.urls.include), it splits the URL string at the designated end character and sends the remaining substring to the included _URLconf_ module for further processing.
We also created a placeholder file for the _URLConf_ module, named **/catalog/urls.py**.
Add the following lines to that file:
@@ -107,7 +107,7 @@ For example, we can use the name parameter to link to our home page from any oth
A view is a function that processes an HTTP request, fetches the required data from the database, renders the data in an HTML page using an HTML template, and then returns the generated HTML in an HTTP response to display the page to the user. The index view follows this model — it fetches information about the number of `Book`, `BookInstance`, available `BookInstance` and `Author` records that we have in the database, and passes that information to a template for display.
-Open **catalog/views.py** and note that the file already imports the [render()](https://docs.djangoproject.com/en/4.2/topics/http/shortcuts/#django.shortcuts.render) shortcut function to generate an HTML file using a template and data:
+Open **catalog/views.py** and note that the file already imports the [render()](https://docs.djangoproject.com/en/5.0/topics/http/shortcuts/#django.shortcuts.render) shortcut function to generate an HTML file using a template and data:
```python
from django.shortcuts import render
@@ -160,11 +160,11 @@ We'll talk more about templates and the `context` variable in the next section.
A template is a text file that defines the structure or layout of a file (such as an HTML page), it uses placeholders to represent actual content.
-A Django application created using **startapp** (like the skeleton of this example) will look for templates in a subdirectory named '**templates**' of your applications. For example, in the index view that we just added, the `render()` function will expect to find the file **_index.html_** in **/locallibrary/catalog/templates/** and will raise an error if the file is not present.
+A Django application created using **startapp** (like the skeleton of this example) will look for templates in a subdirectory named '**templates**' of your applications. For example, in the index view that we just added, the `render()` function will expect to find the file **_index.html_** in **/django-locallibrary-tutorial/catalog/templates/** and will raise an error if the file is not present.
You can check this by saving the previous changes and accessing `127.0.0.1:8000` in your browser - it will display a fairly intuitive error message: "`TemplateDoesNotExist at /catalog/`", and other details.
-> **Note:** Based on your project's settings file, Django will look for templates in a number of places, searching in your installed applications by default. You can find out more about how Django finds templates and what template formats it supports in [the Templates section of the Django documentation](https://docs.djangoproject.com/en/4.2/topics/templates/).
+> **Note:** Based on your project's settings file, Django will look for templates in a number of places, searching in your installed applications by default. You can find out more about how Django finds templates and what template formats it supports in [the Templates section of the Django documentation](https://docs.djangoproject.com/en/5.0/topics/templates/).
#### Extending templates
@@ -220,7 +220,7 @@ We will use the following code snippet as the base template for the _LocalLibrar
> **Note:** We also introduce two additional template tags: `url` and `load static`. These tags will be explained in following sections.
-Create a new file **base_generic.html** in **/locallibrary/catalog/templates/** and paste the following code to the file:
+Create a new file **base_generic.html** in **/django-locallibrary-tutorial/catalog/templates/** and paste the following code to the file:
```django
@@ -231,9 +231,9 @@ Create a new file **base_generic.html** in **/locallibrary/catalog/templates/**
{% endblock %}
-
{% load static %}
@@ -260,7 +260,7 @@ Create a new file **base_generic.html** in **/locallibrary/catalog/templates/**
The template includes CSS from [Bootstrap](https://getbootstrap.com/) to improve the layout and presentation of the HTML page. Using Bootstrap (or another client-side web framework) is a quick way to create an attractive page that displays well on different screen sizes.
-The base template also references a local CSS file (**styles.css**) that provides additional styling. Create a **styles.css** file in **/locallibrary/catalog/static/css/** and paste the following code in the file:
+The base template also references a local CSS file (**styles.css**) that provides additional styling. Create a **styles.css** file in **/django-locallibrary-tutorial/catalog/static/css/** and paste the following code in the file:
```css
.sidebar-nav {
@@ -272,7 +272,7 @@ The base template also references a local CSS file (**styles.css**) that provide
#### The index template
-Create a new HTML file **index.html** in **/locallibrary/catalog/templates/** and paste the following code in the file.
+Create a new HTML file **index.html** in **/django-locallibrary-tutorial/catalog/templates/** and paste the following code in the file.
This code extends our base template on the first line, and then replaces the default `content` block for the template.
```django
@@ -336,9 +336,9 @@ You can add an image into the page in a similar way, for example:
style="width:555px;height:540px;" />
```
-> **Note:** The samples above specify where the files are located, but Django does not serve them by default. We configured the development web server to serve files by modifying the global URL mapper (**/locallibrary/locallibrary/urls.py**) when we [created the website skeleton](/en-US/docs/Learn/Server-side/Django/skeleton_website), but still need to enable file serving in production. We'll look at this later.
+> **Note:** The samples above specify where the files are located, but Django does not serve them by default. We configured the development web server to serve files by modifying the global URL mapper (**/django-locallibrary-tutorial/locallibrary/urls.py**) when we [created the website skeleton](/en-US/docs/Learn/Server-side/Django/skeleton_website), but still need to enable file serving in production. We'll look at this later.
-For more information on working with static files see [Managing static files](https://docs.djangoproject.com/en/4.2/howto/static-files/) in the Django documentation.
+For more information on working with static files see [Managing static files](https://docs.djangoproject.com/en/5.0/howto/static-files/) in the Django documentation.
#### Linking to URLs
@@ -377,7 +377,7 @@ The setting of `'APP_DIRS': True`, is the most important, as it tells Django to
We can also specify specific locations for Django to search for directories using `'DIRS': []` (but that isn't needed yet).
-> **Note:** You can find out more about how Django finds templates and what template formats it supports in [the Templates section of the Django documentation](https://docs.djangoproject.com/en/4.2/topics/templates/).
+> **Note:** You can find out more about how Django finds templates and what template formats it supports in [the Templates section of the Django documentation](https://docs.djangoproject.com/en/5.0/topics/templates/).
## What does it look like?
@@ -405,11 +405,11 @@ In the next article we'll build upon this knowledge to create the remaining four
## See also
-- [Writing your first Django app, part 3: Views and Templates](https://docs.djangoproject.com/en/4.2/intro/tutorial03/) (Django docs)
-- [URL dispatcher](https://docs.djangoproject.com/en/4.2/topics/http/urls/) (Django docs)
-- [View functions](https://docs.djangoproject.com/en/4.2/topics/http/views/) (DJango docs)
-- [Templates](https://docs.djangoproject.com/en/4.2/topics/templates/) (Django docs)
-- [Managing static files](https://docs.djangoproject.com/en/4.2/howto/static-files/) (Django docs)
-- [Django shortcut functions](https://docs.djangoproject.com/en/4.2/topics/http/shortcuts/#django.shortcuts.render) (Django docs)
+- [Writing your first Django app, part 3: Views and Templates](https://docs.djangoproject.com/en/5.0/intro/tutorial03/) (Django docs)
+- [URL dispatcher](https://docs.djangoproject.com/en/5.0/topics/http/urls/) (Django docs)
+- [View functions](https://docs.djangoproject.com/en/5.0/topics/http/views/) (DJango docs)
+- [Templates](https://docs.djangoproject.com/en/5.0/topics/templates/) (Django docs)
+- [Managing static files](https://docs.djangoproject.com/en/5.0/howto/static-files/) (Django docs)
+- [Django shortcut functions](https://docs.djangoproject.com/en/5.0/topics/http/shortcuts/#django.shortcuts.render) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/introduction/index.md b/files/en-us/learn/server-side/django/introduction/index.md
index e0c24d7a1259bad..ff69f813139f9a1 100644
--- a/files/en-us/learn/server-side/django/introduction/index.md
+++ b/files/en-us/learn/server-side/django/introduction/index.md
@@ -60,7 +60,7 @@ Django helps you write software that is:
Django was initially developed between 2003 and 2005 by a web team who were responsible for creating and maintaining newspaper websites. After creating a number of sites, the team began to factor out and reuse lots of common code and design patterns. This common code evolved into a generic web development framework, which was open-sourced as the "Django" project in July 2005.
-Django has continued to grow and improve, from its first milestone release (1.0) in September 2008 through to the version 4.0 in 2022. Each release has added new functionality and bug fixes, ranging from support for new types of databases, template engines, and caching, through to the addition of "generic" view functions and classes (which reduce the amount of code that developers have to write for a number of programming tasks).
+Django has continued to grow and improve, from its first milestone release (1.0) in September 2008 through to the version 5.0 in late 2023. Each release has added new functionality and bug fixes, ranging from support for new types of databases, template engines, and caching, through to the addition of "generic" view functions and classes (which reduce the amount of code that developers have to write for a number of programming tasks).
> **Note:** Check out the [release notes](https://docs.djangoproject.com/en/stable/releases/) on the Django website to see what has changed in recent versions, and how much work is going into making Django better.
diff --git a/files/en-us/learn/server-side/django/models/index.md b/files/en-us/learn/server-side/django/models/index.md
index 622b0c04af172ea..fc6c1c892d3405d 100644
--- a/files/en-us/learn/server-side/django/models/index.md
+++ b/files/en-us/learn/server-side/django/models/index.md
@@ -113,22 +113,22 @@ The order that fields are declared will affect their default order if a model is
The following common arguments can be used when declaring many/most of the different field types:
-- [help_text](https://docs.djangoproject.com/en/4.2/ref/models/fields/#help-text): Provides a text label for HTML forms (e.g. in the admin site), as described above.
-- [verbose_name](https://docs.djangoproject.com/en/4.2/ref/models/fields/#verbose-name): A human-readable name for the field used in field labels. If not specified, Django will infer the default verbose name from the field name.
-- [default](https://docs.djangoproject.com/en/4.2/ref/models/fields/#default): The default value for the field. This can be a value or a callable object, in which case the object will be called every time a new record is created.
-- [null](https://docs.djangoproject.com/en/4.2/ref/models/fields/#null): If `True`, Django will store blank values as `NULL` in the database for fields where this is appropriate (a `CharField` will instead store an empty string). The default is `False`.
-- [blank](https://docs.djangoproject.com/en/4.2/ref/models/fields/#blank): If `True`, the field is allowed to be blank in your forms. The default is `False`, which means that Django's form validation will force you to enter a value. This is often used with `null=True`, because if you're going to allow blank values, you also want the database to be able to represent them appropriately.
-- [choices](https://docs.djangoproject.com/en/4.2/ref/models/fields/#choices): A group of choices for this field. If this is provided, the default corresponding form widget will be a select box with these choices instead of the standard text field.
-- [unique](https://docs.djangoproject.com/en/4.2/ref/models/fields/#unique):
+- [help_text](https://docs.djangoproject.com/en/5.0/ref/models/fields/#help-text): Provides a text label for HTML forms (e.g. in the admin site), as described above.
+- [verbose_name](https://docs.djangoproject.com/en/5.0/ref/models/fields/#verbose-name): A human-readable name for the field used in field labels. If not specified, Django will infer the default verbose name from the field name.
+- [default](https://docs.djangoproject.com/en/5.0/ref/models/fields/#default): The default value for the field. This can be a value or a callable object, in which case the object will be called every time a new record is created.
+- [null](https://docs.djangoproject.com/en/5.0/ref/models/fields/#null): If `True`, Django will store blank values as `NULL` in the database for fields where this is appropriate (a `CharField` will instead store an empty string). The default is `False`.
+- [blank](https://docs.djangoproject.com/en/5.0/ref/models/fields/#blank): If `True`, the field is allowed to be blank in your forms. The default is `False`, which means that Django's form validation will force you to enter a value. This is often used with `null=True`, because if you're going to allow blank values, you also want the database to be able to represent them appropriately.
+- [choices](https://docs.djangoproject.com/en/5.0/ref/models/fields/#choices): A group of choices for this field. If this is provided, the default corresponding form widget will be a select box with these choices instead of the standard text field.
+- [unique](https://docs.djangoproject.com/en/5.0/ref/models/fields/#unique):
If `True`, ensures that the field value is unique across the database.
This can be used to prevent duplication of fields that can't have the same values.
The default is `False`.
-- [primary_key](https://docs.djangoproject.com/en/4.2/ref/models/fields/#primary-key):
+- [primary_key](https://docs.djangoproject.com/en/5.0/ref/models/fields/#primary-key):
If `True`, sets the current field as the primary key for the model (A primary key is a special database column designated to uniquely identify all the different table records).
If no field is specified as the primary key, Django will automatically add a field for this purpose.
- The type of auto-created primary key fields can be specified for each app in [`AppConfig.default_auto_field`](https://docs.djangoproject.com/en/4.2/ref/applications/#django.apps.AppConfig.default_auto_field) or globally in the [`DEFAULT_AUTO_FIELD`](https://docs.djangoproject.com/en/4.2/ref/settings/#std:setting-DEFAULT_AUTO_FIELD) setting.
+ The type of auto-created primary key fields can be specified for each app in [`AppConfig.default_auto_field`](https://docs.djangoproject.com/en/5.0/ref/applications/#django.apps.AppConfig.default_auto_field) or globally in the [`DEFAULT_AUTO_FIELD`](https://docs.djangoproject.com/en/5.0/ref/settings/#std:setting-DEFAULT_AUTO_FIELD) setting.
- > **Note:** Apps created using **manage.py** set the type of the primary key to a [BigAutoField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#bigautofield).
+ > **Note:** Apps created using **manage.py** set the type of the primary key to a [BigAutoField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#bigautofield).
> You can see this in the local library **catalog/apps.py** file:
>
> ```py
@@ -136,23 +136,23 @@ The following common arguments can be used when declaring many/most of the diffe
> default_auto_field = 'django.db.models.BigAutoField'
> ```
-There are many other options — you can view the [full list of field options here](https://docs.djangoproject.com/en/4.2/ref/models/fields/#field-options).
+There are many other options — you can view the [full list of field options here](https://docs.djangoproject.com/en/5.0/ref/models/fields/#field-options).
##### Common field types
The following list describes some of the more commonly used types of fields.
-- [CharField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.CharField) is used to define short-to-mid sized fixed-length strings. You must specify the `max_length` of the data to be stored.
-- [TextField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.TextField) is used for large arbitrary-length strings. You may specify a `max_length` for the field, but this is used only when the field is displayed in forms (it is not enforced at the database level).
-- [IntegerField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.IntegerField) is a field for storing integer (whole number) values, and for validating entered values as integers in forms.
-- [DateField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#datefield) and [DateTimeField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#datetimefield) are used for storing/representing dates and date/time information (as Python `datetime.date` and `datetime.datetime` objects, respectively). These fields can additionally declare the (mutually exclusive) parameters `auto_now=True` (to set the field to the current date every time the model is saved), `auto_now_add` (to only set the date when the model is first created), and `default` (to set a default date that can be overridden by the user).
-- [EmailField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#emailfield) is used to store and validate email addresses.
-- [FileField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#filefield) and [ImageField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#imagefield) are used to upload files and images respectively (the `ImageField` adds additional validation that the uploaded file is an image). These have parameters to define how and where the uploaded files are stored.
-- [AutoField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#autofield) is a special type of `IntegerField` that automatically increments. A primary key of this type is automatically added to your model if you don't explicitly specify one.
-- [ForeignKey](https://docs.djangoproject.com/en/4.2/ref/models/fields/#foreignkey) is used to specify a one-to-many relationship to another database model (e.g. a car has one manufacturer, but a manufacturer can make many cars). The "one" side of the relationship is the model that contains the "key" (models containing a "foreign key" referring to that "key", are on the "many" side of such a relationship).
-- [ManyToManyField](https://docs.djangoproject.com/en/4.2/ref/models/fields/#manytomanyfield) is used to specify a many-to-many relationship (e.g. a book can have several genres, and each genre can contain several books). In our library app we will use these very similarly to `ForeignKeys`, but they can be used in more complicated ways to describe the relationships between groups. These have the parameter `on_delete` to define what happens when the associated record is deleted (e.g. a value of `models.SET_NULL` would set the value to `NULL`).
+- [CharField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#django.db.models.CharField) is used to define short-to-mid sized fixed-length strings. You must specify the `max_length` of the data to be stored.
+- [TextField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#django.db.models.TextField) is used for large arbitrary-length strings. You may specify a `max_length` for the field, but this is used only when the field is displayed in forms (it is not enforced at the database level).
+- [IntegerField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#django.db.models.IntegerField) is a field for storing integer (whole number) values, and for validating entered values as integers in forms.
+- [DateField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#datefield) and [DateTimeField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#datetimefield) are used for storing/representing dates and date/time information (as Python `datetime.date` and `datetime.datetime` objects, respectively). These fields can additionally declare the (mutually exclusive) parameters `auto_now=True` (to set the field to the current date every time the model is saved), `auto_now_add` (to only set the date when the model is first created), and `default` (to set a default date that can be overridden by the user).
+- [EmailField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#emailfield) is used to store and validate email addresses.
+- [FileField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#filefield) and [ImageField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#imagefield) are used to upload files and images respectively (the `ImageField` adds additional validation that the uploaded file is an image). These have parameters to define how and where the uploaded files are stored.
+- [AutoField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#autofield) is a special type of `IntegerField` that automatically increments. A primary key of this type is automatically added to your model if you don't explicitly specify one.
+- [ForeignKey](https://docs.djangoproject.com/en/5.0/ref/models/fields/#foreignkey) is used to specify a one-to-many relationship to another database model (e.g. a car has one manufacturer, but a manufacturer can make many cars). The "one" side of the relationship is the model that contains the "key" (models containing a "foreign key" referring to that "key", are on the "many" side of such a relationship).
+- [ManyToManyField](https://docs.djangoproject.com/en/5.0/ref/models/fields/#manytomanyfield) is used to specify a many-to-many relationship (e.g. a book can have several genres, and each genre can contain several books). In our library app we will use these very similarly to `ForeignKeys`, but they can be used in more complicated ways to describe the relationships between groups. These have the parameter `on_delete` to define what happens when the associated record is deleted (e.g. a value of `models.SET_NULL` would set the value to `NULL`).
-There are many other types of fields, including fields for different types of numbers (big integers, small integers, floats), booleans, URLs, slugs, unique ids, and other "time-related" information (duration, time, etc.). You can view the [full list here](https://docs.djangoproject.com/en/4.2/ref/models/fields/#field-types).
+There are many other types of fields, including fields for different types of numbers (big integers, small integers, floats), booleans, URLs, slugs, unique ids, and other "time-related" information (duration, time, etc.). You can view the [full list here](https://docs.djangoproject.com/en/5.0/ref/models/fields/#field-types).
#### Metadata
@@ -179,11 +179,11 @@ Another common attribute is `verbose_name`, a verbose name for the class in sing
verbose_name = 'BetterName'
```
-Other useful attributes allow you to create and apply new "access permissions" for the model (default permissions are applied automatically), allow ordering based on another field, or to declare that the class is "abstract" (a base class that you cannot create records for, and will instead be derived from to create other models).
+Class metadata can be used to create and apply new "access permissions" for the model (default permissions are applied automatically), allow ordering based on another field, define [constraints](https://docs.djangoproject.com/en/5.0/ref/models/constraints) on possible values of data that can be stored, or to declare that the class is "abstract" (a base class that you cannot create records for, and will instead be derived from to create other models).
Many of the other metadata options control what database must be used for the model and how the data is stored (these are really only useful if you need to map a model to an existing database).
-The full list of metadata options are available here: [Model metadata options](https://docs.djangoproject.com/en/4.2/ref/models/options/) (Django docs).
+The full list of metadata options are available here: [Model metadata options](https://docs.djangoproject.com/en/5.0/ref/models/options/) (Django docs).
#### Methods
@@ -259,7 +259,7 @@ wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = wild_books.count()
```
-The fields to match and the type of match are defined in the filter parameter name, using the format: `field_name__match_type` (note the _double underscore_ between `title` and `contains` above). Above we're filtering `title` with a case-sensitive match. There are many other types of matches you can do: `icontains` (case insensitive), `iexact` (case-insensitive exact match), `exact` (case-sensitive exact match) and `in`, `gt` (greater than), `startswith`, etc. The [full list is here](https://docs.djangoproject.com/en/4.2/ref/models/querysets/#field-lookups).
+The fields to match and the type of match are defined in the filter parameter name, using the format: `field_name__match_type` (note the _double underscore_ between `title` and `contains` above). Above we're filtering `title` with a case-sensitive match. There are many other types of matches you can do: `icontains` (case insensitive), `iexact` (case-insensitive exact match), `exact` (case-sensitive exact match) and `in`, `gt` (greater than), `startswith`, etc. The [full list is here](https://docs.djangoproject.com/en/5.0/ref/models/querysets/#field-lookups).
In some cases, you'll need to filter on a field that defines a one-to-many relationship to another model (e.g. a `ForeignKey`). In this case, you can "index" to fields within the related model with additional double underscores.
So for example to filter for books with a specific genre pattern, you will have to index to the `name` through the `genre` field, as shown below:
@@ -272,11 +272,11 @@ books_containing_genre = Book.objects.filter(genre__name__icontains='fiction')
> **Note:** You can use underscores (`__`) to navigate as many levels of relationships (`ForeignKey`/`ManyToManyField`) as you like.
> For example, a `Book` that had different types, defined using a further "cover" relationship might have a parameter name: `type__cover__name__exact='hard'.`
-There is a lot more you can do with queries, including backwards searches from related models, chaining filters, returning a smaller set of values, etc. For more information, see [Making queries](https://docs.djangoproject.com/en/4.2/topics/db/queries/) (Django Docs).
+There is a lot more you can do with queries, including backwards searches from related models, chaining filters, returning a smaller set of values, etc. For more information, see [Making queries](https://docs.djangoproject.com/en/5.0/topics/db/queries/) (Django Docs).
## Defining the LocalLibrary Models
-In this section we will start defining the models for the library. Open `models.py` (in /locallibrary/catalog/). The boilerplate at the top of the page imports the _models_ module, which contains the model base class `models.Model` that our models will inherit from.
+In this section we will start defining the models for the library. Open `models.py` (in /django-locallibrary-tutorial/catalog/). The boilerplate at the top of the page imports the _models_ module, which contains the model base class `models.Model` that our models will inherit from.
```python
from django.db import models
@@ -290,7 +290,10 @@ Copy the `Genre` model code shown below and paste it into the bottom of your `mo
As mentioned above, we've created the genre as a model rather than as free text or a selection list so that the possible values can be managed through the database rather than being hard coded.
```python
-from django.urls import reverse # Used to generate URLs by reversing the URL patterns
+from django.urls import reverse # Used in get_absolute_url() to get URL for specified ID
+
+from django.db.models import UniqueConstraint # Constrains fields to unique values
+from django.db.models.functions import Lower # Returns lower cased value of field
class Genre(models.Model):
"""Model representing a book genre."""
@@ -307,13 +310,27 @@ class Genre(models.Model):
def get_absolute_url(self):
"""Returns the url to access a particular genre instance."""
return reverse('genre-detail', args=[str(self.id)])
+
+ class Meta:
+ constraints = [
+ UniqueConstraint(
+ Lower('name'),
+ name='genre_name_case_insensitive_unique',
+ violation_error_message = "Genre already exists (case insensitive match)"
+ ),
+ ]
```
The model has a single `CharField` field (`name`), which is used to describe the genre (this is limited to 200 characters and has some `help_text`).
We've set this field to be unique (`unique=True`) because there should only be one record for each genre.
-After the field, we declare a `__str__()` method, which returns the name of the genre defined by a particular record. No verbose name has been defined, so the field will be called `Name` in forms.
-The final method, `get_absolute_url()` returns a URL that can be used to access a detail record for this model (for this to work, we will have to define a URL mapping that has the name `genre-detail`, and define an associated view and template).
+After the field, we declare a `__str__()` method, which returns the name of the genre defined by a particular record. No verbose name has been defined, so the field label will be `Name` when it is used in forms.
+Then we declare the `get_absolute_url()` method, which returns a URL that can be used to access a detail record for this model (for this to work, we will have to define a URL mapping that has the name `genre-detail`, and define an associated view and template).
+
+Setting `unique=True` on the field above prevents genres being created with _exactly_ the same name, but not variations such as "fantasy", "Fantasy", or even "FaNtAsY".
+The last part of the model definition uses a [`constraints`](https://docs.djangoproject.com/en/5.0/ref/models/options/#constraints) option on the model's [metadata](#metadata) to specify that the lower case of the value in the `name` field must be unique in the database, and display the `violation_error_message` string if it isn't.
+Here we don't need to do anything else, but you can define multiple constrainst a field or fields.
+For more information see the [Constraints reference](https://docs.djangoproject.com/en/5.0/ref/models/constraints), including [`UniqueConstraint()`](https://docs.djangoproject.com/en/5.0/ref/models/constraints/#uniqueconstraint) (and [`Lower()`](https://docs.djangoproject.com/en/5.0/ref/models/database-functions/#lower)).
### Book model
@@ -480,8 +497,8 @@ At this point we'll divert briefly from creating the site, and check out the _Dj
## See also
-- [Writing your first Django app, part 2](https://docs.djangoproject.com/en/4.2/intro/tutorial02/) (Django docs)
-- [Making queries](https://docs.djangoproject.com/en/4.2/topics/db/queries/) (Django Docs)
-- [QuerySet API Reference](https://docs.djangoproject.com/en/4.2/ref/models/querysets/) (Django Docs)
+- [Writing your first Django app, part 2](https://docs.djangoproject.com/en/5.0/intro/tutorial02/) (Django docs)
+- [Making queries](https://docs.djangoproject.com/en/5.0/topics/db/queries/) (Django Docs)
+- [QuerySet API Reference](https://docs.djangoproject.com/en/5.0/ref/models/querysets/) (Django Docs)
{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/sessions/index.md b/files/en-us/learn/server-side/django/sessions/index.md
index c9bbf3164afb109..ce24d70c576c63b 100644
--- a/files/en-us/learn/server-side/django/sessions/index.md
+++ b/files/en-us/learn/server-side/django/sessions/index.md
@@ -48,7 +48,7 @@ Django uses a cookie containing a special _session id_ to identify each browser
Sessions were enabled automatically when we [created the skeleton website](/en-US/docs/Learn/Server-side/Django/skeleton_website) (in tutorial 2).
-The configuration is set up in the `INSTALLED_APPS` and `MIDDLEWARE` sections of the project file (**locallibrary/locallibrary/settings.py**), as shown below:
+The configuration is set up in the `INSTALLED_APPS` and `MIDDLEWARE` sections of the project file (**django-locallibrary-tutorial/locallibrary/settings.py**), as shown below:
```python
INSTALLED_APPS = [
@@ -87,7 +87,7 @@ request.session['my_car'] = 'mini'
del request.session['my_car']
```
-The API also offers a number of other methods that are mostly used to manage the associated session cookie. For example, there are methods to test that cookies are supported in the client browser, to set and check cookie expiry dates, and to clear expired sessions from the data store. You can find out about the full API in [How to use sessions](https://docs.djangoproject.com/en/4.2/topics/http/sessions/) (Django docs).
+The API also offers a number of other methods that are mostly used to manage the associated session cookie. For example, there are methods to test that cookies are supported in the client browser, to set and check cookie expiry dates, and to clear expired sessions from the data store. You can find out about the full API in [How to use sessions](https://docs.djangoproject.com/en/5.0/topics/http/sessions/) (Django docs).
## Saving session data
@@ -108,13 +108,13 @@ request.session['my_car']['wheels'] = 'alloy'
request.session.modified = True
```
-> **Note:** You can change the behavior so the site will update the database/send cookie on every request by adding `SESSION_SAVE_EVERY_REQUEST = True` into your project settings (**locallibrary/locallibrary/settings.py**).
+> **Note:** You can change the behavior so the site will update the database/send cookie on every request by adding `SESSION_SAVE_EVERY_REQUEST = True` into your project settings (**django-locallibrary-tutorial/locallibrary/settings.py**).
## Simple example — getting visit counts
As a simple real-world example we'll update our library to tell the current user how many times they have visited the _LocalLibrary_ home page.
-Open **/locallibrary/catalog/views.py**, and add the lines that contain `num_visits` into `index()` (as shown below).
+Open **/django-locallibrary-tutorial/catalog/views.py**, and add the lines that contain `num_visits` into `index()` (as shown below).
```python
def index(request):
@@ -140,9 +140,9 @@ def index(request):
Here we first get the value of the `'num_visits'` session key, setting the value to 0 if it has not previously been set. Each time a request is received, we then increment the value and store it back in the session (for the next time the user visits the page). The `num_visits` variable is then passed to the template in our context variable.
-> **Note:** We might also test whether cookies are even supported in the browser here (see [How to use sessions](https://docs.djangoproject.com/en/4.2/topics/http/sessions/) for examples) or design our UI so that it doesn't matter whether or not cookies are supported.
+> **Note:** We might also test whether cookies are even supported in the browser here (see [How to use sessions](https://docs.djangoproject.com/en/5.0/topics/http/sessions/) for examples) or design our UI so that it doesn't matter whether or not cookies are supported.
-Add the line shown at the bottom of the following block to your main HTML template (**/locallibrary/catalog/templates/index.html**) at the bottom of the "Dynamic content" section to display the `num_visits` context variable.
+Add the line shown at the bottom of the following block to your main HTML template (**/django-locallibrary-tutorial/catalog/templates/index.html**) at the bottom of the "Dynamic content" section to display the `num_visits` context variable.
```django
Dynamic content
@@ -160,7 +160,7 @@ Add the line shown at the bottom of the following block to your main HTML templa
```
-Note that we use the Django built-in template tag [pluralize](https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#pluralize) to add an "s" when the page has been visited multiple time**s**.
+Note that we use the Django built-in template tag [pluralize](https://docs.djangoproject.com/en/5.0/ref/templates/builtins/#pluralize) to add an "s" when the page has been visited multiple time**s**.
Save your changes and restart the test server. Every time you refresh the page, the number should update.
@@ -172,6 +172,6 @@ In our next articles we'll explain the authentication and authorization (permiss
## See also
-- [How to use sessions](https://docs.djangoproject.com/en/4.2/topics/http/sessions/) (Django docs)
+- [How to use sessions](https://docs.djangoproject.com/en/5.0/topics/http/sessions/) (Django docs)
{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/Authentication", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/skeleton_website/index.md b/files/en-us/learn/server-side/django/skeleton_website/index.md
index 9e1d5fc58db69e7..2e3ceb3765c3a3c 100644
--- a/files/en-us/learn/server-side/django/skeleton_website/index.md
+++ b/files/en-us/learn/server-side/django/skeleton_website/index.md
@@ -58,33 +58,26 @@ At the end of this article, we discuss other site-wide configuration you might a
To create the project:
1. Open a command shell (or a terminal window), and make sure you are in your [virtual environment](/en-US/docs/Learn/Server-side/Django/development_environment#using_a_virtual_environment).
-2. Navigate to the folder where you want to store your local library application.
- This should be the folder named "django_local_library" that you [created as a local Github repository](/en-US/docs/Learn/Server-side/Django/development_environment#clone_the_repo_to_your_local_computer) when setting up the development environment.
-3. Create the new project using the `django-admin startproject` command as shown, and then change into the project folder:
+2. Navigate to the folder where you want to create your local library application (later on we'll move it to the "django_local_library" that you [created as a local Github repository](/en-US/docs/Learn/Server-side/Django/development_environment#clone_the_repo_to_your_local_computer) when setting up the development environment).
+3. Create the new project using the `django-admin startproject` command as shown, and then navigate into the project folder:
```bash
django-admin startproject locallibrary
cd locallibrary
```
-The `django-admin` tool creates a folder/file structure as follows:
+ The `django-admin` tool creates a folder/file structure as follows:
-```bash
-locallibrary/
- manage.py
- locallibrary/
- __init__.py
- settings.py
- urls.py
- wsgi.py
- asgi.py
-```
-
-Our current working directory should look something like this:
-
-```bash
-../django_local_library/locallibrary/
-```
+ ```bash
+ locallibrary/
+ manage.py
+ locallibrary/
+ __init__.py
+ settings.py
+ urls.py
+ wsgi.py
+ asgi.py
+ ```
The _locallibrary_ project sub-folder is the entry point for the website:
@@ -141,7 +134,7 @@ In addition we now have:
Now that the application has been created, we have to register it with the project so that it will be included when any tools are run (like adding models to the database for example). Applications are registered by adding them to the `INSTALLED_APPS` list in the project settings.
-Open the project settings file, **django_projects/locallibrary/locallibrary/settings.py**, and find the definition for the `INSTALLED_APPS` list. Then add a new line at the end of the list, as shown below:
+Open the project settings file, **django-locallibrary-tutorial/locallibrary/settings.py**, and find the definition for the `INSTALLED_APPS` list. Then add a new line at the end of the list, as shown below:
```bash
INSTALLED_APPS = [
@@ -152,19 +145,19 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
# Add our new application
- 'catalog.apps.CatalogConfig', #This object was created for us in /catalog/apps.py
+ 'catalog.apps.CatalogConfig', # This object was created for us in /catalog/apps.py
]
```
-The new line specifies the application configuration object (`CatalogConfig`) that was generated for you in **/locallibrary/catalog/apps.py** when you created the application.
+The new line specifies the application configuration object (`CatalogConfig`) that was generated for you in **/django-locallibrary-tutorial/catalog/apps.py** when you created the application.
> **Note:** You'll notice that there are already a lot of other `INSTALLED_APPS` (and `MIDDLEWARE`, further down in the settings file). These enable support for the [Django administration site](/en-US/docs/Learn/Server-side/Django/Admin_site) and the functionality it uses (including sessions, authentication, etc.).
## Specifying the database
-This is also the point where you would normally specify the database to be used for the project. It makes sense to use the same database for development and production where possible, in order to avoid minor differences in behavior. You can find out about the different options in [Databases](https://docs.djangoproject.com/en/4.2/ref/settings/#databases) (Django docs).
+This is also the point where you would normally specify the database to be used for the project. It makes sense to use the same database for development and production where possible, in order to avoid minor differences in behavior. You can find out about the different options in [Databases](https://docs.djangoproject.com/en/5.0/ref/settings/#databases) (Django docs).
-We'll use the default SQLite database for this example, because we don't expect to require a lot of concurrent access on a demonstration database, and it requires no additional work to set up! You can see how this database is configured in **settings.py**:
+We'll use the default SQLite database for most of this example, because we don't expect to require a lot of concurrent access on a demonstration database, and it requires no additional work to set up! You can see how this database is configured in **settings.py**:
```python
DATABASES = {
@@ -175,11 +168,11 @@ DATABASES = {
}
```
-Because we are using SQLite, we don't need to do any further setup here. Let's move on!
+Later on in the [Deploying Django to production](/en-US/docs/Learn/Server-side/Django/Deployment#database_configuration) we'll also show you how to configure a Postgres database, which might be more suitable for larger sites.
## Other project settings
-The **settings.py** file is also used for configuring a number of other settings, but at this point, you probably only want to change the [TIME_ZONE](https://docs.djangoproject.com/en/4.2/ref/settings/#std:setting-TIME_ZONE) — this should be made equal to a string from the standard [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (the TZ column in the table contains the values you want). Change your `TIME_ZONE` value to one of these strings appropriate for your time zone, for example:
+The **settings.py** file is also used for configuring a number of other settings, but at this point, you probably only want to change the [TIME_ZONE](https://docs.djangoproject.com/en/5.0/ref/settings/#std:setting-TIME_ZONE) — this should be made equal to a string from the standard [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (the TZ column in the table contains the values you want). Change your `TIME_ZONE` value to one of these strings appropriate for your time zone, for example:
```python
TIME_ZONE = 'Europe/London'
@@ -194,14 +187,14 @@ There are two other settings you won't change now, but that you should be aware
The website is created with a URL mapper file (**urls.py**) in the project folder. While you can use this file to manage all your URL mappings, it is more usual to defer mappings to the associated application.
-Open **locallibrary/locallibrary/urls.py** and note the instructional text which explains some of the ways to use the URL mapper.
+Open **django-locallibrary-tutorial/locallibrary/urls.py** and note the instructional text which explains some of the ways to use the URL mapper.
```python
"""
URL configuration for locallibrary project.
The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/4.2/topics/http/urls/
+ https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
@@ -243,7 +236,7 @@ Now let's redirect the root URL of our site (i.e. `127.0.0.1:8000`) to the URL `
Add the following lines to the bottom of the file:
```python
-#Add URL maps to redirect the base URL to our application
+# Add URL maps to redirect the base URL to our application
from django.views.generic import RedirectView
urlpatterns += [
path('', RedirectView.as_view(url='catalog/', permanent=True)),
@@ -283,7 +276,7 @@ urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
> ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
> ```
-As a final step, create a file inside your catalog folder called **urls.py**, and add the following text to define the (empty) imported `urlpatterns`. This is where we'll add our patterns as we build the application.
+As a final step, create a file inside your _catalog_ folder called **urls.py**, and add the following text to define the (empty) imported `urlpatterns`. This is where we'll add our patterns as we build the application.
```python
from django.urls import path
@@ -302,7 +295,7 @@ Before we do that, we should first run a _database migration_. This updates our
### Running database migrations
-Django uses an Object-Relational-Mapper (ORM) to map model definitions in the Django code to the data structure used by the underlying database. As we change our model definitions, Django tracks the changes and can create database migration scripts (in **/locallibrary/catalog/migrations/**) to automatically migrate the underlying data structure in the database to match the model.
+Django uses an Object-Relational-Mapper (ORM) to map model definitions in the Django code to the data structure used by the underlying database. As we change our model definitions, Django tracks the changes and can create database migration scripts (in **/django-locallibrary-tutorial/catalog/migrations/**) to automatically migrate the underlying data structure in the database to match the model.
When we created the website, Django automatically added a number of models for use by the admin section of the site (which we'll look at later). Run the following commands to define tables for those models in the database (make sure you are in the directory that contains **manage.py**):
@@ -317,13 +310,15 @@ The `makemigrations` command _creates_ (but does not apply) the migrations for a
The `migrate` command is what applies the migrations to your database. Django tracks which ones have been added to the current database.
-> **Note:** See [Migrations](https://docs.djangoproject.com/en/4.2/topics/migrations/) (Django docs) for additional information about the lesser-used migration commands.
+> **Note:** You should re-run migrations and re-test the site whenever you make significant changes. It doesn't take very long!
+>
+> See [Migrations](https://docs.djangoproject.com/en/5.0/topics/migrations/) (Django docs) for additional information about the lesser-used migration commands.
### Running the website
During development, you can serve the website first using the _development web server_, and then viewing it on your local web browser.
-> **Note:** The development web server is not robust or performant enough for production use, but it is a very easy way to get your Django website up and running during development to give it a convenient quick test. By default it will serve the site to your local computer (`http://127.0.0.1:8000/)`, but you can also specify other computers on your network to serve to. For more information see [django-admin and manage.py: runserver](https://docs.djangoproject.com/en/4.2/ref/django-admin/#runserver) (Django docs).
+> **Note:** The development web server is not robust or performant enough for production use, but it is a very easy way to get your Django website up and running during development to give it a convenient quick test. By default it will serve the site to your local computer (`http://127.0.0.1:8000/)`, but you can also specify other computers on your network to serve to. For more information see [django-admin and manage.py: runserver](https://docs.djangoproject.com/en/5.0/ref/django-admin/#runserver) (Django docs).
Run the _development web server_ by calling the `runserver` command (in the same directory as **manage.py**):
@@ -337,28 +332,45 @@ Once the server is running, you can view the site by navigating to `http://127.0
Don't worry! This error page is expected because we don't have any pages/urls defined in the `catalog.urls` module (which we're redirected to when we get a URL to the root of the site).
-> **Note:** The example page demonstrates a great Django feature — automated debug logging. Whenever a page cannot be found, Django displays an error screen with useful information or any error raised by the code. In this case, we can see that the URL we've supplied doesn't match any of our URL patterns (as listed). Logging is turned off in production (which is when we put the site live on the Web), in which case a less informative but more user-friendly page will be served.
-
At this point, we know that Django is working!
-> **Note:** You should re-run migrations and re-test the site whenever you make significant changes. It doesn't take very long!
+> **Note:** The example page demonstrates a great Django feature — automated debug logging. Whenever a page cannot be found, Django displays an error screen with useful information or any error raised by the code. In this case, we can see that the URL we've supplied doesn't match any of our URL patterns (as listed). Logging is turned off in production (which is when we put the site live on the Web), in which case a less informative but more user-friendly page will be served.
## Don't forget to backup to Github
-We've just done some significant work, so now is a good time to backup the project.
-You can use a similar set of commands to those in the [Modify and sync changes](/en-US/docs/Learn/Server-side/Django/development_environment#modify_and_sync_changes) section of the _Development environment_ topic:
+We've just done some significant work, so now is a good time to backup the project using GitHub.
+
+First move the _content_ of the top level **locallibrary** folder into the **django_local_library** folder that you [created as a local Github repository](/en-US/docs/Learn/Server-side/Django/development_environment#clone_the_repo_to_your_local_computer) when setting up the development environment.
+This will include **manage.py**, the **locallibrary** subfolder, the **catalog** subfolder, and anything else inside the top level folder.
+
+Then add and commit the changes in the **django_local_library** folder and push them to GitHub.
+From the root of that folder, you can use a similar set of commands to those in the [Modify and sync changes](/en-US/docs/Learn/Server-side/Django/development_environment#modify_and_sync_changes) section of the _Development environment_ topic:
```bash
+# Get the current source from GitHub on the main branch
+git checkout main
+git pull origin main
+
+# Create a branch and add/commit your newly created app skeleton
git checkout -b skeleton_website # Create and activate a new branch "skeleton_website"
git add -A # Add all changed files to the staging area
git commit -m "Create Skeleton framework for LocalLibrary" # Commit the changed files
-git push origin skeleton_website # Push the branch to GitHub
+
+# Push the branch to GitHub
+git push origin skeleton_website
+```
+
+Then create and merge a PR from your GitHub repo.
+After merging you can switch back to the `main` branch and pull your changes from GitHub:
+
+```bash
+git checkout main
+git pull origin main
```
-The create and merge a PR from your GitHub repo.
-Note that if you don't delete the `skeleton_website` branch you can always switch back to it at some later point.
+> **Note:** If you don't delete the `skeleton_website` branch you can always switch back to it at some later point.
-We won't necessarily mention this in future, but you may find it useful to create new branches at the end of each section in this tutorial.
+We won't necessarily mention this again in future, but you may find it useful to update GitHub with your changes at the end of each section in this tutorial.
## Challenge yourself
@@ -374,8 +386,8 @@ Now that the skeleton for the [Local Library website](/en-US/docs/Learn/Server-s
## See also
-- [Writing your first Django app - part 1](https://docs.djangoproject.com/en/4.2/intro/tutorial01/) (Django docs)
-- [Applications](https://docs.djangoproject.com/en/4.2/ref/applications/#configuring-applications) (Django Docs).
+- [Writing your first Django app - part 1](https://docs.djangoproject.com/en/5.0/intro/tutorial01/) (Django docs)
+- [Applications](https://docs.djangoproject.com/en/5.0/ref/applications/#configuring-applications) (Django Docs).
Contains information on configuring applications.
{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}
diff --git a/files/en-us/learn/server-side/django/testing/index.md b/files/en-us/learn/server-side/django/testing/index.md
index 92b53835c66315a..0984fefe99d03cc 100644
--- a/files/en-us/learn/server-side/django/testing/index.md
+++ b/files/en-us/learn/server-side/django/testing/index.md
@@ -50,9 +50,9 @@ There are numerous types, levels, and classifications of tests and testing appro
Testing a website is a complex task, because it is made of several layers of logic – from HTTP-level request handling, to model queries, to form validation and processing, and template rendering.
-Django provides a test framework with a small hierarchy of classes that build on the Python standard [`unittest`](https://docs.python.org/3/library/unittest.html#module-unittest) library. Despite the name, this test framework is suitable for both unit and integration tests. The Django framework adds API methods and tools to help test web and Django-specific behavior. These allow you to simulate requests, insert test data, and inspect your application's output. Django also provides an API ([LiveServerTestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#liveservertestcase)) and tools for [using different testing frameworks](https://docs.djangoproject.com/en/4.2/topics/testing/advanced/#other-testing-frameworks), for example you can integrate with the popular [Selenium](/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment) framework to simulate a user interacting with a live browser.
+Django provides a test framework with a small hierarchy of classes that build on the Python standard [`unittest`](https://docs.python.org/3/library/unittest.html#module-unittest) library. Despite the name, this test framework is suitable for both unit and integration tests. The Django framework adds API methods and tools to help test web and Django-specific behavior. These allow you to simulate requests, insert test data, and inspect your application's output. Django also provides an API ([LiveServerTestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#liveservertestcase)) and tools for [using different testing frameworks](https://docs.djangoproject.com/en/5.0/topics/testing/advanced/#other-testing-frameworks), for example you can integrate with the popular [Selenium](/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment) framework to simulate a user interacting with a live browser.
-To write a test you derive from any of the Django (or _unittest_) test base classes ([SimpleTestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#simpletestcase), [TransactionTestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#transactiontestcase), [TestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#testcase), [LiveServerTestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#liveservertestcase)) and then write separate methods to check that specific functionality works as expected (tests use "assert" methods to test that expressions result in `True` or `False` values, or that two values are equal, etc.) When you start a test run, the framework executes the chosen test methods in your derived classes. The test methods are run independently, with common setup and/or tear-down behavior defined in the class, as shown below.
+To write a test you derive from any of the Django (or _unittest_) test base classes ([SimpleTestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#simpletestcase), [TransactionTestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#transactiontestcase), [TestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#testcase), [LiveServerTestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#liveservertestcase)) and then write separate methods to check that specific functionality works as expected (tests use "assert" methods to test that expressions result in `True` or `False` values, or that two values are equal, etc.) When you start a test run, the framework executes the chosen test methods in your derived classes. The test methods are run independently, with common setup and/or tear-down behavior defined in the class, as shown below.
```python
class YourTestClass(TestCase):
@@ -71,9 +71,9 @@ class YourTestClass(TestCase):
self.assertTrue(False)
```
-The best base class for most tests is [django.test.TestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#testcase). This test class creates a clean database before its tests are run, and runs every test function in its own transaction. The class also owns a test [Client](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#django.test.Client) that you can use to simulate a user interacting with the code at the view level. In the following sections we're going to concentrate on unit tests, created using this [TestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#testcase) base class.
+The best base class for most tests is [django.test.TestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#testcase). This test class creates a clean database before its tests are run, and runs every test function in its own transaction. The class also owns a test [Client](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#django.test.Client) that you can use to simulate a user interacting with the code at the view level. In the following sections we're going to concentrate on unit tests, created using this [TestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#testcase) base class.
-> **Note:** The [django.test.TestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#testcase) class is very convenient, but may result in some tests being slower than they need to be (not every test will need to set up its own database or simulate the view interaction). Once you're familiar with what you can do with this class, you may want to replace some of your tests with the available simpler test classes.
+> **Note:** The [django.test.TestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#testcase) class is very convenient, but may result in some tests being slower than they need to be (not every test will need to set up its own database or simulate the view interaction). Once you're familiar with what you can do with this class, you may want to replace some of your tests with the available simpler test classes.
### What should you test?
@@ -170,7 +170,7 @@ The new class defines two methods that you can use for pre-test configuration (f
Below those we have a number of test methods, which use `Assert` functions to test whether conditions are true, false or equal (`AssertTrue`, `AssertFalse`, `AssertEqual`). If the condition does not evaluate as expected then the test will fail and report the error to your console.
-The `AssertTrue`, `AssertFalse`, `AssertEqual` are standard assertions provided by **unittest**. There are other standard assertions in the framework, and also [Django-specific assertions](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#assertions) to test if a view redirects (`assertRedirects`), to test if a particular template has been used (`assertTemplateUsed`), etc.
+The `AssertTrue`, `AssertFalse`, `AssertEqual` are standard assertions provided by **unittest**. There are other standard assertions in the framework, and also [Django-specific assertions](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#assertions) to test if a view redirects (`assertRedirects`), to test if a particular template has been used (`assertTemplateUsed`), etc.
> **Note:** You should **not** normally include **print()** functions in your tests as shown above. We do that here only so that you can see the order that the setup functions are called in the console (in the following section).
@@ -184,7 +184,7 @@ python3 manage.py test
This will discover all files named with the pattern **test\*.py** under the current directory and run all tests defined using appropriate base classes (here we have a number of test files, but only **/catalog/tests/test_models.py** currently contains any tests.) By default the tests will individually report only on test failures, followed by a test summary.
-> **Note:** If you get errors similar to: `ValueError: Missing staticfiles manifest entry...` this may be because testing does not run _collectstatic_ by default, and your app is using a storage class that requires it (see [manifest_strict](https://docs.djangoproject.com/en/4.2/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict) for more information). There are a number of ways you can overcome this problem - the easiest is to run _collectstatic_ before running the tests:
+> **Note:** If you get errors similar to: `ValueError: Missing staticfiles manifest entry...` this may be because testing does not run _collectstatic_ by default, and your app is using a storage class that requires it (see [manifest_strict](https://docs.djangoproject.com/en/5.0/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict) for more information). There are a number of ways you can overcome this problem - the easiest is to run _collectstatic_ before running the tests:
>
> ```bash
> python3 manage.py collectstatic
@@ -248,7 +248,7 @@ The `auto` is optional, and you can also specify a particular number of cores to
python3 manage.py test --parallel auto
```
-For more information, including what to do if your tests are not independent, see [DJANGO_TEST_PROCESSES](https://docs.djangoproject.com/en/4.2/ref/django-admin/#envvar-DJANGO_TEST_PROCESSES).
+For more information, including what to do if your tests are not independent, see [DJANGO_TEST_PROCESSES](https://docs.djangoproject.com/en/5.0/ref/django-admin/#envvar-DJANGO_TEST_PROCESSES).
### Running specific tests
@@ -271,7 +271,7 @@ python3 manage.py test catalog.tests.test_models.YourTestClass.test_one_plus_one
### Other test runner options
The test runner provides many other options, including the ability to shuffle tests (`--shuffle`), run them in debug mode (`--debug-mode`), and use the Python logger to capture the results.
-For more information see the Django [test runner](https://docs.djangoproject.com/en/4.2/ref/django-admin/#test) documentation.
+For more information see the Django [test runner](https://docs.djangoproject.com/en/5.0/ref/django-admin/#test) documentation.
## LocalLibrary tests
@@ -468,7 +468,7 @@ The first two functions test that the field's `label` and `help_text` are as exp
The rest of the functions test that the form is valid for renewal dates just inside the acceptable range and invalid for values outside the range. Note how we construct test date values around our current date (`datetime.date.today()`) using `datetime.timedelta()` (in this case specifying a number of days or weeks). We then just create the form, passing in our data, and test if it is valid.
-> **Note:** Here we don't actually use the database or test client. Consider modifying these tests to use [SimpleTestCase](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#django.test.SimpleTestCase).
+> **Note:** Here we don't actually use the database or test client. Consider modifying these tests to use [SimpleTestCase](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#django.test.SimpleTestCase).
>
> We also need to validate that the correct errors are raised if the form is invalid, however this is usually done as part of view processing, so we'll take care of that in the next section.
@@ -478,7 +478,7 @@ That's all for forms; we do have some others, but they are automatically created
### Views
-To validate our view behavior we use the Django test [Client](https://docs.djangoproject.com/en/4.2/topics/testing/tools/#django.test.Client). This class acts like a dummy web browser that we can use to simulate `GET` and `POST` requests on a URL and observe the response. We can see almost everything about the response, from low-level HTTP (result headers and status codes) through to the template we're using to render the HTML and the context data we're passing to it. We can also see the chain of redirects (if any) and check the URL and status code at each step. This allows us to verify that each view is doing what is expected.
+To validate our view behavior we use the Django test [Client](https://docs.djangoproject.com/en/5.0/topics/testing/tools/#django.test.Client). This class acts like a dummy web browser that we can use to simulate `GET` and `POST` requests on a URL and observe the response. We can see almost everything about the response, from low-level HTTP (result headers and status codes) through to the template we're using to render the HTML and the context data we're passing to it. We can also see the chain of redirects (if any) and check the URL and status code at each step. This allows us to verify that each view is doing what is expected.
Let's start with one of our simplest views, which provides a list of all Authors. This is displayed at URL **/catalog/authors/** (a URL named 'authors' in the URL configuration).
@@ -969,10 +969,10 @@ The next and final tutorial shows how you can deploy your wonderful (and fully t
## See also
-- [Writing and running tests](https://docs.djangoproject.com/en/4.2/topics/testing/overview/) (Django docs)
-- [Writing your first Django app, part 5 > Introducing automated testing](https://docs.djangoproject.com/en/4.2/intro/tutorial05/) (Django docs)
-- [Testing tools reference](https://docs.djangoproject.com/en/4.2/topics/testing/tools/) (Django docs)
-- [Advanced testing topics](https://docs.djangoproject.com/en/4.2/topics/testing/advanced/) (Django docs)
+- [Writing and running tests](https://docs.djangoproject.com/en/5.0/topics/testing/overview/) (Django docs)
+- [Writing your first Django app, part 5 > Introducing automated testing](https://docs.djangoproject.com/en/5.0/intro/tutorial05/) (Django docs)
+- [Testing tools reference](https://docs.djangoproject.com/en/5.0/topics/testing/tools/) (Django docs)
+- [Advanced testing topics](https://docs.djangoproject.com/en/5.0/topics/testing/advanced/) (Django docs)
- [A Guide to Testing in Django](https://toastdriven.com/blog/2011/apr/09/guide-to-testing-in-django/) (Toast Driven Blog, 2011)
- [Workshop: Test-Driven Web Development with Django](https://test-driven-django-development.readthedocs.io/en/latest/index.html) (San Diego Python, 2014)
- [Testing in Django (Part 1) - Best Practices and Examples](https://realpython.com/testing-in-django-part-1-best-practices-and-examples/) (RealPython, 2013)
diff --git a/files/en-us/learn/server-side/django/web_application_security/index.md b/files/en-us/learn/server-side/django/web_application_security/index.md
index 6e8f35e6c50c7da..4ad14aba121eee6 100644
--- a/files/en-us/learn/server-side/django/web_application_security/index.md
+++ b/files/en-us/learn/server-side/django/web_application_security/index.md
@@ -32,7 +32,7 @@ The [Website security](/en-US/docs/Web/Security) topic provides an overview of w
> **Warning:** The single most important lesson you can learn about website security is to **never trust data from the browser**. This includes `GET` request data in URL parameters, `POST` data, HTTP headers and cookies, user-uploaded files, etc. Always check and sanitize all incoming data. Always assume the worst.
-The good news for Django users is that many of the more common threats are handled by the framework! The [Security in Django](https://docs.djangoproject.com/en/4.2/topics/security/) (Django docs) article explains Django's security features and how to secure a Django-powered website.
+The good news for Django users is that many of the more common threats are handled by the framework! The [Security in Django](https://docs.djangoproject.com/en/5.0/topics/security/) (Django docs) article explains Django's security features and how to secure a Django-powered website.
## Common threats/protections
@@ -42,7 +42,7 @@ Rather than duplicate the Django documentation here, in this article we'll demon
XSS is a term used to describe a class of attacks that allow an attacker to inject client-side scripts _through_ the website into the browsers of other users. This is usually achieved by storing malicious scripts in the database where they can be retrieved and displayed to other users, or by getting users to click a link that will cause the attacker's JavaScript to be executed by the user's browser.
-Django's template system protects you against the majority of XSS attacks by [escaping specific characters](https://docs.djangoproject.com/en/4.2/ref/templates/language/#automatic-html-escaping) that are "dangerous" in HTML. We can demonstrate this by attempting to inject some JavaScript into our LocalLibrary website using the Create-author form we set up in [Django Tutorial Part 9: Working with forms](/en-US/docs/Learn/Server-side/Django/Forms).
+Django's template system protects you against the majority of XSS attacks by [escaping specific characters](https://docs.djangoproject.com/en/5.0/ref/templates/language/#automatic-html-escaping) that are "dangerous" in HTML. We can demonstrate this by attempting to inject some JavaScript into our LocalLibrary website using the Create-author form we set up in [Django Tutorial Part 9: Working with forms](/en-US/docs/Learn/Server-side/Django/Forms).
1. Start the website using the development server (`python3 manage.py runserver`).
2. Open the site in your local browser and login to your superuser account.
@@ -161,12 +161,12 @@ Django also provides other forms of protection (most of which would be hard or n
- : In this attack a malicious user hijacks clicks meant for a visible top level site and routes them to a hidden page beneath. This technique might be used, for example, to display a legitimate bank site but capture the login credentials in an invisible [`