Skip to content

Commit

Permalink
Bootstrap, logout form, fixes for url to django-githubrepo base
Browse files Browse the repository at this point in the history
  • Loading branch information
hamishwillee committed Feb 26, 2024
1 parent e282940 commit a850dc0
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 59 deletions.
4 changes: 2 additions & 2 deletions files/en-us/learn/server-side/django/admin_site/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ After registering the models we'll show how to create a new "superuser", login t

## 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
Expand Down Expand Up @@ -144,7 +144,7 @@ You can find a complete reference of all the admin site customization choices in

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)
Expand Down
73 changes: 48 additions & 25 deletions files/en-us/learn/server-side/django/authentication/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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)
Expand All @@ -155,7 +155,7 @@ 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.
Django will show an error that it could not find a mapping for this URL, and list all the URLs it tried.
From this you can see the URLs that will work, for example:

> **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.
Expand All @@ -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

Expand All @@ -190,15 +190,15 @@ 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/
> registration/
> ```

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).

Expand All @@ -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" %}
Expand Down Expand Up @@ -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/)
Expand All @@ -283,7 +283,7 @@ LOGIN_REDIRECT_URL = '/'

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).

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" %}
Expand All @@ -306,7 +306,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" %}
Expand All @@ -325,7 +325,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" %}
Expand All @@ -337,7 +337,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:
Expand All @@ -346,7 +346,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" %}
Expand Down Expand Up @@ -382,7 +382,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" %}
Expand All @@ -397,13 +397,11 @@ This is the last password-reset template, which is displayed to notify you when

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/`

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
Expand All @@ -422,7 +420,7 @@ 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
<ul class="sidebar-nav">
Expand All @@ -431,7 +429,12 @@ Open the base template (**/locallibrary/catalog/templates/base_generic.html**) a

{% if user.is_authenticated %}
<li>User: \{{ user.get_username }}</li>
<li><a href="{% url 'logout' %}?next=\{{ request.path }}">Logout</a></li>
<li>
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
{% csrf_token %}
<button type="submit" class="btn btn-link">Logout</button>
</form>
</li>
{% else %}
<li><a href="{% url 'login' %}?next=\{{ request.path }}">Login</a></li>
{% endif %}
Expand All @@ -440,9 +443,24 @@ Open the base template (**/locallibrary/catalog/templates/base_generic.html**) a

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"`.
We 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.
> **Note:** Try it out by clicking Login/Logout in the sidebar.

### Testing in views

Expand Down Expand Up @@ -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
<ul class="sidebar-nav">
Expand All @@ -647,7 +665,12 @@ Open the base template (**/locallibrary/catalog/templates/base_generic.html**) a
<li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li>
<li><a href="{% url 'logout' %}?next=\{{ request.path }}">Logout</a></li>
<li>
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
{% csrf_token %}
<button type="submit" class="btn btn-link">Logout</button>
</form>
</li>
{% else %}
<li><a href="{% url 'login' %}?next=\{{ request.path }}">Login</a></li>
{% endif %}
Expand Down
Loading

0 comments on commit a850dc0

Please sign in to comment.