Django 5 для начинающих

Прогресс по курсу:  9/1004

4.2 CRUD проект
4 из 12 шагов пройдено
0 из 60 баллов  получено

Для работы с базой данных в Django существует понятие ORM. Само понятие ORM обозначает возможность преобразования и взаимодействия прикладного языка (в нашем случае Python) и базы данных (обычно это SQL).

В любой реализации ORM есть 4 ключевых понятия, которые складываются в аббревиатуру CRUD:

  • Create - создание или добавление данных в БД.
  • Read - получение и чтение данных из БД.
  • Update - обновление данных в БД.
  • Delete - удаление данных из БД.

В этом разделе, мы рассмотрим как создается функциональность CRUD в Django, и создадим простое CRUD-приложение.


Продолжим работу с проектом Course_ThirdProject, но добавим в него модели.

Для этого воспользуемся моделью данных Person, а в файл моделей crud/models.py добавим следующий код:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=20)
    age = models.IntegerField()

Согласно приведенной модели данных, в БД предусмотрено два поля для хранения сведений о клиенте: имя клиента name и возраст клиента age.


Не забываем создать и применить миграции:

python manage.py makemigrations
python manage.py migrate


При выполнении миграции, в базе данных (в файле db.sqliteЗ) будет создана таблица для хранения сведений о клиентах с именем crud_person и тремя полями:

  • id: идентификатор записи
  • name: имя клиента
  • age: возраст клиента


В Django, за взаимодействие с БД отвечает представление(view). Так что следующим шагом, в файле представлений  views.py, мы реализуем две функции-представления. Одну для получения данных из БД, а другую для сохранения данных,  введенных пользователем:

from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponseNotFound
from .models import Person


# Получение данных из БД
def index(request):
    people = Person.objects.all()
    return render(request, 'index.html', {'people': people})


# Сохранение данных в БД
def create(request):
    if request.method == 'POST':
        person = Person()
        person.name = request.POST.get('name')
        person.age = request.POST.get('age')
        person.save()
    return HttpResponseRedirect('/')

Здесь нами были созданы две функции-представления: index() и create().

В функции index() мы получаем все данные в объект people, с помощью метода Person.objects.all(), и затем передаем их в шаблон index.html в виде переменной people.

В функции create() мы получаем данные из запроса методом POST, которые пользователь ввел в форму, затем сохраняем их в БД с помощью метода save().

Далее, через класс временной переадресации HttpResponseRedirect, перенаправляем пользователя по пути '/', т.е. выполняем редирект в корневую директорию сайта. Где он, согласно маршрута, будет обрабатываться функцией index(), которая в свою очередь отобразит данные всех пользователей(в том числе и только что добавленные) на главной странице сайта в шаблоне index.html.


Теперь, в директории templates, изменим шаблон главной страницы index.html, в которой будут отображаться введенные пользователем данные:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>CRUD</title>
</head>
<body>
    <form method="POST" action="create/">
        {% csrf_token %}
        <p>
            <label>Введите имя</label><br>
            <input type="text" name="name" value="{{ person.name }}"/>
        </p>
        <p>
            <label>Введите возраст</label><br>
            <input type="number" name="age" value="{{ person.age }}"/>
        </p>
        <p>
            <input type="submit" value="Сохранить">
        </p>
    </form>
{% if people.count > 0 %}
    <h2>Список пользователей</h2>
    <table>
        <thead align="center">
            <tr>
                <th width="10%">Id</th>
                <th width="30%">Имя</th>
                <th width="10%">Возраст</th>
                <th width="50%">Действие</th>
            </tr>
        </thead>
        <tbody align="center">
        {% for person in people %}
            <tr>
                <td>{{ person.id }}</td>
                <td>{{ person.name }}</td>
                <td>{{ person.age }}</td>
                <td><a href="edit/{{ person.id }}">Изменить</a> | <a href="delete/{{ person.id }}">Удалить</a></td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
{% endif %}
</body>
</html>


И наконец, в файле urls.py, свяжем маршруты с функциями-представлениями:

from django.urls import path
from crud import views

urlpatterns = [
    path('', views.index),
    path('create/', views.create),
]


Что ж, у нас всё готово, и можно запустить приложение. При первом запуске мы получим страницу, которая будет иметь вид, представленный на рисунке:

