Django Python how to implement my custom birth date function in views? - python

I write this python function for calculate age.
def age(birthdate):
today = date.today()
age = today.year - birthdate.year - ((today.month, today.day) < (birthdate.month, birthdate.day))
return age
result:
>>> print(age(date(1980, 1, 1)))
42
here is my code:
models.py
class CalculateAge(models.Model):
age = models.IntegerField(max_length=100)
date_of_birth = models.DateField()
user only pick the date of birth and I want age will be automatically calculate when submitting forms.
views.py
def CalculateAge(request):
if request.method == "POST":
patient_from = AddPatientFrom(request.POST or None)
if patient_from.is_valid():
patient_from.save()
how to implement this age function in my views.py and models.py?
I tried this in my views.py but didn't work.
if patient_from.is_valid():
pick_date = request.POST['date_of_birth']
find_age = age(date(pick_date))
print(find_age)
getting this error:
TypeError at /add-patient/ an integer is required (got type str)

You should work with the .cleaned_data [Django-doc] of the form: this will contain the data as date object:
if patient_from.is_valid():
pick_date = form.cleaned_data['date_of_birth']
find_age = age(age_y)
print(find_age)

Related

Django Class based view filtering queryset but not?

I have a bit of a challenge with the way a date filter is working:
Django Class based view, starting here https://github.com/varlenthegray/wcadmin/blob/master/customer/views.py#L61
class CustomersCustomReport(generic.ListView):
model = Customer
template_name = 'customer/reports/custom_report.html'
def get_queryset(self):
from_date = self.request.GET.get('fromDate')
to_date = self.request.GET.get('toDate')
self.queryset = Customer.objects.filter(is_active=True)
if from_date:
from_date = datetime.strptime(from_date, '%m-%d-%Y').strftime('%Y-%m-%d')
print("Checking date from " + from_date)
self.queryset.filter(next_service__gte=from_date)
if to_date:
to_date = datetime.strptime(to_date, '%m-%d-%Y').strftime('%Y-%m-%d')
print("Checking date to " + to_date)
self.queryset.filter(next_service__lte=to_date)
return self.queryset
I'm expecting this to return a filtered query based on the date that is a form field.
https://wcadmin.innovated.tech/customer/report/custom_report?fromDate=04-01-2022&toDate=04-30-2022
I know this data isn't filtered because the entire customer list is 521 entries of mock data that are active. I was following information from this question: How Can I Filter By Date Range Using Djangos Built in ListView?
I know it's getting data from the database, I know it's getting the date range I want from the URL due to the print, and the model is set to DateField for next_service, so I'm not quite sure what's going wrong here?
you need only a little changes:
def get_queryset(self):
from_date = self.request.GET.get('fromDate')
to_date = self.request.GET.get('toDate')
queryset = Customer.objects.filter(is_active=True) # change
if from_date:
from_date = datetime.strptime(from_date, '%m-%d-%Y').strftime('%Y-%m-%d')
print("Checking date from " + from_date)
queryset = queryset.filter(next_service__gte=from_date) # change
if to_date:
to_date = datetime.strptime(to_date, '%m-%d-%Y').strftime('%Y-%m-%d')
print("Checking date to " + to_date)
queryset = queryset.filter(next_service__lte=to_date) # change
return queryset # change

Django convert Date of Birth model field to Age

