How to pass only year from url to view - python

I have my django app and I want to pass from url to view years in format, for example: 2017-18.
Below I got an error that my date have to be in date format - YYYY-MM-DD.
Here is my url:
url(r'^(?P<branch_slug>/production/(?P<year1>[0-9]{4})-(?P<year2>[0-9]{2})$', Events.as_view()),
Here is my view:
def get_queryset(self):
season = Events.objects.get(start=self.kwargs['year1'], end=self.kwargs['year2'])
filter_['start__gte'] = season.start
filter_['start__lte'] = season.end
return self.model.objects.filter(**filter_)

The start and end attributes of your Event object are probably datetime.date instances (if you are using a DateField). So you need to convert the year1 and year2 variables from your url to a date before using them in your view.
some_date = datetime.date(YYYY, 1, 1)

Your original question, and others' answers here, match a season that begins on 1 January of year1 and ends on 31 December of year2. I suspect that this is not what you want, and that instead you want a season which starts sometime in year1 and ends some time in year2, and then you want to look up events between those dates.
Django has a special lookup for matching only the year part of a date, using __year=. See https://docs.djangoproject.com/en/1.10/ref/models/querysets/#year for more on this. You don't need to convert the input values to dates to use this; it works with integers.
def get_queryset(self):
# Get a season starting any time in year1 and ending in year2
season = Events.objects.get(
start__year=int(self.kwargs['year1']),
end__year=int(self.kwargs['year2']),
)
As with others have commented you should change the URL regex to match 4-digit years to avoid ambiguity.
url(r'^(?P<branch_slug>/production/(?P<year1>[0-9]{4})-(?P<year2>[0-9]{4})$', Events.as_view()),

As #dentemm pointed out, to do filtering on datetime fields, strings representing date must be converted to datetime objects. My suggestion is to use datetime field. Pass year string as you are already doing and then in the views convert date string to a datetime object to do filtering
import datetime
def get_queryset(self):
start=datetime.strptime('1-1-'+self.kwargs['year1'], '%m-%d-%Y')
end=datetime.strptime('12-31-'+self.kwargs['year2'], '%m-%d-%Y')
season = Events.objects.get(start=start, end=end)
filter_['start__gte'] = season.start
filter_['start__lte'] = season.end
return self.model.objects.filter(**filter_)
datetime.strptime('1-1-'+self.kwargs['year1'], '%m-%d-%Y') will create datetime object for start date with date as 1st of january for given start date string and datetime.strptime('12-31-'+self.kwargs['year2'], '%m-%d-%Y') will create datetime object for end date with date as 31st of december for given end date string. To make sure all objects created within end date is returned by query you may do something like
`end_date = datetime.strptime('31-12-'+self.kwargs['year1']+'T23:59:59.999999', '%m-%d-%YT%H:%M:%S.%f')`
As #Alasdair mnetioned in one of the comments change (?P<year2>[0-9]{2}) to (?P<year2>[0-9]{4}) to accept 4 digit year string from url

If you have a datetime/date field in your model, use the year lookup from Django:
https://docs.djangoproject.com/en/1.10/ref/models/querysets/#year
As it says:
Entry.objects.filter(pub_date__year=2005)
is equal in sql to:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';

Related

I have a list of dates and I want to subtract actual date from each of them to know how many day passed. Is there any fast way to do this?

I know I should import datetime to have actual date. But the rest is black magic for me right now.
ex.
dates = ['2019-010-11', '2013-05-16', '2011-06-16', '2000-04-22']
actual_date = datetime.datetime.now()
How can I subtract this and as a result have new list with days that passed by from dates to actual_date?
If I'm understanding correctly, you need to find the current date, and then find the number of days between the current date and the dates in your list?
If so, you could try this:
from datetime import datetime, date
dates = ['2019-10-11', '2013-05-16', '2011-06-16', '2000-04-22']
actual_date = date.today()
days = []
for date in dates:
date_object = datetime.strptime(date, '%Y-%m-%d').date()
days_difference = (actual_date - date_object).days
days.append(days_difference)
print(days)
What I am doing here is:
Converting the individual date strings to a "date" object
Subtracting the this date from the actual date. This gets you the time as well, so to strip that out we add .days.
Save the outcome to a list, although of course you could do whatever you wanted with the output.

Create a blank date in python

I want to add a blank column of date of format "%Y-%m-%d" to a dataframe. I tried datetime.datetime.strptime('0000-00-00',"%Y-%m-%d")
But I get an error ValueError: time data '0000-00-00' does not match format '%Y-%m-%d'
How can I create a column of blank date of format "%Y-%m-%d"?
In R following works.
df$date =""
class(df$date) = "Date"
How can I achieve this in Python?
Thank you.
I don't think that's possible with datetime module. The oldest you can go to is answered here:
What is the oldest time that can be represented in Python?
datetime.MINYEAR
The smallest year number allowed in a date or datetime object. MINYEAR is 1.
datetime.MAXYEAR
The largest year number allowed in a date or datetime object. MAXYEAR is 9999.
source: datetime documentation
initial_date = request.GET.get('data') or datetime.min # datetime.min is 1
end_date = request.GET.get('data_f') or datetime.max # datetime.max is 9999