Попробуем добавить нескольких клиентов. Когда пользователь введёт данные нескольких клиентов(пользователей), информация о них будет получена из БД и отображена на главной странице:

Если мы теперь, с использованием менеджера SQLiteStudio, откроем содержимое таблицы crud_person, то увидим в ней данные о клиентах, которые мы занесли в БД с помощью созданного нами приложения:


Как можно видеть, мы добились свой цели, т. е. занесли информацию в БД через интерфейс НТМL-страницы. При этом мы использовали два метода: Person.objects.all()(получение информации из БД) и person.save()(запись информации о клиентах в БД).


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
Комментарий закреплён

Понравилась задача, тест или урок? Поставьте лайк, поддержите курс. Ваша поддержка очень важна для нас.

Комментарий закреплён

Как заполнить константные модели (например, словарь единиц измерений, или список поддерживаемых языков) данными без участия пользователя? Через форму долго и неудобно. Можно ли заранее известные данные поместить в таблицы на этапе makemigrations - migrate  ?

@Ольга_Миронова, Если правильно вас понял, то можно воспользоваться фикстурами https://docs.djangoproject.com/en/5.0/howto/initial-data/

@Илья_Перминов, Спасибо! Это то, что надо.

@Ольга_Миронова, можно добавить функцию в файл миграции, которая поместит эти данные в нужную таблицу. Так-же можно создать фикстуру с этими данными и загрузить данные командой python manage.py loaddata fixture_name.json.

Вот пример добавления данных с помощью миграций.

Сначала создадим пустую миграцию для приложения main_app:

python manage.py makemigrations --empty main_app


В результате создался файл миграции main_app\migrations\0002_auto_20240305_1033.py с таким содержимым:

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('main_app', '0001_initial'),
    ]

    operations = [
    ]


Добавим в него функцию load_initial_data() для загрузки данных:

from django.db import migrations

def load_initial_data(apps, schema_editor):
    data = [
        {'name': 'Дмитрий', 'age': 39, 'phone': '+79123456789', 'email': 'dmitry@email.com' },
        {'name': 'Павел',   'age': 45, 'phone': '+79234567891', 'email': 'pavel@pavel.com'  },
        {'name': 'Алексей', 'age': 29, 'phone': '+79345678912', 'email': 'alexey@mail.com'  },
        {'name': 'Иван',    'age': 35, 'phone': '+79456789123', 'email': 'ivan@my-site.com' },
        {'name': 'Денис',   'age': 24, 'phone': '+79567891234', 'email': 'admin@site.com'   },
    ]
    user = apps.get_model('main_app', 'User')
    [user.objects.create(**kwargs) for kwargs in data]

class Migration(migrations.Migration):

    dependencies = [
        ('main_app', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(load_initial_data),
    ]


После этого можно применить миграцию:

python manage.py migrate


Данные успешно загрузились в таблицу:

@Дмитрий_Селезнев, спасибо! Я, пока есть время, параллельно делаю маленький проект-презентацию на тему "Зачем нам нужен Django". Модели уже помогли мне  одну из безумных схем БД с огромным количеством связей (достались по наследству от админа-ораклоида) превратить в маленькое симпатичное деревце. В случае успеха, дирекция официально выделит мне время на погружение в джанго. В курсе есть почти все, что нужно для этого, в том числе веб-сокеты и докеры. Еще бы генератор отчетов.... :)

@Дмитрий_Селезнев,  спасибо большое-пребольшое) Так приятно, что не надо лазить по гуглу) Спасибо! 

Для полного понимания я бы вот здесь добавил бы примерно следующее:

..... далее через класс временной переадресации HttpResponseRedirect перенаправляем данные по пути "/" т.е. в корень проекта, где они согласно маршрута по умолчанию будут обрабатываться функцией index() которая в свою очередь отобразит их на главной странице сайта через форму шаблона index.html

(Поправьте меня пожалуйста если что-то не то написал, но мне этот момент был не понятен)

@Максим_Михеев, Все верно написали, исправили.

А как работает вот эта строка? <td><a href="edit/{{ person.id }}">Изменить</a> | <a href="delete/{{ person.id }}">Удалить</a></td>

Куда ведет путь ''edit/2' например? или это в качестве простого примера, и мы можем реализовать представление этого пути?

@Ilia_Boiarintsev, UPD: ответ на следующей странице)))