Краткий учебник Django

Данное пособие было написано Козловым Михаилом для себя т.к. работаю с довольно большим количеством совершенно разных технологий, постоянно все вылетает из головы, выкладываю в общедоступный доступ на своем сайте http://snakeproject.ru/

 

 

В данном пособии примеры делались на версии Django 2.1, Python 3.4 и Linux Centos 7

 

 

Установка и первый проект

 

 

С Python версии 3.4 в состав включается утилита pip, с помощью нее выполняем установку дополнительных библиотек из штатного репозитория PyPI

 

Установка django

pip install django

 

 

Создадим новый проект с именем testsite с помощью утилиты django-admin

 

mkdir -p /data/www

cd /data/www/

django-admin startproject testsite

 

 

Создастся структура проекта

cd testsite && ls -l && ls -l testsite/

testsite/

  manage.py

  testsite

testsite/testsite

  __init__.py

  settings.py

  urls.py

  wsgi.py

 

manage.py – по сути программная оболочка для работы с проектом, которая вызывает утилиту django-admin, передавая ей аргументы

testsite – папка, содержащая модули проекта и конфигурацию

__init__.py – сообщает python, что папка является полноценным пакетом

settings.py – модуль настроек проекта

urls.py – модуль маршрутизации проекта

wsgi.py – модуль связки проекта с веб-сервером

 

 

Запуск отладочного веб-сервера

 

Находясь в папке с проектом

pwd

/data/www/testsite

 

Наберите (ip моего тестового сервера - 10.0.2.10)

python3.4 manage.py runserver 10.0.2.10:8000

 

И проверьте через браузер:

http://10.0.2.10:8000

 

Вы увидите тестовую страницу проекта

 

 

The install worked successfully! Congratulations!

 

You are seeing this page because DEBUG=True is in your settings file and you have not configured any URLs.

 

 

Первое приложение

 

Расширим функционал нашего проекта с помощью приложений

 

Находясь в папке проекта создадим приложение с именем «app

python3.4 manage.py startapp app1

 

Созданная структура приложения app1

ls -l app1/

  admin.py

  apps.py

  __init__.py

  migrations

  models.py

  tests.py

  views.py

 

admin.py - модуль административных настроек

apps.py - модуль настроек приложения

_init_.py - сообщает python, что папка является полноценным пакетом

migrations - директория хранит сгенерированные модули миграций

models.py - модуль моделей

tests.py - модуль тестирующих процедур

views.py - модуль контроллеров

 

Зарегистрируем наше приложение в проекте

testsite/settings.py

 

Добавим приложение app1 в секцию INSTALLED_APPS

INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'app1.apps.App1Config',

]

 

 

Теперь добавим представление, которое по сути является кодом, запускаемым в ответ на клиентский запрос

 

Напишем представление-функцию в нашем приложении app1

app1/views.py

 

from django.http import HttpResponse

 

def index(request) :

  return HttpResponse("Тестовый вывод")

 

Представление-функция с именем index принимает обязательный параметр экземпляра класса HttpRequest, который хранит сведения о полученном запросе клиента

Параметр имеет имя request

 

Внутри функции создается экземпляр класса HttpResponse модуля django.http, который отправит клиенту ответ

Содержимое указывается параметром конструктора класса, готовый экземпляр класса возвращается из функции с именем index

 

 

Теперь настроим маршрутизацию на уровне проекта

 

testsite/urls.py

 

from django.contrib import admin

from django.urls import path

from app1.views import index

 

urlpatterns = [

  path ( 'app1/', index),

  path ( 'admin/', admin. site. urls),

]

 

Тут мы добавили связь запроса

Маршруты описываются в списке urlpatterns

Каждый маршрут - результат, возвращаемый функцией path() модуля django.urls

Функция path() принимает строку с шаблоном url и ссылку на функцию-представление

Т.е. новый маршрут связывает шаблон url app1/ и функцию-представление index

 

Запускаем и проверяем

python3.4 manage.py runserver 10.0.2.10:8000

 

http://10.0.2.10:8000/app1/

Тестовый вывод

 

Теперь настроим маршрутизацию на уровне приложения

 

В маршрутизации приложения

app1/urls.py

 

from django.urls import path

from .views import index

 

urlpatterns = [

  path ('', index),

]

Пустая строка - '' означает корень пути маршрута предыдущего уровня вложенности

 

 

