Here is my first project in which I am experimenting with the Django documentation: a Person
model. and two featured views (one to create a person and the other to view the list of created persons). So far a person has only two CharFields
, first_name
and last_name
.
What I'd like to do now is to implement a BooleanField
adult
, which returns True
if the difference between today's date and the date of birth is greater than or equal to, say, 18 (or 16, it doesn't matter).
Possibly I would also implement an attribute age
based on the same principles.
Obviously, it would be perfectly ok to derive adult
from age
.
How can this be implemented in Django? Where should I write the piece of code that makes the math to derive adult/age
? Inside models.py, forms.py, views.py or maybe inside the template?
P.S. I know it looks weird to see the age
attribute been declared as a DurationField, but as I was saying I am trying to experiment with different attribute fields. If the answer to my question requires it to be changed into, say, PositiveInteger
, I don't mind changing it.
My models.py looks like this
from django.db import models
# Create your models here.
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=30)
adult = models.BooleanField(default=False)
date_of_birth = models.DateField(default=None)
created_on = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_on = models.DateTimeField(auto_now_add=False, auto_now=True)
age = models.DurationField(default=None)
my forms.py is the following
from django import forms
from .models import Person
class CreatePersonForm(forms.ModelForm):
class Meta:
model = Person
fields = [
'first_name',
'last_name',
'adult',
'date_of_birth',
'age',
]
And here is my views.py
from django.shortcuts import render
from .models import Person
from .forms import CreatePersonForm
# Create your views here.
def home_view(request):
return render(request, 'home.html')
def persons_list_view(request):
persons = Person.objects.all()
context = {
'persons': persons
}
return render(request, 'persons_list.html', context)
def create_person_view(request):
if request.method == 'POST':
form = CreatePersonForm(request.POST)
persons = Person.objects.all()
context = {
'persons': persons
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'persons_list.html', context)
else:
form = CreatePersonForm()
context = {'form': form}
return render(request, 'create_person.html', context)
Thanks for any help in advance
EDIT
I had a go at writing the subtraction in views.py (as suggested), and ran all the migrations, but when I try to create a new person on the localhost I get the following error:
Exception Type: TypeError
Exception Value:
unsupported operand type(s) for -: 'DeferredAttribute' and 'DeferredAttribute'
which seems to be caused by this line of code if (Person.date_today - Person.date_of_birth) >= 18:
.
I have also tried this solution, which involves models.py rather than views.py, but I get the same error. I am also, trying to find something on the Django documentation, but I have to say it's not really 'beginners friendly'.
Probably I should mention that I only have a basic Python knowledge, and I might be pushing things a bit too far.
I forgot to upload the code I have written:
def create_person_view(request):
if (Person.date_today - Person.date_of_birth) >= 18:
Person.adult=True
if request.method == 'POST':
form = CreatePersonForm(request.POST)
persons = Person.objects.all()
context = {
'persons': persons
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'persons_list.html', context)
else:
form = CreatePersonForm()
context = {'form': form}
return render(request, 'create_person.html', context)
And this is what I assed in models.py
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=30)
adult = models.BooleanField(default=False)
date_of_birth = models.DateField(default=None)
date_today = models.DateField(auto_now=True)
EDIT 2
I am now trying this solution from the python documentation (in the methods section, rearranging the baby boomer status), which, however, does the calculation inside models.py rather than views.py (as suggested in the comments to this question).
So I have tried something like:
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=30)
adult = models.BooleanField(default=False)
date_of_birth = models.DateField(default=None)
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
def is_adult(self):
import datetime
if (datetime.date.today() - self.date_of_birth) > datetime.timedelta(days=18*365):
self.adult = True
This time I don't get any error, but when I try to create a person born on 1985-04-28 with the admin and save it, adult remains false. Does anyone have any idea of how to actually implement this?