Average age from birth date in django - django

In my django(3.0.5) application I am trying to get average age from date of birth in a model. I am using MySql database.
Here is how I tried:
Model:
class ShippingStaff(models.Model):
full_name = models.CharField('Full Name', max_length=200)
birth_date = models.DateField('Date of Birth', null=True, blank=True)
Customer Filter:
#register.filter(name='age')
def age(bday, d=None):
if d is None:
d = datetime.date.today()
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
Views:
def home(request):
shipping_staff = ShippingStaff.objects.aggregate(staff_count=Count('full_name'),
avg_age=Avg(custom_time.age('birth_date'))
I get error like:
Exception Value:
'str' object has no attribute 'year'
Exception Location: /home/smrashel/jahaji/crewdatabd/templatetags/custom_time.py in age, line 31
which is
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
How can I solve this?
Any help will be much appreciated.

You need to change str to date. So you could use datetime.strptime like this:
from datetime import datetime
datetime_str = '08/12/12'
d = datetime.strptime(datetime_str, '%m/%d/%y')
print(d.year)
>>> 2012
In your case:
#register.filter(name='age')
def age(bday, d=None):
b = datetime.strptime(datetime_str, '%m/%d/%y')
if d is None:
d = datetime.date.today()
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
Of course it depends how your str date looks like, you need to adapt it to your needs

Related

Multiplying three models in django and getting the result in views

My model:
class VisData(models.Model):
visdata_id = models.AutoField(primary_key=True,blank=True)
user_name = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL,blank=True)
title = models.CharField(max_length=200, null=True,blank=True)
buy_sell = models.CharField(max_length=1, null=True,blank=True)
date = models.DateField(auto_now_add=False,null=True,editable=True,blank=True)
hour = models.TimeField(auto_now=False, auto_now_add=False,null=True,editable=True,blank=True)
shares_number = models.DecimalField(decimal_places=0,default=0,max_digits=999,null=True,blank=True)
course = models.DecimalField(decimal_places=2,default=0,max_digits=999,null=True,blank=True)
fare = models.DecimalField(decimal_places=2,default=0,max_digits=999,null=True,blank=True)
def __str__(self):
return self.title
I want to assign:
total_value = (shares_number * (course - fare)) and just print it in terminal
My views:
def summaryPage(request):
visdata = VisData.objects.all()
#print(visdata)
context = {}
return render(request, 'smth/homepage.html', context)
I found some close answers but I couldn't understand the solution nor use them in my code.
What you probably need called aggregation:
from django.db.models import F, Sum
def summaryPage(request):
aggregated_data = VisData.objects.annotate(
intermid_result=F('course') - F('fare')
).annotate(
record_total=F('shares_number') * F('intermid_result')
).aggregate(
total=SUM('record_total')
)
result = aggregated_data['total']
print(result)
...
This query will annotate each record with the value of record_total = shares_number * (course - fare) and then calculate a sum for record_total of all records.
Also try to avoid using camelcase function names in Python. See here for details.

How to auto populate data from other model and how to add calculated fields?

I am learning django and I have not been able to properly do two things within model clearance:
Within modelRetrieve the name fields that correspond to the imo number selected.
Autopopulate a date field with the current day plus 7 days.
Any ideas what I am doing wrong? Here is my code:
from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone
from datetime import timedelta, datetime
def imo_validator(value):
if value < 0 or value > 9999999:
raise ValidationError(
'This is not a valid IMO number',
params={'value':value},
)
class ship(models.Model):
imo = models.IntegerField(unique=True,validators=[imo_validator])
name = models.CharField(max_length=20)
rpm = models.FloatField()
power = models.FloatField()
main_engine = models.IntegerField()
class Meta:
ordering = ['imo']
def __str__(self):
return "{}, (IMO:{})".format(self.name, self.imo)
class clearance(models.Model):
STATUSES = [
('PENDING','PENDING'),
('REJECTED','REJECTED'),
('APPROVED','APPROVED'),
]
PORTS = [
('PACAN','PACAN'),
('PABLB','PABLB'),
('PACCT','PACCT'),
('PAANP','PAANP'),
('PAANA','PAANA'),
]
date_of_request = models.DateField(default=timezone.now,blank=False,editable=True)
imo = models.ForeignKey(ship, on_delete=models.PROTECT)
port = models.CharField(max_length=20,null=True,choices=PORTS)
eta = models.DateField(null=False)
name = ship.name.get(imo=imo)
calculated_eta = models.DateField(datetime.today + timedelta(days=1))
aduanas = models.FileField(blank=True)
aduanas_ok = models.CharField(max_length=15,default='PENDING',choices=STATUSES,editable=False)
minsa = models.FileField(blank=True)
minsa_ok = models.CharField(max_length=15,default='PENDING',choices=STATUSES,editable=False)
def __str__(self):
return "{}, ETA:{}".format(self.imo, self.eta)
class Meta:
ordering = ['eta']
To add a default to a DateField that is 7 days in the future you need to create a function that returns the date 7 days in the future and then pass that to the "default" parameter of the field
def seven_days_from_now():
return datetime.date.today() + datetime.timedelta(days=7)
class clearance(models.Model):
...
calculated_eta = models.DateField(default=seven_days_from_now)
...
Your "name" field should be a property that returns the name of the associated "imo"
class clearance(models.Model):
...
#property
def name(self):
return self.imo.name
...

