Заполнение формы FormMixin

Можно ли заполнить данные формы FormMixin, не передавая переменную формы в шаблон? У меня есть шаблон, но я не понимаю, как создать форму с помощью Django, поэтому я просто указываю атрибут name в шаблоне. Форма создается, все хорошо, я переопределяю метод
get_initial(), но форма не заполняется Возможно ли это сделать или мне нужно передать переменную формы?

class CommentEditView(View, FormMixin):
    form_class = EditCommentForm

    def get_initial(self):
        initial = super().get_initial()
        comment = get_object_or_404(Comment, pk=15)
        
        initial['review_text'] = comment.review_text
        initial['grade'] = comment.grade

        return initial

    def get(self, request, comment_id):
        return render(request, 'catalog/review-edit.html')
class EditCommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ['review_text', 'grade']
<form method="POST">
                    {% csrf_token %}
                    <textarea class="product-detail-reviews-textarea" name="review_text" id="id_review_text"></textarea>
                    {% for error in form.review_text.errors %}
                        <p class="product-detail-reviews-error">* {{ error }} </p>
                    {% endfor %}
                    <div class="product-detail-reviews-row">
                        <div class="product-detail-reviews-stars">
                            <p>Stars:</p>
                            <div class="rating-area">
                                <input type="radio" id="id_grade_five" name="grade" value="5">
                                <label for="id_grade_five" title="Star «5»"></label>    
                                <input type="radio" id="id_grade_four" name="grade" value="4">
                                <label for="id_grade_four" title="Star «4»"></label>    
                                <input type="radio" id="id_grade_three" name="grade" value="3">
                                <label for="id_grade_three" title="Star «3»"></label>  
                                <input type="radio" id="id_grade_two" name="grade" value="2">
                                <label for="id_grade_two" title="Star «2»"></label>    
                                <input type="radio" id="id_grade_one" name="grade" value="1">
                                <label for="id_grade_one" title="Star «1»"></label>
                            </div>
                        </div>
                        <button type="submit" class="product-detail-reviews-link">Confirm</a>
                    </div>
                    {% for error in form.grade.errors %}
                        <p class="product-detail-reviews-error">*{{ error }} </p>
                    {% endfor %}
        </form>

Переопределенный метод get_initial()

Вы выводите поля вручную, поэтому вам также нужно позаботиться о том, чтобы включить начальные значения для этих полей. Например, для review_text

<textarea class="product-detail-reviews-textarea" name="review_text" id="id_review_text">{{ form.review_text.initial }}</textarea>

Если вы просто хотите добавить несколько CSS-классов к элементам формы, лучше объявить их в виджетах, как описано здесь, или в форме Meta, как описано здесь. Например:

class EditCommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ["review_text", "grade"]
        widgets = {"review_text": Textarea(attrs={"class": "product-detail-reviews-textarea"})}

Таким образом, вы можете позволить django делать большую часть рендеринга:

{{ form.review_text }}
{% for error in form.review_text.errors %}
  <p class="product-detail-reviews-error">* {{ error }} </p>
{% endfor %}

Кроме того, подумайте о том, чтобы включить метки для элементов управления формы. Они предлагают больше, чем просто описание поля:

  • Текст метки не только визуально связан с соответствующим текстовым вводом, он также связан с ним программно. Это означает, что, например, программа чтения с экрана будет считывать метку, когда пользователь сосредоточен на вводе формы, облегчая пользователю вспомогательных технологий понимание того, какие данные следует ввести.
  • Когда пользователь щелкает или касается метки, браузер передает фокус на связанный с ней ввод (результирующее событие также поднимается для ввода). Увеличение области попадания для фокусировки ввода дает преимущество всем, кто пытается его активировать, включая тех, кто использует устройство с сенсорным экраном.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label

Вы не передаете форму в контекст, в этом и заключается проблема. Не переопределяйте .get(…): FormMixin добавит элемент в контекст да, но, переопределив метод .get(…) и просто отобразив шаблон, он даже не построит контекст.