В маршрутизации проекта

testsite/urls.py

 

from django.contrib import admin

from django.urls import path, include

 

urlpatterns = [

  path ('app1/', include('app1.urls')),

  path ( 'admin/', admin.site.urls),

]

 

include('app1.urls')) - это список маршрутов, функции path(), представляет результат, возвращаемый функцией include() из модуля django.urls, ее параметр - строка с путем до модуля urls приложения app1, в котором описан список маршрутов

 

 

Запускаем и проверяем

python3.4 manage.py runserver 10.0.2.10:8000

 

http://10.0.2.10:8000/app1/

Тестовый вывод

 

Когда сайт получает запрос типа http://10.0.2.10:8000/app1/ , маршрутизатор определит, что адрес запроса совпадает с шаблонном app1/ из маршрутизации проекта - testsite/urls.py

 

Из полученного в запросе адреса удалится префикс, который соответствует шаблонному адресу, и получится пустая строка

 

Далее пройдет загрузка вложенного списка маршрутов из модуля urls.py приложения - testsite/urls.py

 

Полученный адрес, представляющий пустую строку совпадет с первым маршрутом вложенного списка, запустится функция-представление index() с тестовым выводом

 

 

Теперь поговорим о структуре

 

Модель – структура сущности, хранящаяся в базе данных в виде python класса, по сути представление таблицы, в которой хранится набор сущностей, в каждой из которых хранятся атрибуты класса, которые описывают поля этой таблицы.

 

Каждый экземпляр класса модели является отдельной сущностью

Класс модели объявляется на уровне приложения в models.py , а сам класс дает возможность выборки, сортировки, фильтрации

 

По умолчанию созданный проект настроен использовать базу данных SQLite (файл db.sqlite3 в папке проекта)

 

 

Тестовая модель A1 для приложения app1 (будем описывать товар)

 

name - тип: CharField, строка длинною 30 символов

description - тип: TextField

price - тип: Float

arrival - тип: DateTimeField, дата и время (подставлять текущее по дефолту)

 

 

Внесем изменения

app1/models.py

 

from django.db import models

 

class A1(models.Model):

  name = models.CharField(max_length=30)

  description = models.TextField(null=True, blank=True)

  price = models.FloatField(null=True, blank=True)

  arrival = models.DateTimeField(auto_now_add=True, db_index=True)

 

Где:

CharField - строковое поле фиксированной длины (max_length=30 - 30 символов)

 

TextField - текстовое поле неограниченной длины, (null=True и blank=True - разрешит поле не заполнять)

 

FloatField - вещественных чисел поле

 

DateTimeField - даты и времени поле (auto_now_add=True - добавление текущей даты и времени, db_index=True - создать индекс)

 

 

Теперь нужно сформировать в базе данных структуру модели

Используем модуль миграция

 

Запустим миграцию всех моделей для приложения app1

python3.4 manage.py makemigrations app1

Migrations for 'app1':

  app1/migrations/0001_initial.py

    - Create model A1

 

0001_initial.py – модуль с кодом миграции

 

Код нашей миграции

cat app1/migrations/0001_initial.py

# Generated by Django 2.0.13 on 2019-03-19 15:54

 

from django.db import migrations, models

 

 

class Migration(migrations.Migration):

 

    initial = True

 

    dependencies = [

    ]

 

    operations = [

        migrations.CreateModel(

            name='A1',

            fields=[

                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),

                ('name', models.CharField(max_length=30)),

                ('description', models.TextField(blank=True, null=True)),

                ('price', models.FloatField(blank=True, null=True)),

                ('arrival', models.DateTimeField(auto_now_add=True, db_index=True)),

            ],

        ),

    ]

 

 

Миграции создают SQL код, который будет отправлен СУБД, просмотрим его

python3.4 manage.py sqlmigrate app1 0001

BEGIN;

--

-- Create model A1

--

CREATE TABLE "app1_a1" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL, "description" text NULL, "price" real NULL, "arrival" datetime NOT NULL);

CREATE INDEX "app1_a1_arrival_42c6d35f" ON "app1_a1" ("arrival");

COMMIT;

 

Самую первую миграцию нового проекта рекомендовано производить для всех приложений

python3.4 manage.py migrate

