Set declined to True if approved is False

huangapple go评论65阅读模式
英文:

Set declined to True if approved is False

问题

我正在进行一个项目,允许学生申请从图书馆借书,然后图书管理员决定批准或拒绝请求。

models.py

class PendingRequest(models.Model):
    book_request = models.ForeignKey(Borrow, on_delete=models.CASCADE, null=True)
    member = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True)
    book = models.ForeignKey(Books, on_delete=models.CASCADE, default=None, null=True)
    approved = models.BooleanField(default=False)
    declined = models.BooleanField(default=False)
    approval_date = models.DateTimeField(auto_now=True, null=True)

我正在使用modelformset_factory来呈现上述模型的多个实例的表单。我想要实现的是,当图书管理员不批准请求时,能够将declined字段设置为True,将approved设置为False

views.py

def approve(request, pk):
    member = get_object_or_404(User, id=pk)
    pending_requests = PendingRequest.objects.filter(member=member)
    PendingRequestFormSet = modelformset_factory(
        PendingRequest, form=ApproveForm, extra=0
    )
    if request.method == "POST":
        formset = PendingRequestFormSet(request.POST, queryset=pending_requests)
        approved = request.POST.get(formset.prefix + "-approved")
        if formset.is_valid():
            instances = formset.save(commit=False)
            for instance in instances:
                instance.book_request = instance.book_request
                instance.member = instance.member
                instance.book = instance.book
                instance.save()
    else:
        formset = PendingRequestFormSet(queryset=pending_requests)
    context = {"formset": formset, "member": member}
    return render(request, "books/approve.html", context)

form.py

class ApproveForm(forms.ModelForm):
    approved = forms.BooleanField(required=False)
    class Meta:
        model = PendingRequest
        fields = [
            "approved",
            "book",
        ]

template

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Approve Request</title>
  </head>
  <body>
    <h1>Update Pending Requests for {{ member.username }}</h1>

    <form method="post">
      {% csrf_token %} 
      {{ formset.management_form }}
      <table>
        <thead>
          <tr>
            <th>Book</th>
            <th>Approved</th>
          </tr>
        </thead>
        <tbody>
          {% for form in formset %}
          <tr>
            <td>{{form.book}}</td>
            <td>{{form.approved}}</td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
      <input type="submit" value="Update" />
    </form>
    <style>
      select {
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        background: transparent;
        border: none;
        font-size: 15px;
      }
      select {
        pointer-events: none;
      }
    </style>
  </body>
</html>
英文:

I am working on a project that allows student to apply to borrow book from a library and then the librarian decides to approve or decline the request.

models.py

class PendingRequest(models.Model):
    book_request = models.ForeignKey(Borrow, on_delete=models.CASCADE, null=True)
    member = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True)
    book = models.ForeignKey(Books, on_delete=models.CASCADE, default=None, null=True)
    approved = models.BooleanField(default=False)
    declined = models.BooleanField(default=False)
    approval_date = models.DateTimeField(auto_now=True, null=True)

I am using a modelformset_factory to render out the form to update multiple instance of the above model. What i want to achieve is to be able to set declined field to True and approved to False whenever the librarian doesn't approve the request

views.py

def approve(request, pk):
    member = get_object_or_404(User, id=pk)
    pending_requests = PendingRequest.objects.filter(member=member)
    PendingRequestFormSet = modelformset_factory(
        PendingRequest, form=ApproveForm, extra=0
    )
    if request.method == &quot;POST&quot;:
        formset = PendingRequestFormSet(request.POST, queryset=pending_requests)
        approved = request.POST.get(formset.prefix + &quot;-approved&quot;)
        if formset.is_valid():
            instances = formset.save(commit=False)
            for instance in instances:
                instance.book_request = instance.book_request
                instance.member = instance.member
                instance.book = instance.book
                instance.save()
    else:
        formset = PendingRequestFormSet(queryset=pending_requests)
    context = {&quot;formset&quot;: formset, &quot;member&quot;: member}
    return render(request, &quot;books/approve.html&quot;, context)

form.py

class ApproveForm(forms.ModelForm):
    approved = forms.BooleanField(required=False)
    class Meta:
        model = PendingRequest
        fields = [
            &quot;approved&quot;,
            &quot;book&quot;,
        ]

template

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Approve Request&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Update Pending Requests for {{ member.username }}&lt;/h1&gt;

    &lt;form method=&quot;post&quot;&gt;
      {% csrf_token %} 
      {{ formset.management_form }}
      &lt;table&gt;
        &lt;thead&gt;
          &lt;tr&gt;
            &lt;th&gt;Book&lt;/th&gt;
            &lt;th&gt;Approved&lt;/th&gt;
          &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
          {% for form in formset %}
          &lt;tr&gt;
            &lt;td&gt;{{form.book}}&lt;/td&gt;
            &lt;td&gt;{{form.approved}}&lt;/td&gt;
          &lt;/tr&gt;
          {% endfor %}
        &lt;/tbody&gt;
      &lt;/table&gt;
      &lt;input type=&quot;submit&quot; value=&quot;Update&quot; /&gt;
    &lt;/form&gt;
    &lt;style&gt;
      select {
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        background: transparent;
        border: none;
        font-size: 15px;
      }
      select {
        pointer-events: none;
      }
    &lt;/style&gt;
  &lt;/body&gt;
&lt;/html&gt;

答案1

得分: 0

我们在评论中的朋友指的是approveddeclined字段是互斥的。您只需要其中一个来指示特定的状态。

class PendingRequest(models.Model):
    ...
    approved = models.BooleanField(default=False)
    declined = models.BooleanField(default=False)
    ...

关于您的问题。表单未验证是因为需要id字段,因此需要添加它们:

forms.py

class ApproveForm(forms.ModelForm):
    approved = forms.BooleanField(required=False)
    class Meta:
        model = PendingRequest
        fields = [
            "id",
            "approved",
            "book",
        ]
        widgets = {
            "id": forms.HiddenInput()
        }

还需要在templates.py中添加:

...
<tbody>
  {% for form in formset %}
  <tr>
    {{form.id}}
    <td>{{form.book}}</td>
    <td>{{form.approved}}</td>
  </tr>
  {% endfor %}
</tbody>
...

以及在views.py中:

if request.method == "POST":
    formset = PendingRequestFormSet(request.POST, queryset=pending_requests)
    for form in formset:
        if form.is_valid():
            if form.cleaned_data['approved']:
                form.save()

这将在更新时将approved字段设置为TrueFalse。如果您要保留declined字段,只需按照相同的过程将其添加到forms.pt中,尽管我建议将其删除。

英文:

Our friend in comments meant that approved and declined fields are mutually exclusive. You only need one of them to indicate that specific status.

class PendingRequest(models.Model):
    ...
    approved = models.BooleanField(default=False)
    declined = models.BooleanField(default=False)
    ...

Related to you question. Form is not validating because id field is required, so add them in:

forms.py

class ApproveForm(forms.ModelForm):
    approved = forms.BooleanField(required=False)
    class Meta:
        model = PendingRequest
        fields = [
            &quot;id&quot;,
            &quot;approved&quot;,
            &quot;book&quot;,
        ]
        widgets = {
            &quot;id&quot;: forms.HiddenInput()
        }

and also in templates.py

...
&lt;tbody&gt;
  {% for form in formset %}
  &lt;tr&gt;
    {{form.id}}
    &lt;td&gt;{{form.book}}&lt;/td&gt;
    &lt;td&gt;{{form.approved}}&lt;/td&gt;
  &lt;/tr&gt;
  {% endfor %}
&lt;/tbody&gt;
...

and views.py

if request.method == &quot;POST&quot;:
    formset = PendingRequestFormSet(request.POST, queryset=pending_requests)
    for form in formset:
        if form.is_valid():
            if form.cleaned_data[&#39;approved&#39;]:
                form.save()

That will set approved field to True or False on update click. If you want to maintain declined field then just add to forms.pt as a hidden field using the same process, although I would recommend to remove it.

huangapple
  • 本文由 发表于 2023年2月19日 18:19:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499413.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定