Атрибут имени поля ввода идентичный modelform

Я пытаюсь просмотреть модель PendingRequest и проверить каждый запрос пользователя и одобрить или отклонить запрос пользователя для каждого экземпляра. Я использую ModelForm для отображения формы, однако, часть, которая вызывает проблему, заключается в том, что радиокнопка, на которую нужно нажать, чтобы одобрить или отклонить, не имеет общего входного имени attribue

вот мой шаблон

    <form method="post">
      {% csrf_token %}
      <table>
        <thead>
          <tr>
            <th>Book Title</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {% for book in books %}
          <tr>
            <td>{{ book.book.title }}</td>
            <td>
              <input type="radio" name="{{ book.id }}" value="approved"> Approve
              <input type="radio" name="{{ book.id }}" value="not_approved"> Decline
            </td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
      <button type="submit">Update</button>
    </form>     

Итак, что я хочу достичь, это заменить <input type="radio" name="{{ book.id }}" value="approved"> и <input type="radio" name="{{ book.id }}" value="not_approved"> следующим образом, чтобы при отображении каждый цикл имел одинаковый атрибут name, но разные значения

    <form method="post">
      {% csrf_token %}
      <table>
        <thead>
          <tr>
            <th>Book Title</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {% for book in books %}
          <tr>
            <td>{{ book.book.title }}</td>
            <td>
              {% for choice in form.approved %}
                {{choice.tag}}
              {% endfor %}
              {% for choice in form.not_approved %}
                {{choice.tag}}
              {% endfor %}
            </td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
      <button type="submit">Update</button>
    </form>     

вот мой forms.py

class Approve(forms.ModelForm):
    approved = forms.BooleanField(widget=forms.RadioSelect(choices=[(True, 'Approve')]))
    not_approved = forms.BooleanField(widget=forms.RadioSelect(choices=[(True, 'Decline')]))
    class Meta:
        model = PendingRequest
        exclude = ["member", "book_request", "book"]

models.py

class PendingRequest(models.Model):
    book_request = models.OneToOneField(BorrowBook, on_delete=models.CASCADE, null=True)
    member = models.ForeignKey(User, on_delete=models.CASCADE, default="", null=True)
    book = models.ForeignKey(Books, on_delete=models.CASCADE, default="", null=True)
    approved = models.BooleanField(default=False)
    not_approved = models.BooleanField(default=False)
    approval_date = models.DateTimeField(auto_now=True, null=True)

views.py

def approve(request, pk):
    books = PendingRequest.objects.filter(member__id=pk)
    if request.method == "POST":
        for book in books:
            form = Approve(request.POST, instance=book)
            if form.is_valid():
                    book.approve = form.cleaned_data.get(f'approve_{book.id}')
                    book.save()
            return redirect(index)
    else:
        form = Approve()
    return render(request, "books/approve.html", {"form": form, "books": books})

Вы немного усложняете себе задачу...

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

Вы также усложняете себе жизнь, имея два поля с радиокнопками с одной радиокнопкой в каждом поле. Радиокнопки предназначены для множественного выбора, допускается одно значение. Вы можете использовать две радиокнопки для одного поля (флажок часто лучше), но иметь две радиокнопки для двух отдельных полей - это не только плохой HTML, но вы, скорее всего, сможете выбрать оба поля сразу. Если вы дадите им одинаковые имена, чтобы предотвратить это, они не будут привязаны к нужному полю без множества странных пост-постовских заморочек. Это очень муторно. Я бы очень советовал использовать одно поле.

Независимо от того, последуете ли вы этому совету, для нескольких форм одной модели Django может справиться с этой ситуацией с помощью modelformset, что-то вроде...

views.py

PendingRequestFormSet = modelformset_factory(PendingRequest , form = Approve)
#we have to also bring in the book title along with the forms , even though we are not using it in the form,
# so we'll zip up the queryset with the formset.
# We use select_related in the queryset to prevent additional database calls in the template when the title gets evaluated
pending_requests = PendingRequest.objects.filter(member__id=pk).select_related('book')
formset = PendingRequestFormSet(queryset=pending_requests))
pending_requests_and_formset = zip(queryset, formset)
...
return render(request, "books/approve.html", {"form": form, "books": books, 'pending_requests_and_formset', pending_requests_and_formset })

template.html

 ...
 <form method="post">
     {{ formset.management_form }}
     {% for request, form in pending_requests_and_formset %}
        <td>{{request.book.title}}</td>
        <td>{{ form }}</td>
     {% endfor %}
 </form>
Вернуться на верх