Operations to perform:

  Apply all migrations: admin, app1, auth, contenttypes, sessions

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying app1.0001_initial... OK

  Applying contenttypes.0002_remove_content_type_name... OK

  Applying auth.0002_alter_permission_name_max_length... OK

  Applying auth.0003_alter_user_email_max_length... OK

  Applying auth.0004_alter_user_username_opts... OK

  Applying auth.0005_alter_user_last_login_null... OK

  Applying auth.0006_require_contenttypes_0002... OK

  Applying auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying auth.0009_alter_user_last_name_max_length... OK

  Applying sessions.0001_initial... OK

 

 

Теперь познакомимся с консолью python django

Консоль для данного проекта открыть можно так

 

python3.4 manage.py shell

 

Теперь вы находитесь в консоли, которая в составе путей поиска модулей имеет ваш проект

 

 

Добавим запись в базу

 

>>> from app1.models import A1

>>> a1 = A1 (name='Дрова', description='Березовые, высушенные', price=300)

>>> a1.save()

 

 

Проверим, сохранилась ли запись, выведя ее ключевое поле

>>> a1.pk

1

 

Выведем определенные поля записи

a1.description

'Березовые, высушенные'

>>> a1.id

1

>>> a1.arrival

datetime.datetime(2019, 3, 19, 16, 9, 29, 911052, tzinfo=<UTC>)

 

 

Второй вариант создания записи

>>> a2 = A1()

>>> a2. name='Щепки'

>>> a2. description='Березовые, сырые'

>>> a2. price=200

>>> a2.save()

 

Изменим поле записи

>>> a2.price

200

>>> a2.price=100

>>> a2.price

100

>>> a2.save()

Третий вариант создания записи (атрибут objects класса моделей)

>>> A1.objects.create(name='Опилки', description='Влажные', price=50)

<A1: A1 object (3)>

 

Наконец сделаем перебор наших записей из базы

>>> for a in A1.objects.all():

...   print(a.pk, ': ', a.name)

...

1 :  Дрова

2 :  Щепки

3 :  Опилки

 

Выборка с наложением фильтра методом filter()

>>> for a in A1.objects.filter(name='Щепки'):

...   print(a.pk, ': ', a.name)

...

2 :  Щепки

 

Выборка с сортировкой методом order_by

Тут метод all() – возвращает набор записей из нашей модели

 

>>> for a in A1.objects.order_by('name'):

...   print(a.pk, ': ', a.name)

...

1 :  Дрова

3 :  Опилки

2 :  Щепки

 

Сделаем выборку записи по pk=3

>>> a=A1.objects.get(pk=3)

>>> a.name

'Опилки'

>>> a.price

50.0

 

Удалим запись

>>> a.delete()

(1, {'app1.A1': 1})

 

Выходим из консоли

Use exit() or Ctrl-D

 

 

Добавим вывод записей в django приложении app1

app1/views.py

from django.http import HttpResponse

from .models import A1

 

def index(request):

  mess = 'Товары:\r\n'

  for a in A1.objects.order_by('-arrival'):

    mess += a.name + '\r\n' + a.description + '\r\n'

  return HttpResponse(mess, content_type='text/plain; charset=utf-8')

 

Тут метод order_by('-arrival') – сортирует по убыванию даты

 

Запускаем и проверяем

python3.4 manage.py runserver 10.0.2.10:8000

 

 

http://10.0.2.10:8000/app1/

 

Товары:

Щепки

Березовые, сырые

Дрова

Березовые, высушенные

 

 

Теперь поговорим о шаблонах

Шаблонизатор django по умолчанию смотрит в папку templates внутри приложения

 

Для начала подредактируем вид

app1/views.py

from django.http import HttpResponse

from .models import A1

from django.template import loader

 

def index(request):

  template=loader.get_template('index.html')

  a1v=A1.objects.order_by('-arrival')

  context={'a1v': a1v}

  return HttpResponse(template.render(context, request))

 

Тут мы с помощью функции get_template() загружаем шаблон из модуля django.template.loader

('index.html') – путь до шаблона (об этом ниже)

context={'a1v': a1v} – контекст шаблона по сути данные, доступные внутри самого шаблона

template.render(context, request) – рендеринг по сути объединение контекста и шаблона

 

Создадим для приложения app1 эту папку и шаблон

mkdir app1/templates

 

app1/templates/index.html

<html>

<head>

<titlе>Заголовок</titlе>

</head>

<body>

<h2>Список</h2>

{% for a in a1v %}

<h3>{{ a.name }} </h3>

