how to get year from datefield at django? - python

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.

Related

How to filter through date in django-views?(Doesn't show the expired one)

models.py
class Dibbs_Fields(models.Model):
hash = models.CharField(max_length=16)
nsn = models.CharField(max_length=32)
nomenclature = models.TextField()
technical_documents = models.TextField()
return_by = models.DateField()
How to filter this class in django views according to the date return_by ? I don't want to show the data that is expired i.e. if the return_by date is earlier than today's date, then it should not show.
You can do this:
from datetime import date
def func(request):
today = date.today()
data = Dibbs_Fields.objects.filter(
return_by__lt=today)
The code simply returns data are earlier than today's date.
EDIT
return_by__lt # less than
return_by__gt # greater than
return_by__gte # greater than or equal to
return_by__lte # less than or equal to

Python - Django - Filter and count all people in first year from start date

I need to count all the people who are in the first year of the contract.
I even made several attempts and failed. Can anyone help me? Thanks!
Model:
class Contracts(models.Model):
person = models.CharField(max_length=50, null=True, blank=True, verbose_name='Name')
start_date = models.DateField(null=True, blank=False, verbose_name='Start')
def __str__(self):
return '{}'.format(self.person)
So far...
View:
def people_in_first_year(request):
people = Contracts.objects.filter(Q(start_date__lte=timezone.now()) & Q(end_date__gte=timezone.now() + timedelta(days=365)))
total_people = people.count()
context = {
'total_people': total_people,
}
return render(request, 'people.html', context)
Since there is not an end_date, you can not filter much on that one. What you can do is simply set the start_date to be greater than or equal to now minus 365 days:
total_people = Contracts.objects.filter(
start_date__gte=timezone.now() - timedelta(days=365)
).count()
A year however is not per se 365 days. You can for example make use of the python-dateutil package [pypi], and work with a relativedelta [readthedocs.io]:
from dateutil.relativedelta import relativedelta
total_people = Contracts.objects.filter(
start_date__gte=timezone.now() - relativedelta(years=1)
).count()

Sorting queryset with date

Extending from the question here, where queryset is filtered using input from the user, I wanted to know if it was possible to filter queryset depending on present month and week. Eg each month should start on the 1st and each week on a monday and the queryset should be filtered for all the tests that have taken place in the present month and week.
models.py
class City(models.Model):
city_name=models.CharField(max_length=100,default='',blank=False)
class Person(models.Model):
title = models.CharField(max_length=3,default="mr",blank=False)
name = models.CharField(max_length=50,default='',blank=False)
address = models.CharField(max_length=200,default='',blank=False)
city = models.ForeignKey(City)
class Test(models.Model):
person = models.ForeignKey(Person)
date = models.DateTimeField(auto_now_add=True)
test_name = models.CharField(max_length=200,default='',blank=False)
subject = models.CharField(max_length=100,default='')
views.py
def personlist(request, id):
data = requests.get('http://127.0.0.1:8000/app/cities/' + id + '/persons/').json()
context = RequestContext(request, {
'persons': data['results'],'count': data['count'],
})
return render_to_response('template.html', context)
And the related json
According to this question - one way could be to use
startdate = date.today()
enddate = startdate + timedelta(days=6)
Sample.objects.filter(date__range=[startdate, enddate])
But wouldn't date.today() keep changing everyday and thus everyday a new week will start and thus, a new queryset?Similarly with month. Is there a way to get querysets filtered by present week and month. With each starting from every monday and every 1st respectively?
You can use the __month and __year lookups to limit the queryset to this month's objects.
from datetime import date
today = date.today()
this_month_qs = Sample.objects.filter(
date__month=today.month,
date_year=today.year,
)
To find this weeks objects, you first need to find the date of this Monday. You can do this by finding today's day of the week (Monday = 0, Sunday = 6) using a date's weekday() method, and subtracting that many days from today. It's easy to calculate the last day of the week by adding 6 days, and then you can use __range to find this week's objects.
from datetime import date, timedelta
today = date.today()
# Use today.isoweekday() if you want the week
# to start on Sunday instead of Monday
first_day_of_week = date.today() - timedelta(today.weekday())
end_date = first_day_of_week + timedelta(days=6)
this_week_qs = Sample.objects.filter(date__range=[startdate, enddate])

Change query in Django based on day of week

First of all thank you for looking at my question.
I am looking for a way to store the day of week in a model, I have established that having a boolean for each day of the week in the model is likely the most simple approach. I had looked at using bitflags but was unsure again how to query this.
My model looks like the following
class CallForwardingRule(models.Model):
forward_to = models.CharField(max_length=255,null=False,blank=False)
start_time = models.TimeField(default=time(0,0))
end_time = models.TimeField(default=time(0,0))
active = models.BooleanField(default=True)
monday = models.BooleanField(default=False)
tuesday = models.BooleanField(default=False)
wednesday = models.BooleanField(default=False)
thursday = models.BooleanField(default=False)
friday = models.BooleanField(default=False)
saturday = models.BooleanField(default=False)
sunday = models.BooleanField(default=False)
My query is then like the following
CallForwardingRule.objects.filter(start_time__lte=time,end_time__gte=time)
What I need to do is alter the query depending on the current day, if the day is monday the query should look for a rule where boolean value monday=True
I hope I have been clear in my question, I am quite new to Django and Python.
Kind Regards
You can use a custom manager. Say
class TodayManager(models.Manager):
def get_queryset(self, *args, **kwargs):
today = self.weekday_as_string()
return super(TodayManager, self).get_queryset(*args, **kwargs).filter(
**{today: true})
def weekday_as_string(self):
# TODO
class CallForwardingRule(models.Model):
# your fields
of_today = TodayManager()
And query like this:
CallForwardingRule.of_today.filter(
start_time__lte=time,end_time__gte=time)
Read more about object managers here https://docs.djangoproject.com/en/1.8/topics/db/managers/
NOTE: If you don't intend for the user to be able to mix days in the same model instance, you should use an integer field with choices instead, as suggested in the comments.
You should either use an integer or a charfield for your dayofweek. Each of them may be used with choices (https://docs.djangoproject.com/en/1.8/ref/models/fields/#choices) which allows you to make it easier to translate the code of the day to its name.
Then, you just have to filter your queryset with this field.

Upcoming birthdays with MongoEngine

Any idea how can I find the next upcoming birthdays considering this code (based on Python/Mongoengine)
class User(mongoengine.Document):
(...)
birthday = DateTimeField()
I know how to do it in plain SQL, but I have no idea how to do this query with this language.
There could be some benefit to save something like:
class User(mongoengine.Document):
birthdate = DateTimeField()
birth_month = IntegerField()
birth_day = IntegerField()
then to query, everyone with bithrdays this month or next month
current_month = datetime.now().month
current_day = datetime.now().day
next_month = (datetime.date.today() +
dateutil.relativedelta.relativedelta(months=1)).month
User.object.filter(Q(birth_month=current_month, birth_day__gte=current_day) |
Q(birth_month=next_month)).order_by('birthday')
The above should get all the users who have birthday from today until next the end of next month. Started to write a solution but failed!, this problem seems deceptively hard, hopefully someone has a lot cleaner solution

Categories

Resources