Reputation: 25
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
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