I have a Django class to convert the date of birth (dob) field in my model to age and annotate the result to a queryset.
class CalculateAge(Case):
def __init__(self, model, field, condition=None, then=None, **lookups):
today = date.today()
obj = model.objects.first()
field_object = model._meta.get_field(field)
field_value = field_object.value_from_object(obj)
bornyear = field_value.year
bornmonth = field_value.month
bornday = field_value.day
# something is wrong with the next two lines
age = [today.year - bornyear - ((today.month, today.day) < (bornmonth, bornday))]
return super().__init__(*age, output_field=IntegerField())
however when I try to pass the result to my queryset
queryset = Person.objects.all().annotate(age=CalculateAge(Person, 'dob')
I get the error
Positional arguments must all be When objects.
How can I get this to work?
There is an easier way. Just add a function on your model to get the age like this:
class ModelName(models.Model):
birth_date = models.DateField()
#other fields
def get_age(self):
age = datetime.date.today()-self.birth_date
return int((age).days/365.25)

how to get year from datefield at django?

i want to get year from birthday.
so i use self.birthday.year
but it make error.
how do i fix it?
best regards.
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(_("Name of User"), blank=True, max_length=255) #이름
gender = models.CharField(max_length=1, choices=CHOICES_GENDER) # 성
birthday = models.DateField(null=True) #생일
def calculate_age(self):
import datetime
return int((datetime.date.year - self.birthday.year) +1)
age = property(calculate_age) #나이
Try this solution,
from datetime import date
class User(AbstractUser):
name = models.CharField(_("Name of User"), blank=True, max_length=255)
gender = models.CharField(max_length=1, choices=CHOICES_GENDER)
birthday = models.DateField(null=True)
#property
def calculate_age(self):
if self.birthday:
today = date.today()
return today.year - self.birthday.year - ((today.month, today.day) < (self.birthday.month, self.birthday.day))
return 0 # when "self.birthday" is "NULL"
The problem is that datetime.date.year does not exists. You can fetch the year of a date (or datetime) object with .year, and you can thus for example use today() or now().
Semantically the function is incorrect as well. If I am born in 1984, then I am not per se 35 years old: that depends on whether the current year is before or after the day of birth (for example February 9th).
Finally there can be an error if the self.birthday value is None. In that case you probably want to return None as well.
So a potential solution for this is:
from datetime import date
class User(AbstractUser):
# ...
def calculate_age(self):
bd = self.birthday
if bd:
td = date.today()
return td.year - bd.year - ((td.month, td.day) < (bd.month, bd.day))
We thus first calculate today(), and then we return the current year minus the year of the birthday and minus one if today is still before the birthday this year.
In case the user did not specify his/her birthday, then the calculate_age(..) will return None (a value that can be interpreted as "unknown").
An issue that still remains (and is harder to fix) are timezones: since today in Australia is another today than in the United States, it is possible that - depending on where the server and users are located - the age of a user is one too high the day before his/her birthday, or one too low one day on his/her birthday. This is a harder problem to solve, since we have no information here where the user is located.

DJANGO avoid repeating date on DateTime calculation

I have managed to create a very simple model which allows me to subtract 2 DateTime fields, like so:
class Log(models.Model):
date = models.DateField()
take = models.DateTimeField()
land = models.DateTimeField()
tot = models.CharField(max_length=200, blank=True, default='00000')
def __str__(self):
return str(self.date)
def time_delta(self):
tdelta = self.land - self.take
return str(tdelta)
def save(self, *args, **kwargs):
self.tot = self.time_delta()
super(Log, self).save(*args, **kwargs)
My problem is the user would have to specify the date on every field. How could I make the fields take and land refer to date once and for all?
I don’t know how to do that in your Django model. I think you have to calculate the dates and times in your controller instead, and then register the values in your database.
You can do something like that with datetime.datetime.combine() function:
Return a new datetime object whose date components are equal to the given date object’s, and whose time components are equal to the given time object’s.
You have a reference date, for instance: today.
import datetime
date = datetime.date.today()
The user enter the takeoff time, you can combine this time with the reference date.
takeoff_time = datetime.time(8, 12)
takeoff_datetime = datetime.datetime.combine(date, takeoff_time)
print(takeoff_datetime.isoformat(" "))
# -> 2016-12-21 08:12:00
If the landing date is the same as the takeoff date, you can calculate the landing date/time with the same date reference:
landing_time = datetime.time(12, 37)
landing_datetime = datetime.datetime.combine(date, landing_time)
print(landing_datetime.isoformat(" "))
# -> 2016-12-21 12:37:00
Then, you can register the date, _takeoff_datetime_ and _landing_datetime_ in your database.
Note: you can do the same with the flight duration
I eventually managed to find a solution largely based on Laurent's answer so here it is,if that can ever help someone else:
from datetime import datetime
def calculation(self):
calc_take_off = datetime.combine(self.date, self.take)
calc_land = datetime.combine(self.date, self.land)
result = calc_land - calc_take_off
return str(result)
and then to save this in models:
def save(self, *args, **kwargs):
self.tot = self.calculation()
super(Log, self).save(*args, **kwargs)

Django - filtering in views

I am working on an basic application and I`m stuck at a displaying some info.
Please take a look:
Models:
class Companies(models.Model):
name = models.CharField()
address = models.CharField()
def __unicode__(self):
return self.name
class Payments(models.Model):
company = models.ForeignKey(Companies)
year = models.CharField(choices=YEAR)
month = models.CharField(choices=MONTHS)
date = models.DateField(auto_now_add=True)
I want a view in which to display ONLY the companies that did not pay the monthly fee.
So I`ve started like this:
def checks(request):
i = datetime.datetime.now()
an_c = i.strftime('%Y')
comp = Companies.objects.all()
pay1 = Payments.objects.filter(an=an_c, month='01')
But in the template I do not know how to filter the "comp" list.
I want to display in the template all the records from "comp" except that ones with the id/pk which can be find in the "pay1.company"
You wouldn't do that in the template. Do the whole thing in the view:
pay1 = Payments.objects.filter(an=an_c, month='01')
comp = Companies.objects.exclude(payments__in=pay1)
(Style note: Django model classes are usually named in the singular, not the plural.)

Categories

Resources