Filter Django DB object with a manipulated keyword

I take a timestamp for my Institution class:
class Institution(models.Model):
timestamp_utc = models.DateTimeField()
If there is an entry in the DB that has the same year, month and date (not time), then I want to update the value of the entry. If not, then I want to create a new entry.
The conditional is as follows:
if Institution.objects.filter(timestamp_utc.strftime("%Y/%m/%d")=b['timestamp_utc'].strftime("%Y/%m/%d")).exists():
I am getting this error:
Exception Value: keyword can't be an expression
Is there a way to filter the DB object with a manipulated keyword?
You can just filter by the date range, i.e. time stamps that are great than or equal to the date, and less that the date + 1 day.
from datetime import relativedelta
date_start = b['timestamp_utc'].strftime("%Y-%m-%d")
date_end = (b['timestamp_utc'] + relativedelta(days=1)).strftime("%Y-%m-%d")
if Institution.objects.filter(
timestamp_utc__gte=date_start, timestamp_utc__lt=date_end
).exists():

Django filter by datetime, after converting string to datetime

I'm trying to filter my query by a datetime. This datetime is the datetime for the value range the customer wants to know information for. I'm trying to set it to the first of the month selected by the customer. I pass the month number convert it to the correct string format and then convert to a datetime object because simply looking for the string object was returning no values and Django's documentation says you need to do it like:
pub_date__gte=datetime(2005, 1, 30)
Code:
if 'billing-report' in request.POST:
customer_id = int(post_data['selected_customer'])
This is the code I use to get the selected customer date and turn it into a tupple
if 'billing-report' in request.POST:
customer_id = int(post_data['selected_customer'])
selected_date = int(post_data['month'])
if selected_date < 10:
selected_date = '0'+str(selected_date)
year = datetime.now()
year = year.year
query_date = str(year) + '-' + str(selected_date) + '-01'
query_date_filter = datetime.strptime(query_date, "%Y-%m-%d")
compute_usages = ComputeUsages.objects.filter(customer_id = customer_id).filter(values_date = query_date_filter)
django debug shows: datetime.datetime(2014, 10, 1, 0, 0)
query_date looks like: 2014-07-01 before it is converted
.
No error but no data is returned
I used to use:
compute_usages = ComputeUsages.objects.filter(customer_id = customer_id).filter(values_date = datetime(query_date_filter))
which was causing the error. I'm sorry for changing my question as it evolved that is why I'm re-including what I was doing before so the comments make sense.
Almost all of that code is irrelevant to your question.
I don't understand why you are calling datetime on query_date. That is already a datetime, as you know because you converted it to one with strptime earlier. So there's no need for any more conversion:
ComputeUsages.objects.filter(customer_id=customer_id).filter(values_date=query_date)
Well after spending sometime exploring setting the query filter to datetime(year, month, day) I came to the realization that django doesn't convert it to a neutral datetime format it has to match exactly. Also my data in the database had the year, day, month.
Learning point:
You have to use the datetime() exactly how it is in the database django does not convert to a neutral format and compare. I assumed it was like writing a query and saying to_date or to_timestamp where the db will take your format and convert it to a neutral format to compare against the rest of the db.
Here is the correct way
compute_usages = ComputeUsages.objects.filter(customer_id = customer_id).filter(values_date = datetime(year, day, selected_month))

Django/Python - Check a date is in current week

I would like to do something like this:
entries = Entry.objects.filter(created_at__in = current_week())
How to make it for good performance. Thanks!
Edit: I still have no idea for current_week() function.
Use __range. You'll need to actually calculate the beginning and end of the week first:
import datetime
date = datetime.date.today()
start_week = date - datetime.timedelta(date.weekday())
end_week = start_week + datetime.timedelta(7)
entries = Entry.objects.filter(created_at__range=[start_week, end_week])
Since Django 1.11, we you can use week Field lookup:
Entry.objects.filter(created_at__week=current_week)
It will give you the week from monday to sunday, according to ISO-8601.
To query for the current week:
from datetime import date
current_week = date.today().isocalendar()[1]
isocalendar() will return a tuple with 3 items: (ISO year, ISO week number, ISO weekday).
Yep, this question is at 2 years ago. Today with more experiences, I recommend using arrow with less pain in handling date time.
Checkout: https://github.com/crsmithdev/arrow

Categories

Resources