Содержание
Восьмое занятие по веб-програмированию с python 3, посвященное Django. Django — гораздо более тяжелый веб-фреймворк, чем Flask, с гораздо большим количеством готовых функций, которые пришлось бы создавать вручную и многократно с помощью микро-фреймворка, например, такого как Flask.
Используя Django
Django делит все свои веб-приложения на «проекты», состоящие из разных частей. Чтобы начать новый проект, запустите django-admin startproject projectname
.
Компоненты проекта
Джанго создает ряд файлов с новым проектом:
__init__.py
: определяет каталогprojectname
как «пакет» Python, набор из нескольких файлов Python- Django построен на идее пакетов. Веб-приложение может состоять из нескольких пакетов, каждый из которых выполняет несколько разные задачи, и Django поможет управлять ими.
manage.py
: скрипт Python, который можно использовать для выполнения полезных операций в веб-приложенииsettings.py
: основные настройки, такие как часовой пояс, другие приложения, установленные в проекте, какая база данных используется и т. д.urls.py
: определяет, какие URL / маршруты могут быть доступны при использовании веб-приложенияwsgi.py
: файл, который помогает развернуть приложение на веб-сервереproject_name/
: каталог для проекта, который содержит все вышеперечисленные файлы по умолчанию
Проект Django состоит из одного или нескольких приложений Django или приложений, которые служат определенной цели.
Основное применение
- Чтобы создать приложение, в каталоге проекта запустите
python manage.py startapp appname
. Это создаст каталогappname
внутри каталога проекта.appname
будет содержать несколько файлов автоматически. - Внутри
appname
,views.py
аналогичноapplication.py
приложению Flask. Он содержит код, который определяет, что пользователь видит на определенном маршруте. Сначала это будет выглядеть так:from django.shortcuts import render
# Create your views here.
- Все функции просмотра должны принимать
request
объект в качестве аргумента. Как и во Flask, этот объект будет содержать информацию о том, какие аргументы были переданы в запрос и т. Д. Представление baisc может просто вернуть простой HTTP-ответ.from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def index(request):
return HttpResponse("Hello, world!")
- Однако этот базовый вид не определяет, по какому маршруту он идет. Для этого
urls.py
вappname
каталоге должен быть создан новыйurls.py
файл (он отличается от файла уровня проекта с тем же именем). Каждое приложение часто имеет свои собственные маршруты, и эти отдельные данныеurls.py
помогают сигнализировать об этих различиях в функциональности, упорядочивать вещи и упрощают повторное использование приложений в других проектах.appname/urls.py
может выглядеть так:from django.urls import path
from . import views
urlpatterns = [
path("", views.index),
]
from . import views
импортируетviews.py
изappname
каталога, так что URL-адреса могут быть связаны с представлениями.urlpatterns
список всех URL-адресов, поддерживаемых этим приложением""
указывает на пустой маршрут.- Когда проект Django запускается, он будет проверять только
urls.py
на уровне проекта. Итак, последний шаг перед тем, как это базовое приложение будет фактически пригодным для использования,appname/urls.py
должен быть связан с проектомurls.py
, который начинается с некоторого кода в нем.from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls)
]
- Чтобы связать новый путь, просто добавьте путь к
urlpatterns
:urlpatterns = [
path("", include("appname.urls")),
path("admin/", admin.site.urls)
]
- Причиной такой очевидной сложности является возможность маршрутизации между несколькими различными приложениями. Это
urls.py
служит отправной точкой для всех этихurls.py
файлов более низкого уровня .
- Чтобы запустить приложение, запустите
python manage.py runserver
.
Авиабилеты пересмотрены
- Чтобы продемонстрировать Django более полно, в следующем примере будет реконструировано и расширено приложение приложения Flight Manager, изначально созданное с помощью Flask. Имя проекта будет
djangoair
, и оно будет содержать приложение под названиемflights
. - Для начала
flights/urls.py
:from django.urls import path
from . import views
urlpatterns = [
path("", views.index),
]
- Эти URL должны быть связаны так
djangoair/urls.py
же, как и в предыдущем примере.
flights/views.py
:from django.http import HttpResponse
from django.shortcuts import render
# Create your views here
def index(request):
return HttpResponse("Flights")
- Это приложение теперь находится в той же точке, что и предыдущий пример. Следующим шагом является добавление базы данных. Django был разработан для взаимодействия с данными, поэтому это очень легко сделать.
flights/models.py
выглядит вот так прямо сейчас:from django.db import models
# Create your models here
- Это файл для определения классов, которые будут определять типы данных, хранящихся в базе данных. Информация, которая будет содержаться здесь, очень похожа на информацию, созданную с помощью Flask-SQLAlchemy.
- Модель для полета может выглядеть так:
class Flight(models.Model):
origin = models.CharField(max_length=64)
destination = models.CharField(max_length=64)
duration = models.IntegerField()
- Инертинг
models.Model
просто устанавливает этот класс как модель Джанго. - В Django есть несколько встроенных типов полей, которые, например, отображаются на разные типы данных в базе данных SQL.
- Теперь, как и с новыми URL-адресами, модели должны быть связаны с проектом Django. В
djangoair/settings.py
списке есть списокINSTALLED_APPS
, предварительно заполненный установленными приложениями Django. Чтобы добавитьflights
приложение,flights.apps.FlightsConfig
должен быть добавлен в этот список.INSTALLED_APPS = [
'flights.apps.FlightsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
FlightsConfig
это класс, который определяет настройкиflights
приложения.
Миграции
- При создании веб-приложения очень редко будут определены все таблицы с правильными столбцами с самого начала. Обычно таблицы создаются по мере роста приложения, и база данных будет изменена. Было бы утомительно изменять код модели Django и запускать команды SQL для изменения базы данных.
- Решение Джанго этой проблемы «миграция». Django автоматически обнаруживает и изменяет
models.py
и автоматически генерирует необходимый код SQL для внесения необходимых изменений. - Чтобы создать таблицу для управления полетами внутри базы данных, запустите
python manage.py makemigrations
. Это будет просматривать файлы модели на предмет любых изменений и генерировать «миграцию», которая представляет необходимые изменения для базы данных. Выполнение этой команды создаст файлmigrations/0001_initial.py
:# Generated by Django 2.0 on 2018-07-19 22:14
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Flight',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('origin', models.CharField(max_length=64)),
('destination', models.CharField(max_length=64)),
('duration', models.IntegerField()),
],
),
]
- Внутри класса
Migration
есть списокoperations
, который содержит все, что должно происходить с базой данных. В этом случае модельFlight
должна быть создана, с полямиid
,origin
,destination
, иduration
. - Обратите внимание, что
id
никогда не было указано вmodels.py
. Django добавляет этот столбец по умолчанию.
- Команда
python manage.py sqlmigrate flights 0001
создаст код SQL, который фактически соответствует этой миграции. Эту команду не нужно запускать, но она полезна для демонстрации того, что на самом деле происходит. Команда SQL очень похожа на ту, что была показана ранее, но ее не нужно было писать. Все это генерируется системой миграции Django. - Чтобы на самом деле применить эту миграцию к базе данных, запустите
python manage.py migrate
, которая будет применять новую миграцию, а также некоторые из них по умолчанию Django. - База данных , которая фактически используется здесь определяется
djangoair/settings.py
вDATABASES
словаре. По умолчанию он использует SQLite 3 (другую версию SQL, которая использует локальный файл для базы данных) и файл базы данныхdb.sqlite3
.
Джанго Шелл
- Django предоставляет оболочку, похожую на интерпретатор Python, которая позволяет напрямую изменять базу данных. Запустите оболочку, запустив
python manage.py shell
. Внутри оболочки можно запускать команды Python. - Чтобы создать новый полет, внутри оболочки можно выполнить следующие команды.
from flights.models import Flight
f = Flight(origin="New York", destination="London", duration=415)
f.save()
Flight.objects.all()
# Returns <QuerySet [<Flight: Flight object(1)>]>
f.save()
аналогично SQLCOMMIT
.- А
QuerySet
, как список, с добавленной функциональностью.
- Представление,
QuerySet
которое возвращает оболочка, на самом деле не читабельно и не полезно. Чтобы получить более полезное строковое представление полета,__str__
вFlight
класс можно добавить функциюflights/models.py
.def __str__(self):
return f"{self.id} - {self.origin} to {self.destination}"
- Для любого класса, не только в Django,
__str__
функция определяет, как должен выглядеть объект при печати, на терминале, на странице HTML и т. Д.
- Вернуться к оболочке:
Flight.objects.all()
# Returns <QuerySet [<Flight: 1 - New York to London>]>
f = Flight.objects.first()
f
# Returns <Flight: 1 - New York to London>
f.origin()
# Returns 'New York'
f.id
# Returns 1
f.delete()
# Deletes the flight as expected
Лучшие Модели
- Более надежный дизайн для
Flight
модели будет иметь поле идентификатора, которое ссылается на таблицу аэропортов, а не просто текст для происхождения и пунктов назначения. Для этогоAirport
сначала необходимо создать новую модель.class Airport(models.Model):
code = models.CharField(max_length=3)
city = models.CharField(max_length=64)
def __str__(self):
return f"{self.city} ({self.code})"
- Затем
Flight
модель может быть изменена соответствующим образом, с исходной и конечной точкамиForeignKey
s.class Flight(models.Model):
origin = models.ForeignKey(Airport, on_delete=models.CASCADE, related_name="departures")
destination = models.ForeignKey(Airport, on_delete=models.CASCADE, related_name="arrivals")
- Модели Django допускают определенное поведение, например, при удалении аэропорта.
on_delete=models.CASCADE
означает, что в случае удаления аэропорта все рейсы с этим аэропортом в качестве пункта отправления или назначения также будут удалены. related_name
позволяет получить доступ ко всем рейсам, вылетающим из или прибывающим в конкретный аэропорт, используя ключиdeparatures
илиarrivals
.- Обратите внимание, что нет буквальных определений происхождения и назначения в качестве идентификаторов, а также каких-либо фактических команд для того, как связать две таблицы. Единственное, что указано, это то, что
origin
иdestination
должно бытьAirport
s. Вся работа по выполнению этого поручена Джанго.
- Чтобы применить эти изменения, они должны быть перенесены так же, как и раньше. Теперь в оболочке намного проще и понятнее создавать полеты.
from flights.models import Airport, Flight
jfk = Airport(code="JFK", city="New York City")
lhr = Airport(code="LHR", city="London")
jfk.save()
lhr.save()
f = Flight(origin=jfk, destination=lhr, duration=415)
f.save()
f.origin
# Returns <Airport: New York City (JFK)>
f.origin.code
# Returns 'JFK'
jfk.departures.all()
# Returns <QuerySet [<Flight: 1 - New York City (JFK) to London (LHR)>]>
Шаблоны рендеринга
- Подобно Flask, для рендеринга HTML-шаблона, отрендеренный шаблон должен возвращаться функцией, которая обрабатывает маршрут. Для Джанго это в
flights/views.py
.def index(request)
return render(request, "flights/index.html")
- Второй аргумент
render
— это просто путь к шаблону, который будет отображаться. - Они должны храниться в пути примерно так:
flights/templates/flights/index.html
. Обратите внимание, чтоrender
путь начинается сtemplate
папки. Очевидная избыточность этого пути, хотя и не является строго необходимой в этом примере, является хорошей практикой, позволяющей избежать проблем, когда у нескольких приложений могут быть свои собственныеindex.html
.
index.html
может быть простым на данный момент.<html> <head> <title>Flights</title> </head> <body> <h1>Flights</h1> </body> </html>
- Для отображения информации о рейсах можно использовать систему шаблонов Django, которая очень похожа на Jinja. Джанго передает информацию в шаблон через
context
словарь.from .models import Flight
def index(request)
context = {
"flights": Flights.objects.all()
}
return render(request, "flights/index.html", context)
<body> <h1>Flights</h1> <ul> {% for flight in flights %} <li> {{ flight }} </li> {% endfor %} </ul> </body>
Администратор
- Admin — это встроенное приложение Django, которое позволяет легко добавлять или изменять существующие данные на веб-странице. Обратите внимание, что это задача, которая требует много кода во Flask. Это, пожалуй, одна из самых мощных функций Django, особенно когда речь идет о работе с данными и манипулировании ими.
flights/admin.py
начинается такfrom django.contrib import admin
# Register your models here.
- Добавить
Airport
иFlight
модели просто.from django.contrib import admin
from .models import Airpot, Flight
# Register your models here.
admin.site.register(Airport)
admin.site.register(Flight)
- Это позволяет администратору приложения управлять аэропортами и рейсами.
- Чтобы получить доступ к сайту администратора через Интернет, пользователь должен войти в систему. Это одна задача, которая будет довольно утомительной во Flask, но, опять же, Django поставляется с этой встроенной функциональностью. Первый шаг заключается в создании «суперпользователя» счет с доступом ко всему:
python manage.py createsuperuser
. Затем Django запросит имя пользователя, адрес электронной почты и пароль. Затем эти данные будут занесены в таблицу пользователей, за которой полностью следит Django. - Сайт администратора уже связан по умолчанию в проекте
urls.py
наadmin/
маршруте. На сайте администратора пользователь может войти в систему и манипулировать данными. Интерфейс администратора прост и удобен в навигации. Обратите внимание, что этот интерфейс администратора предназначен не для использования всеми пользователями веб-сайта, а скорее просто для управления контентом для таких вещей, как заполнение моделей и добавление информации, тогда как пользователи будут просматривать эту информацию на отдельно отображаемой странице.
Добавление большего количества маршрутов
- Например, чтобы добавить больше маршрутов для конкретной информации о рейсе, нужно просто добавить URL-адреса
flights/urls.py
вместе с соответствующим представлениемflights/views.py
и шаблоном вtemplates/flights
.urlpatterns = [
path("", views.index),
path("<int:flight_id>", views.flight),
]
- Синтаксис для создания маршрутов, которые принимают аргументы, очень похож на синтаксис Flask.
def flight(request, flight_id):
try:
flight = Flight.objects.get(pk=flight_id)
except Flight.DoesNotExist:
raise Http404("Flight does not exist")
context = {
"flight": flight,
}
return render(request, "flights/flight.html", context)
- Потому что
flight_id
был параметром в URL,flight_id
передается вflight
представление. pk
обозначает «первичный ключ».DoesNotExist
это специальное исключение, встроенное в модели Django.Http404
это еще одна встроенная функция Django (импортированная изdjango.http
), которая просто вызывает ошибку 404. « `html
Flight {{flight.id}}
- Происхождение: {{flight.origin}}
- Пункт назначения: {{flight.destination}}
« `
head
содержимое может быть таким же, как иindex.html
сейчас. Обратите внимание на текущую избыточность в шаблонах HTML.
Наследование шаблонов
- Наследование шаблонов для HTML-страниц в Django работает почти так же, как и во Flask. Вот как
base.html
может выглядеть универсальный шаблон :<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
- Теперь
index.html
иflight.html
можно упростить.{% extends "flight/base.html" %}
{% block title %}
Flights
{% endblock %}
{% body block %}
<h1>Flights</h1>
<uL>
{% for flight in flights $}
<li>
<a href="{% for flight in flights $}
<li>
<a href="{% url 'flight' flight.id %}">{{ flight }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}
и
{% extends "flight/base.html" %}
{% block title %}
Flight {{ flight.id }}
{% endblock %}
<h1>Flight {{ flight.id }}</h1>
<ul>
<li>Origin: {{ flight.origin }}</li>
<li>Destination: {{ flight.destination }}</li>
</ul>
<a href="{% url 'index' %}">Back to full listing</a>
{% block body %}
{% endblock %}
Модельные Отношения
- Раньше с помощью Flask и SQL для связи пассажиров с рейсами в таблице пассажиров был столбец идентификатора рейса, чтобы каждый пассажир мог быть связан с рейсом. Проблема этого подхода заключается в том, что каждый пассажир может находиться только на одном рейсе. Что является более желательным, так это отношения «многие ко многим», когда пассажир может совершать несколько рейсов, а рейс может иметь несколько пассажиров. Обычной парадигмой для этого является реализация «промежуточной таблицы», которая просто имеет два столбца, один для идентификатора пассажира и один для идентификатора рейса, с таким количеством строк, сколько необходимо. Django допускает это, но выполняет автоматическую реализацию промежуточной таблицы.
- Первым шагом является внедрение модели пассажира в России
flights/models.py
.class Passenger(models.Model):
first = models.CharField(max_length=64)
last = models.CharField(max_length=64)
flights = models.ManyToManyField(Flight, blank=True, related_name="passengers")
def __str__(self):
return f"{self.first} {self.last}"
- Раньше, когда связывались две таблицы,
models.ForeignKey
использовался.models.ManyToManyField
учитывает желаемое поведение отношений «многие ко многим». blank=True
позволяет пассажиру быть связанным без полетов.- Как и раньше,
related_name
позволяет опрашивать всех пассажиров данного рейса.
- Обновление базы данных, как и прежде, с
python manage.py makemigrations
проверкой SQL и проверкой наpython manage.py sqlmigrate flights 0003
наличие кода позволяет выявить код для созданияflights_passengers
указанной таблицы , а также таблицуflights_passengers_flights
, которая не была указана, но является таблицей, созданной автоматически. - После завершения миграции
python manage.py migrate
можно использовать оболочку, чтобы опробовать эти новые модели.from flights.models import Flight, Passenger
f = Flight.objects.get(pk=1)
f
# Returns <Flight: 1 - New York City (JFK) to London (LHR)>
p = Passenger(first="Alice", last="Adams")
p.save()
p.flights.add(f)
p.flights.all()
# Returns <QuerySet [<Flight: 1 - New York City (JFK) to London (LHR)>]>
f.passengers.all()
# Returns <QuerySet [<Passenger: Alice Adams>]>
flight
Вид и соответствующий HTML могут быть обновлены до сих пор отображения пассажирской информации.def flight(request, flight_id):
try:
flight = Flight.objects.get(pk=flight_id)
except Flight.DoesNotExist:
raise Http404("Flight does not exist")
context = {
"flight": flight,
"passengers": flight.passengers.all(),
}
return render(request, "flights/flight.html", context)
и
<h2>Passengers</h2>
<ul>
{% for passenger in passengers %}
<li>{{ passenger }}</li>
{% empty %}
<li>No passengers</li>
{% endfor %}
</ul>
{% empty %}
выполняется еслиpassengers
пусто
Passenger
Модель также может быть добавлен администратором и изменение приложения администратора в то же самое было и раньше.
Регистрация пользователя
- Первым шагом к созданию веб-интерфейса пользователя для использования регистрации полета может быть создание нового маршрута вместе с соответствующим представлением и шаблоном HTML.
urlpatterns = [
path("", views.index, name="index"),
path("<int:flight_id>", views.flight, name="flight"),
path("<int:flight_id>/book", views.book, name="book")
]
def book(request, flight_id):
try:
passenger_id = int(request.POST["passenger"])
flight = Flight.objects.get(pk=flight_id)
passenger = Passenger.objects.get(pk=passenger_id)
except KeyError:
return render(request, "flights/error.html", {"message": "No selection."})
except Flight.DoesNotExist:
return render(request, "flights/error.html", {"message": "No flight."})
except Passenger.DoesNotExist:
return render(request, "flights/error.html", {"message": "No passenger."})
passenger.flights.add(flight)
return HttpResponseRedirect(reverse("flight", args=(flight_id,)))
- Этот код написан в предположении, что пользователь отправит веб-форму через
POST
запрос с именем одного аргументаpassenger
. - A
KeyError
будет сгенерирован, если либоPOST
запрос не был отправлен, либоpassenger
аргумент не был предоставлен, не оставляя данных для извлечения. flights/error.html
будет новый общий шаблон для отображения любого количества сообщений об ошибках.HttpResponseRedirect
(импортировано изdjango.http
) используется для отправки пользователя на его страницу полета после его регистрации.reverse()
(импортировано изdjango.urls
) возвращает URL с указанием имени маршрута. Аргументы также могут быть переданы в виде кортежа.
- Предполагая, что создание пассажира — это отдельный процесс от регистрации пассажира на рейс, когда пользователь собирается зарегистрироваться на рейс, он должен иметь возможность выбирать только из созданных пассажиров. Для этого все «не пассажиры» на рейсе должны быть переданы в
flight.html
шаблон.def flight(request, flight_id):
try:
flight = Flight.objects.get(pk=flight_id)
except Flight.DoesNotExist:
raise Http404("Flight does not exist")
context = {
"flight": flight,
"passengers": flight.passengers.all(),
"non_passengers": Passenger.objects.exclude(flights=flight).all()
}
return render(request, "flights/flight.html", context)
Passenger.objects
возвращает все пассажирские объекты, которые затем могут быть отфильтрованы различными способами.exclude
удаляет объекты с определенным свойством; в этом случае все пассажиры на текущем рейсе исключаются.
{% if non_passengers %}
<h2>Add a Passenger</h2>
<form action="{% url 'book' flight.id %}" method="post">
<select name="passenger">
{% for passenger in non_passengers %}
<option value="{{ passenger.id }}">{{ passenger }}</option>
{% endfor %}
</select>
<input type="submit" value="Book Flight" />
</form>
{% else %}
<div>No passengers to add.</div>
{% endif %}
- Вмещающий
if
блок допускает регистрацию, только если есть кто-то, чтобы зарегистрироваться. - Здесь
passenger
select
элементом являются соответствующие данные, которые отправляются обратно вbook
представление, а внутриpassenger
—passenger.id
это то, что ожидается.
Подделка межсайтовых запросов
- Несмотря на то, что функциональность бронирования выглядит почти полной, при отправке регистрационной формы Django не разрешит перенаправить пользователя на страницу своего рейса и вместо этого выдаст 403 Запрещенную ошибку:
CSRF verification failed. Request aborted.
CSRF (Подделка межсайтовых запросов) — потенциальная защита уязвимость в формах, из-за которой кто-то может подделать, откуда исходит форма. Django встроен для защиты от подобных атак. Тем не менее, чтобы учесть это, при работе с формой в Django нужно добавить немного дополнительного синтаксиса.
<form action="{% url 'book' flight.id %}" method="post">
{% csrf_token %}
<select name="passenger">
{% for passenger in non_passengers %}
<option value="{{ passenger.id }}">{{ passenger }}</option>
{% endfor %}
</select>
<input type="submit" value="Book Flight" />
</form>
- Когда форма отправляется, вместе с ней передается токен CSRF, чтобы Django мог проверить, действительно ли веб-приложение отправляет запрос.
Модификация Admin
- Интерфейс администратора Django может быть расширен, чтобы учесть пользовательское поведение. Возвращаясь к примеру с рейсами, вот как это
flights/admin.py
можно изменить.from django.contrib import admin
from .models import Airport, Flight, Passenger
# Register your models here.
class PassengerInline(admin.StackedInline):
model = Passenger.flights.through
extra = 1
class FlightAdmin(admin.ModelAdmin):
inlines = [PassengerInline]
class PassengerAdmin(admin.ModelAdmin):
filter_horizontal = ("flights",)
admin.site.register(Airport)
admin.site.register(Flight, FlightAdmin)
admin.site.register(Passenger, PassengerAdmin)
- Поскольку
Flights
модель не имеет ссылки наPassengers
, управление полетами в приложении администратора не позволяет добавлять или удалять пассажиров так же, как рейсы могут быть добавлены или удалены пассажиру. Это может быть решено путем созданияPassengerInline
класса, который наследуется от встроенного класса,StackedInline
который позволяет добавлять новые отношения между объектами.PassengerInline
представляет собой место в пользовательском интерфейсе, где пассажиры рейса могут быть изменены. Passenger.flights.through
относится к промежуточной таблице, связывающей рейсы и пассажиров. При установкеmodel
этой промежуточной таблицы эта таблица ассоциируется сPassengerInline
.extra = 1
устанавливает количество пассажиров, которое может быть отредактировано за один раз, до 1.FlightAdmin
это новый класс, который наследуется отModelAdmin
и содержит специальный набор конфигураций, которые будут использоваться только при редактировании пассажиров. Эти параметры применяются при пропусканииFlightAdmin
кadmin.site.regiser.
inlines
содержит все дополнительные встроенные разделы модификации для страницы администратора, которая в данном случае содержит толькоPassengerInline
.filter_horizontal
помогает управлять рейсами пассажира. Он просто позволяет добавить дополнительный элемент пользовательского интерфейса в приложение администратора, чтобы упростить добавление или удаление рейсов, на которых находится пассажир.
Статические файлы
- Чтобы использовать внешние статические файлы, такие как
.css
или.js
файлы, необходимо использовать специальный синтаксис Django. Базовый шаблон со статическими файлами может выглядеть так:
{% load static %}
<span class="cp"><!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{% static 'flights/styles.css' %}"/>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
* `{% load static %}` allows for the use of static files.
* Any static file must have its `href` formattaed as `"{% static 'path/static.css' %}"`. * Inside of the application directory (e.g. `flights`), there should be a `static` directory containing a directory for the application which in turn contains any static files. So, the entire hierarchy would look like `flights/static/flights/styles.css`. This is exactly analogous to how templates are stored.
Логин и Аутентификация
- Аутентификация и авторизация — это встроенное приложение, предназначенное для обработки учетных записей пользователей и входа в систему. Этот последний пример показывает эту систему учетных записей в приложении под названием
users
.users/urls.py
выглядит так:from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout")
users/views.py
:from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
# Create your views here.
def index(request):
if <span class="ow">not request.user.is_authenticated:
return render(request, "users/login.html", {"message": None})
context = {
"user": request.user
}
return render(request, "users/user.html", context)
def login_view(request):
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(request, username=username, password=password)
if user <span class="ow">is <span class="ow">not None:
login(request, user)
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "users/login.html", {"message": "Invalid credentials."})
def logout_view(request):
logout(request)
return render(request, "users/login.html", {"message": "Logged out."})
django.contrib.auth
является пакет аутентификации Джанго, который содержитUser
модель, наряду с функциямиauthenticate
,login
иlogout
.request.user.is_authenticated
являетсяtrue
ли пользователь вошел в систему . Если они не вошли в систему , они redirectd на страницу входа в систему . Если они есть, пользователь направляется на свою страницу пользователя.login_view
сначала проверяет, существует ли пользовательauthenticate
, принимает имя пользователя и пароль и возвращает этот объект пользователя.login
берет пользователя и регистрирует его в системе аутентификации.logout
просто выходит из системы
login.html
:
{% block body %}
<h1>Login</h1>
{% if message %}
<div>
{{ message }}
</div>
{% endif %}
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<input name="username" type="text"/>
<input name="password" type="password"/>
<input type="submit" value="Login"/>
</form>
{% endblock %}
user.html
:
{% block body %}
<h1>Hello, {{ user.first_name }}</h1>
<ul>
<li>Currently logged in as: {{ user.username }}</li>
<li><a href="{% url 'logout' %}">Logout</a></li>
</ul>
{% endblock %}
User
Содержит поля , такие какfirst_name
,last_name
,username
и т.д., но также может быть продлен.- Регистрация нового пользователя влечет за собой добавление нового пользователя в базу данных. Это можно сделать через интерфейс администратора с учетной записью суперпользователя или с помощью оболочки:
from django.contrib.auth.models import User
user = User.objects.create_user("alice", "alice@something.com", "alice12345")
user.first_name = "Alice"
user.save()
create_user
принимает аргументы имя пользователя, адрес электронной почты, пароль.
Предыдущая статья «Front Ends, Single-Page Apps, шаблоны JS, CSS и SVG анимация«
Следующая статья «Тестирование приложения, CI/CD«
Читайте больше по теме: