如何通过单击按钮更新 DetailView 中的模型字段

How can I update a Model field inside DetailView with a button click

我创建了一个维护应用程序,允许用户创建和查看维护详细信息。我有一个页面 "maintenance-details.html",其中显示了特定维护的所有详细信息。

这是我的views.py:

class MaintenanceDetailView(DetailView):
    template_name = 'maintenance/maintenance-details.html'
    model = Maintenance

    def get_context_data(self, **kwargs):
        contacts_suppliers = ContactsSupplier.objects.filter(supplier__maintenance=self.object)
        hora_atual = datetime.datetime.now()
        context = super().get_context_data(**kwargs)
        context['contacts_supplier'] = contacts_suppliers
        context['hora_atual'] = hora_atual
        return context

我在我的模板上创建了一个名为 "Mark as done" 的按钮。我的维护模型有一个 BooleandField "done",目的是将任务设置为完成或未完成。我正在寻找的是更新模型并在用户单击时将 "done" 设置为 "True" 的最佳方法。

我的models.py在这里:

class Maintenance(models.Model):
    category = models.ForeignKey(SuppliersCategory, models.DO_NOTHING, db_column='Category')  # Field name made lowercase.
    property = models.ForeignKey(Property, models.DO_NOTHING, db_column='Property_Reference')  # Field name made lowercase.
    name = models.CharField(db_column='Name', max_length=25)  # Field name made lowercase.
    created_date = models.DateTimeField(db_column='Date', auto_now_add=True)  # Field name made lowercase.
    staffmember = models.CharField(db_column='StaffMember', max_length=25, blank=True, null=True)  # Field name made lowercase.
    supplier = models.ForeignKey(Suppliers, db_column='Supplier')  # Field name made lowercase.
    description = models.CharField(db_column='Description', max_length=500, blank=True, null=True)  # Field name made lowercase.
    photo = models.ImageField(upload_to='maintenace/', db_column='Photo', blank=True, null=True)  # Field name made lowercase.
    expirydate = models.DateTimeField(db_column='ExpiryDate', blank=False)  # Field name made lowercase.
    datecompletion = models.DateTimeField(db_column='DateCompletion', blank=True, null=True)  # Field name made lowercase.
    done = models.BooleanField(db_column='Done', default=False)  # Field name made lowercase.

    class Meta:
        db_table = 'Maintenance'

    def get_absolute_url(self):
        return reverse("maintenance:maintenance_detail",kwargs={'pk':self.pk})

    def set_done(self):
        self.done = True
        self.datecompletion = timezone.now()
        self.save()

正确的做法是什么?

假设您的模板中有一个带有按钮的表单:

<form method="post" action="{% url 'done' object.pk %}">
    <button type="submit">Done</button>
</form>

那么您需要 urls.py 来包含名为 'done'

的 url
path('/done/<int:pk>', views.done, name="done")

并在您的视图文件中

def done (request, pk):
    maintenance = Maintenance.objects.get(pk=pk)
    maintenance.set_done()
    return redirect ('url to your detail view')

您仍然可以在 DetailView 中使用 post 方法。
假设这是您的模板:

<form method="POST">
    <button type="submit" name="set_done">Done</button>
</form>

然后在您的 DetailView 中:

def post(self, request, *args, **kwargs):
    if "set_done" in request.POST:
        self.object.set_done()
        return HttpResponseRedirect(self.request.path_info)

如果您不想在用户单击按钮后重新加载页面,请在模板中使用 ajax 而不是常规表单。