Luis Silva
Luis Silva

Reputation: 173

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

I've created a maintenance App that allows the user to create and view the maintenance details. I have a page "maintenance-details.html" where I show all the details of a particular maintenance.

Here is my 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

I have created a button on my template named "Mark as done". My Maintenance model has a BooleandField "done" with the purpose to set the task as done or not. What I'm looking for is the best way to update the model and set the "done" as "True" when the user clicks it.

My models.py here:

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()

What is the right way to do this?

Upvotes: 1

Views: 1751

Answers (2)

lieahau
lieahau

Reputation: 518

you still can use post method inside DetailView.
assuming this is your template:

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

then inside your DetailView:

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

if you don't want to reload the page after user click the button, use ajax instead of regular form in your template.

Upvotes: 1

HenryM
HenryM

Reputation: 5793

Assuming you have a form with button something like this in your template:

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

Then you need urls.py to include the url named 'done'

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

and in your views file

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

Upvotes: 1

Related Questions