1

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?

Luis Silva
  • 173
  • 13

2 Answers2

1

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')
HenryM
  • 5,557
  • 7
  • 49
  • 105
  • Should that 'done' function be used with FormMixin inside my DetailView, like the example here: [https://stackoverflow.com/questions/45659986/django-implementing-a-form-within-a-generic-detailview] – Luis Silva Aug 26 '19 at 20:33
  • I've just used a function here rather than a class view so no – HenryM Aug 27 '19 at 12:09
  • Henry it worked like a charm, but I'm still trying to understand this. Wouldn't it be a good practice to include that function inside my class? Thanks! – Luis Silva Sep 01 '19 at 17:56
  • How to do this to accept a models foreign key to a user, and make the `user.is_active = True` when clicking the button? Using a `DetailView` with the model = a model with the foreign key that has a user to it. – AnonymousUser Sep 27 '21 at 05:18
1

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.

lieahau
  • 498
  • 4
  • 9