How to perform number of days calculation in Django related field query

I have 2 models:
class Assets(models.Model):
assetMake = models.CharField(max_length=50,blank=True,)
assetModel = models.CharField(max_length=50,blank=True,)
class Maintenance(models.Model):
assetID = models.ForeignKey(Assets, on_delete=models.CASCADE)
dateRequested = models.DateTimeField(null=True, blank=True)
dateCompleted = models.DateTimeField(null=True, blank=True)
complete = models.BooleanField(default = False)
I want to have a view that displays all the Assets in order of when they were last maintained (dateCompleted). Which this accomplishes below:
from django.db.models import Max
Assets.objects.annotate(
last_modified=Max('maintenance__dateCompleted')
).order_by('-last_modified')
But how can I calculate the number of days from dateCompleted to now so that I can display this value as well.
Something like:
Assets.objects.annotate(
last_modified=Max('maintenance__dateCompleted'),
days = ((timezone.now() - maintenance__dateCompleted).days
).order_by('-last_modified')
You can use F() expressions with ExpressionWrapper
from django.db.models import F, ExpressionWrapper
from django.db.models.fields import DurationField
assets_annotate = Assets.objects.annotate(
days_dif = ExpressionWrapper(
timezone.now() - F('maintenance__dateCompleted'),
output_field = DurationField()
)
)
Then you can get days count with assets_annotate[0].days_dif.days

Django filter query with foreign key

I want to filter query based on three user inputs. Depart City, Arrive City and Date. Depart City and Arrive city are on the same table called Route while the TravelDate is a foreign key in Route.
My model
class TravelDate(models.Model):
start_date = models.DateField(null = True)
interval = models.IntegerField(null = True)
class Route(models.Model):
depart_city = models.CharField(max_length=50, null=True, blank=False)
arrive_city = models.CharField(max_length=50, null=True, blank=False)
driver = models.ForeignKey(Driver)
schedule = models.ForeignKey(Schedule)
traveldate = models.ForeignKey(TravelDate)
My View
def newpage(request):
if 'origin' in request.GET and request.GET['origin']:
q = request.GET['origin']
c = request.GET['dest']
d = request.GET['travelDate']
results = Route.objects.filter(depart_city=q, arrive_city=c)
return render(request,'busapp/newpage.html', {'results': results})
else:
return render(request, 'busapp/newpage.html',{})
In Views how can i make one query that will filter depart_city, arrive_city, and TravelDate of those routes based on user inputed. If a bus is available on that date from city A to city B will be calculated by doing doing something like this if (d - TravelDate.start_date)% TravelDate.interval =0 then display the results to the user.
I cannot get this right. I'm new to Django and trying to learn.
Keep interval as IntegerField
views.py
from datetime import datetime, timedelta
q = request.GET['origin']
c = request.GET['dest']
d = request.GET['travelDate']
# d format is '20171122',convert str to date
start_date = datetime.strptime(d, "%Y%m%d").date()
results = Route.objects.filter(depart_city=q, arrive_city=c)
routes = []
for route in results:
if (start_date > date) and ((start_date - route.traveldate.start_date) % timedelta(days=route.traveldate.interva)) == timedelta(days=0):
routes.append(route)
return render(request,'busapp/newpage.html', {'results': routes})

Query Values Muliple Field Foreign Key Column

This is my model:
class Personel(models.Model):
Numara = models.IntegerField(max_length=10)
Isim = models.CharField(max_length=30)
Soyisim = models.CharField(max_length=30)
class Islem(models.Model):
MenuAd = models.CharField(max_length=30)
Tarih = models.DateTimeField(auto_now_add=True)
Personel = models.ForeignKey(Personel)
Durum = models.PositiveIntegerField(max_length=5)
This is my query:
sorgu = Islem.objects.all().values('MenuAd', 'Personel')
sorgu result:
[{'MenuAd': 'Deneme', 'Personel': 2 }]
but, i want to result:
[{'MenuAd': 'Deneme', 'Personel': '2 - Baris Halici'}]
Numara: 2
Isim: Baris
Soyisim: Halici
example - proposal
def get_full_personel(self):
return "'%s - %s %s" % (self.Numara, self.Isim, self.Soyisim)
Thanks,
try changing your:
class Personel(models.Model):
def __unicode___(self):
return "'%s - %s %s" % (self.Numara, self.Isim, self.Soyisim)
or ___str___(self): if using python 3.
although that may not solve it... try:
sorgu = Islem.objects.all().values('MenuAd', 'Personel__get_full_personel')