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
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.
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
...
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
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})
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')