Вы можете позволить TemplateView сделать работу за вас: это сгенерирует контекст, а затем отобразит шаблон:

from django.views.generic import TemplateView


class CommentEditView(FormMixin, TemplateView):
    form_class = EditCommentForm
    template_name = 'catalog/review-edit.html'

    def get_initial(self):
        initial = super().get_initial()
        comment = get_object_or_404(Comment, pk=15)

        initial['review_text'] = comment.review_text
        initial['grade'] = comment.grade

        return initial

    # no def get(self, request, comment_id)

Что касается шаблона, то вы загружаете данные из формы в шаблон, например, так:

<textarea class="product-detail-reviews-textarea" name="review_text" id="id_review_text">
    {{ form.review_text.widget.value }}
</textarea>

Если бы у меня было гипотетическое приложение под названием "myapp", я бы:

  1. Направьте корневой urls.py на urls.py myapp'а, используя include:
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls'))
]
  1. Возможно, модель выглядит так:
class Comment(models.Model):
    review_title = models.CharField(max_length=100)
    review_text = models.TextField(max_length=1000)
    grade = models.IntegerField(validators=[
        MinValueValidator(1), MaxValueValidator(5)
    ])

    def __str__(self):
        return str(self.review_title)

    def get_absolute_url(self):
        return reverse('myapp:comment-detail', kwargs={"pk": self.pk})

  1. У меня будет несколько url-путей:
from django.urls import path
from myapp.views import (
    CommentListView, CommentCreateView,
    CommentUpdateView, CommentDetailView
)

app_name = "myapp"
urlpatterns = [
    path('', CommentListView.as_view(), name='comment-list'),
    path('create/', CommentCreateView.as_view(), name='comment-create'),
    path('edit/<int:pk>/', CommentUpdateView.as_view(), name='comment-edit'),
    path('comment/<int:pk>/', CommentDetailView.as_view(), name='comment-detail'),
]
  1. views.py будет выглядеть следующим образом:
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views.generic import (
    ListView, DetailView, CreateView, UpdateView
)

from myapp.forms import EditCommentForm
from myapp.models import Comment


class CommentListView(ListView):
    template_name = 'catalog/comments-list.html'
    model = Comment

class CommentCreateView(CreateView):
    template_name = 'catalog/comment-form.html'
    form_class = EditCommentForm

    def form_valid(self, form):
        self.object = form.save()
        return HttpResponseRedirect(self.object.get_absolute_url())

class CommentUpdateView(UpdateView):
    template_name = 'catalog/comment-form.html'
    form_class = EditCommentForm
    model = Comment

class CommentDetailView(DetailView):
    template_name = 'catalog/comment-detail.html'
    model = Comment
  1. Сделайте три шаблона:

catalog/comments-list.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div>
    <div><a href="{% url 'myapp:comment-create' %}">Create</a></div>
    <h2>Comments</h2>
    {% for comment in object_list %}
      <div>
        <a href="{% url 'myapp:comment-detail' comment.pk %}">{{ comment.review_title }}</a>
      </div>
    {% endfor %}
  </div>
</body>
</html>

catalog/comment-form.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div style="margin: 100px auto; width: 400px;">
    <form method="POST">
      {% csrf_token %}
      {{ form.as_div }}
      <input type="submit" class="product-detail-reviews-link" value="Confirm">
    </form>
  </div>
</body>
</html>

catalog/comment-detail.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div>
    <h2>The Review</h2>
    <div>{{ object.review_title }}</div>
    <div>{{ object.review_text }}</div>
    <div>{{ object.grade }}</div>
    <a href="{% url 'myapp:comment-list' %}">back to list</a>
    <a href="{% url 'myapp:comment-edit' object.pk %}">edit comment</a>
  </div>
</body>
</html>

Это должно проиллюстрировать, как работают формы, как создавать новые экземпляры и редактировать их. Надеюсь, это поможет.

Вернуться на верх