George B
George B

Reputation: 25

How to perform calculations in Django class-based views?

I used Django class-based views to create a simple web application. In this app, a user submits length and width of a building, the app calculates the area and stores it in the database. After submission the user is redirected to the 'results' page where he can see his inputs and result.

I'm not sure how to implement such calculation function in generic views.

My Models:

from django.db import models


class Building(models.Model):

    length = models.IntegerField(default=1)
    width = models.IntegerField(default=1)
    area = models.IntegerField(default=1)

    def __str__(self):
        return self.name

My Forms:

from django import forms
from .models import Building

class BuildingForm(forms.ModelForm):
    class Meta:
        model = Building
        fields = ('length', 'width', 'area')

My Views:

from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse, reverse_lazy
from .models import Building
from .forms import BuildingForm
from django.http import HttpResponseRedirect, HttpResponse


class BuildingListView(ListView):
    model = Building
    context_object_name = 'buildings'


class BuildingCreateView(CreateView):
    model = Building
    form_class = BuildingForm
    success_url = reverse_lazy('results')


class BuildingUpdateView(UpdateView):
    model = Building
    form_class = BuildingForm
    success_url = reverse_lazy('building_changelist')


def calculation(request):

    length = request.POST.get('length', False)
    width = request.POST.get('width', False)
    area = length * width
    Building.objects.create(length=length, width=width, area=area,)

    return HttpResponseRedirect(reverse('results'))

Can someone share a good example related to my question, or help me to implement this function in my views file?

Upvotes: 0

Views: 3801

Answers (1)

jTiKey
jTiKey

Reputation: 743

You'd do this in the .form_is_valid() method:

class BuildingCreateView(CreateView):
    model = Building
    form_class = BuildingForm
    success_url = reverse_lazy('results')

    def form_valid(self, form):
        resp = super().form_valid(form)
        form.instance.area = form.length * form.width
        form.save()
        return resp

But it's good to do calculations in the models (it will save the area each time you save the model):

class Building(models.Model):

    length = models.IntegerField(default=1)
    width = models.IntegerField(default=1)
    area = models.IntegerField(default=1)

    def __str__(self):
       return self.name

    def save(self, *args, **kwargs):
       self.area = self.length * self.width 
       super().save(*args, **kwargs)

Or even make it be calculated each time it's called, with no need to save it into the database:

class Building(models.Model):

    length = models.IntegerField(default=1)
    width = models.IntegerField(default=1)

    def __str__(self):
       return self.name

    @property
    def area(self):
       return self.lenght * self.width

Upvotes: 4

Related Questions