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

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

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

Теперь добавим возможность редактирования и удаления объектов модели. Для этого продолжим работу с проектом из предыдущего шага.


Сначала добавим, в файл представлений 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('/')


# Изменение данных в БД
def edit(request, id):
    try:
        person = Person.objects.get(id=id)
        if request.method == 'POST':
            person.name = request.POST.get('name')
            person.age = request.POST.get('age')
            person.save()
            return HttpResponseRedirect('/')
        else:
            return render(request, 'edit.html', {'person': person})
    except Person.DoesNotExist:
        return HttpResponseNotFound('<h2>Person not found</h2>')


# Удаление данных из БД
def delete(request, id):
    try:
        person = Person.objects.get(id=id)
        person.delete()
        return HttpResponseRedirect('/')
    except Person.DoesNotExist:
        return HttpResponseNotFound('<h2>Person not found</h2>')


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

Функция edit() выполняет редактирование объекта. Она, в качестве параметра, принимает идентификатор объекта id из базы данных. В начале, по этому идентификатору, мы пытаемся получить объект из БД, с помощью метода Person.objects.get(id=id).

Поскольку, в случае отсутствия объекта, мы можем столкнуться с исключением DoesNotExist (объект не найден), то нужно обработать это исключение(если по каким-либо причинам мы получим несуществующий идентификатор).

И если объект найден не будет, пользователю вернется сообщение об ошибке 404 - через вызов return HttpResponseNotFound().

Когда объект найден, обработка будет делиться на две ветви:

1. Если поступит запрос POST, т. е. пользователь отправил новые (измененные) данные для объекта, мы сохраняем эти данные в БД и выполняем переадресацию на главную страницу.

2. Если поступит запрос GET, передаём пользователю шаблон edit.html с формой для редактирования объекта.

Функция delete() аналогичным образом находит объект и выполняет его удаление.


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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>CRUD - Редактирование</title>
</head>
<body>
    <form method="POST">
        {% 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>
</body>
</html>


Затем, в файле urls.py, сопоставим функции-представления edit() и delete() с маршрутами:

from django.urls import path
from crud import views


urlpatterns = [
    path('', views.index),
    path('create/', views.create),
    path('edit/<int:id>/', views.edit),
    path('delete/<int:id>/', views.delete),
]


Запустим проект. Теперь на главной странице рядом с каждым объектом (клиентом) будут работать две ссылки: Изменить и Удалить:

Попробуем изменить данные пользователя с id=1(http://127.0.0.1:8000/edit/1/), изменим его возраст:

Как мы видим, изменение данных пользователей прекрасно работает, и давайте под конец попробуем удалить пользователя с id=5:

В том, что клиент с id=5 действительно удален из БД, можно убедиться, если открыть таблицу crud_person с помощью SQLiteStudio:


В этом разделе мы создали свой первый CRUD-проект. Если у вас возникли трудности, вы можете посмотреть исходный код проекта на GitHub: https://github.com/Permin0ff/Course_CRUD_1.


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

Хотел спросить, а как можно сделать так, чтобы при удалении пользователя менялся и его id?
Например если у нас три пользователя, мы удаляем второго и третий становится на его место с id=2

@Daniil_Nagapetyan, нельзя так сделать.

Вопрос по материалам этого урока.
Как передаётся значение id?
Правильно ли я понимаю, что изначально этому способствует атрибут href (href="edit/{{ person.id }}">Изменить</a>) в html шаблоне (index.html), который передаёт id в url-адрес страницы, на которую нас перенаправляет (например: http://127.0.0.1:8000/edit/1/)? 

Затем значение id  принимается в urls.py (<int:id>) и передаётся в функцию в views соответственно.

@Aleksandr_Yolshin, да, всё правильно поняли. При выводе страницы мы генерируем ссылки для каждого пользователя, в которых задан id пользователя.

Подскажите пожалуйста, а как создавать поле slug через метод POST?
if request.method == "POST":
     person.name = request.POST.get("name")  # тут понятно
     person.slug = # а вот тут не очень.

@Руслан_Гаджиев, Например вот так:

from django.utils.text import slugify


if request.method == "POST":
     person.name = request.POST.get("name")
     person.slug = slugify(person.name)

@Илья_Перминов, Спасибо!)

@Илья_Перминов, Только это (slugify()) не работает для кириллицы

@Руслан_Гаджиев, Чтобы создавать слаги из строк, содержащий кириллицу, нужно добавить "транслитератор". Можно такой:

from unidecode import unidecode

person.slug = slugify(unidecode(str(person.name)))

unidecode нужно предварительно установить

@ilya_kutaev, Да, или через pytils.translit, там тоже есть slugify. В блоге 2.0 мы через нее это делаем.