Как в Django создать форму для обновления данных существующего объекта модели?

Ответ

В Django для обновления данных существующего объекта модели используется класс ModelForm. Он автоматически создает поля формы на основе полей модели, обрабатывает валидацию и сохранение данных, что значительно сокращает количество кода.

Почему ModelForm? Это стандартный и наиболее эффективный способ, так как он тесно интегрирует вашу форму с моделью данных, избавляя от необходимости вручную описывать поля и логику сохранения.

Основные шаги:

  1. Модель данных (models.py) Определяем модель, объекты которой будем редактировать.

    from django.db import models
    
    class UserProfile(models.Model):
        username = models.CharField(max_length=100)
        email = models.EmailField()
  2. Форма (forms.py) Создаем ModelForm, указывая модель и поля для редактирования.

    from django import forms
    from .models import UserProfile
    
    class EmailUpdateForm(forms.ModelForm):
        class Meta:
            model = UserProfile
            fields = ['email'] # Указываем только те поля, которые нужно изменить
  3. Представление (views.py) Это ключевая логика. Мы получаем объект, передаем его в форму через аргумент instance и обрабатываем POST-запрос.

    from django.shortcuts import render, redirect, get_object_or_404
    from .forms import EmailUpdateForm
    from .models import UserProfile
    
    def update_email(request, pk):
        # Получаем объект, который нужно обновить, или возвращаем 404
        profile = get_object_or_404(UserProfile, pk=pk)
    
        if request.method == 'POST':
            # Если форма отправлена, передаем данные и instance для обновления
            form = EmailUpdateForm(request.POST, instance=profile)
            if form.is_valid():
                form.save() # Сохраняет изменения в объекте profile
                return redirect('success_url') # URL для редиректа после успеха
        else:
            # Если это GET-запрос, создаем форму с текущими данными объекта
            form = EmailUpdateForm(instance=profile)
    
        return render(request, 'update_email.html', {'form': form})
  4. Шаблон (update_email.html) Простая HTML-форма для отображения.

    <form method="post">
        {% csrf_token %} <!-- Обязательный токен для безопасности -->
        {{ form.as_p }}   <!-- Рендерит поля формы в тегах <p> -->
        <button type="submit">Обновить email</button>
    </form>

Ответ 18+ 🔞

А, ну это же про то, как в Джанге записи в базе менять! Да, блядь, классика жанра, каждый второй проект этим страдает. Слушай, а ведь это реально просто, если не выебываться и использовать ModelForm. Это как волшебная палочка, только для задротов.

Ну и нахуя этот ModelForm вообще? А нахуя руками-то всё прописывать, если можно заставить фреймворк работать за тебя? Он сам поля нарисует, сам проверит, что ты там ввёл, и сам в базу запишет. Красота, ёпта! Просто говоришь: «Вот модель, вот поля — работай, сука!»

Как это делается, по шагам:

  1. Моделька (models.py) Ну, тут всё как обычно, создаём какую-нибудь сущность, которую будем мучать.

    from django.db import models
    
    class UserProfile(models.Model):
        username = models.CharField(max_length=100)
        email = models.EmailField()
  2. Формочка (forms.py) Вот тут магия начинается. Берёшь ModelForm и натравливаешь его на свою модель.

    from django import forms
    from .models import UserProfile
    
    class EmailUpdateForm(forms.ModelForm):
        class Meta:
            model = UserProfile
            fields = ['email'] # Говоришь конкретно: «Меняй только почту, остальное не трожь!»
  3. Вьюшка (views.py) А вот тут, блядь, самое важное! Главный фокус — это instance. Без него будет создаваться новая запись, а нам-то надо старую поменять!

    from django.shortcuts import render, redirect, get_object_or_404
    from .forms import EmailUpdateForm
    from .models import UserProfile
    
    def update_email(request, pk):
        # Сначала находим ту самую жертву, которую будем редактировать. Или 404, если её нет.
        profile = get_object_or_404(UserProfile, pk=pk)
    
        if request.method == 'POST':
            # Если юзер что-то прислал, суём данные И объект в форму. Ключевое слово — instance!
            form = EmailUpdateForm(request.POST, instance=profile)
            if form.is_valid():
                form.save() # Блядь, и всё! Сохранилось само!
                return redirect('success_url') # И пошли нахуй с этой страницы
        else:
            # Если просто зашли посмотреть, показываем форму с уже заполненными данными объекта.
            form = EmailUpdateForm(instance=profile)
    
        return render(request, 'update_email.html', {'form': form})

    Видишь? instance=profile — вот он, секретный ингредиент! Без него будет пиздец, а не обновление.

  4. Шаблон (update_email.html) Тут вообще зашибись, можно даже не думать.

    <form method="post">
        {% csrf_token %} <!-- Эта хуйня обязательна, а то Джанга обидится! -->
        {{ form.as_p }}   <!-- А это просто вывалит все поля в параграфах -->
        <button type="submit">Обновить email</button>
    </form>

Вот и вся магия, ебать мои старые костыли. Главное — не забыть передать instance в форму, когда обрабатываешь POST, а то будешь потом чесать репу, почему новые юзеры создаются, а старые не меняются. Проверено на собственных граблях, хуле.