<р> {{ a.description }} < /р>

<р> {{ a.price }} < /р>

<р>{ { a.arrival: "d.m. У Н: i:s" } }</р>

{% endfor %}

</body>

</html>

 

Тут {% for a in a1v %}…{% endfor %}по функционалу цикл for

a1v – данные нашего контекста

 

Запускаем, проверяем

python3.4 manage.py runserver 10.0.2.10:8000

 

http://10.0.2.10:8000/app1/

Заголовок

Список

Щепки

<р> Березовые, сырые < /р> <р> 100.0 < /р> <р>{ { a.arrival: "d.m. У Н: i:s" } }

Дрова

<р> Березовые, высушенные < /р> <р> 300.0 < /р> <р>{ { a.arrival: "d.m. У Н: i:s" } }

 

Более простой вариант

 

app1/views.py

from django.shortcuts import render

from .models import A1

 

def index(request):

  a1v=A1.objects.order_by('-arrival')

  return render(request, 'index.html', {'a1v': a1v})

 

Запускаем, проверяем

python3.4 manage.py runserver 10.0.2.10:8000

 

http://10.0.2.10:8000/app1/

Заголовок

Список

Щепки

<р> Березовые, сырые < /р> <р> 100.0 < /р> <р>{ { a.arrival: "d.m. У Н: i:s" } }

Дрова

<р> Березовые, высушенные < /р> <р> 300.0 < /р> <р>{ { a.arrival: "d.m. У Н: i:s" } }

 

 

Поговорим об админке

Стандартный модуль административной панели django входит в состав по умолчанию

 

За хранение учетных данных отвечает приложение

django.contrib.auth

 

За работу админки отвечает приложение

django.contrib.admin

 

Создадим суперпользователя

python3.4 manage.py createsuperuser

Username (leave blank to use 'root'): root

Email address: root@localhost

Password:

Password (again):

Superuser created successfully.

 

Русифицируем админку

testsite/settings.py

 

...

LANGUAGE_CODE = 'ru-ru'

...

 

Чтоб приложение app1 отобразилось в админке, его надо зарегистрировать

app1/admin.py

from django.contrib import admin

from .models import A1

 

admin.site.register(A1)

 

register(A1) – регистрирует наше приложение в админке

 

 

Запускаем, проверяем, вводим логин и пароль

python3.4 manage.py runserver 10.0.2.10:8000

 

http://10.0.2.10:8000/admin/

 

 

 

 

В итоге у нас появится наша модель APP1

Администрирование сайта

APP1

A1s

Добавить

Изменить

ПОЛЬЗОВАТЕЛИ И ГРУППЫ

Группы

Добавить

Изменить

Пользователи

Добавить

Изменить

 

 

Группы и Пользователи – встроенное по умолчанию приложение django.contrib.auth

 

Попробуйте самостоятельно добавить пару записей через кнопку «Добавить» и изменить в приложении App1

 

 

Поля, параметры, модель

 

Давайте дадим в админке «человеческие» названия нашим полям модели

 

app1/models.py

from django.db import models

 

class A1(models.Model):

  name = models.CharField(max_length=30, verbose_name='Название')

  description = models.TextField(null=True, blank=True, verbose_name='Описание')

  price = models.FloatField(null=True, blank=True, verbose_name='Цена')

  arrival = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата')

 

  class Meta:

    verbose_name_plural = 'Товары'

    verbose_name = 'Товар'

    ordering = [ '-arrival' ]

 

Где

verbose_name - название поля, которое выводится на экран

class Meta: - вложенный класс, атрибуты которого зададут параметры модели

verbose_name_plural - название модели во множественном числе

verbose_name - название модели в единственном числе

ordering - сортировка записей

 

 

Переделаем наше представление на более простую конструкцию с all()

app1/views.py

from django.shortcuts import render

from .models import A1

 

def index(request):

  a1v=A1.objects.all()

  return render(request, 'index.html', {'a1v': a1v})

 

Дополнительно отобразим по «человечески» сами записи в админке

app1/admin.py

from django.contrib import admin

from .models import A1

 

class A1Admin(admin.ModelAdmin):

  list_display = ('name', 'description', 'price', 'arrival')

  list_display_links = ('name', 'description')

  search_fields = ('name', 'description')

 

admin.site.register(A1, A1Admin)

 

 

APP1

Товары

Добавить

Изменить