Django rest framework timefield input format - python

After hours of searching, I found many posts that are related but wasn't able to help.
What I want to do is input eg: 10:30 AM into the TimeField.
In the django rest framework API on the browser, it is using this 10:30 AM format ('%I:%M %p').
But when I am using postman to test it, the output is in 24hr format ('%H:%M:%S'). I also tried to use 10:30 PM as input but the output I get is 10:30:00 instead of 22:30:00.
Many of the answers I found suggest to change the TimeField format in settings.py by using this line:
TIME_INPUT_FORMATS = ('%I:%M %p',)
but it doesn't work for me.
Sorry for my inexperience on django rest framework as I am still learning.
Here is the screenshot of the result.
On browser API:
On postman:

If you check the documentation on the TimeField you will see:
Signature: TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
Where
format - A string representing the output format. If not specified, this defaults to the same value as the TIME_FORMAT settings key, which will be 'iso-8601' unless set. Setting to a format string indicates that to_representation return values should be coerced to string output. Format strings are described below. Setting this value to None indicates that Python.
input_formats - A list of strings representing the input formats which may be used to parse the date. If not specified, the TIME_INPUT_FORMATS setting will be used, which defaults to ['iso-8601'].
So you either can specify the format and input_formats on the serializer, or set the settings.TIME_FORMAT and settings.TIME_INPUT_FORMATS.
Let's set the first case:
class MySerializer(serializers.Serializer):
...
birthTime=serializers.TimeField(format='%I:%M %p', input_formats='%I:%M %p')
Some suggestions:
Make your variable names snake case: birth_time.
You may need to play a bit around with the input format because you may expect many different inputs:
input_formats=['%I:%M %p','%H:%M',...]

Convert the result in Serializer validate method and return it.
import time
t = time.strptime(timevalue_24hour, "%H:%M")
timevalue_12hour = time.strftime( "%I:%M %p", t )

Related

Best practices to filter in Django

In one of the pages of my Django app I have a page that simply displays all employees information in a table:
Like so:
First Name: Last Name: Age: Hire Date:
Bob Johnson 21 03/19/2011
Fred Jackson 50 12/01/1999
Now, I prompt the user for 2 dates and I want to know if an employee was hired between those 2 dates.
For HTTP GET I just render the page and for HTTP POST I'm sending a URL with the variables in the URL.
my urls.py file has these patterns:
('^employees/employees_by_date/$','project.reports.filter_by_date'),
('^employees/employees_by_date/sort/(?P<begin_date>\d+)/(? P<end_date>\d+)/$', EmployeesByDate.as_view()),
And my filter_by_date function looks like this:
def filter_by_date(request):
if request.method == 'GET':
return render(request,"../templates/reports/employees_by_date.html",{'form':BasicPrompt(),})
else:
form = BasicPrompt(request.POST)
if form.is_valid():
begin_date = form.cleaned_data['begin_date']
end_date = form.cleaned_data['end_date']
return HttpResponseRedirect('../reports/employees_by_date/sort/'+str(begin_date)+'/'+str(end_date)+'/')
The code works fine, the problem is I'm new to web dev and this doesn't feel like I'm accomplishing this in the right way. I want to use best practices so can anyone either confirm I am or guide me in the proper way to filter by dates?
Thanks!
You're right, it's a bit awkward to query your API in that way. If you need to add the employee name and something else to the filter, you will end up with a very long URL and it won't be flexible.
Your filter parameters (start and end date) should be added as a query in the url and not be part of path.
In this case, the url would be employees/employees_by_date/?start_date=xxx&end_date=yyy and the dates can be retrieved in the view using start_date = request.GET['start_date].
If a form is used with method='get', the input in the form are automatically converted to a query and appended at the end of the url.
If no form is used, parameters need to be encoded with a function to be able to pass values with special characters like \/ $%.
Use Unix timestamps instead of mm/dd/yyyy dates. A unix timestamp is the number of seconds that have elapsed from Jan 1 1970. ("The Epoch".) So it's just a simple integer number. As I'm writing this, the Unix time is 1432071354.
They aren't very human-readable, but Unix timestamps are unambiguous, concise, and can be filtered for with the simple regex [\d]+.
You'll see lots of APIs around the web use them, for example Facebook. Scroll down to "time based pagination", those numbers are Unix timestamps.
The problem with mm/dd/yyyy dates is ambiguity. Is it mm/dd/yyyy (US)? or dd/mm/yyyy (elsewhere)? What about mm-dd-yyyy?

Formating Django Datetime objects outside template

I love the date tag that comes with Django.
Exceptionally, I'd like to format a DateTime object in my view (because I need to send a formated date string to an API, and not to display it in a Django template).
Do you know if there is a way to use this Django "system" outside templates?
In the mean time, I tried to use the strftime Python method but found out some con's:
It does not use the same format chars as Django, which makes my code deals with 2 different ways to handle date formatting.
By default, it doesn't care about the Django locales and writes English dates.
Thanks :)
The template tag is built on the Django formats utility libraries. See django.utils.formats.date_format for a named date format or django.utils.formats.dateformat.format for arbitrary ones. For example:
from datetime import datetime
# Date format string
from django.utils.formats import dateformat
formatted_date = dateformat.format(datetime.now(), "r")
# Named format
from django.utils.formats import date_format
formatted_date = date_format(datetime.now(), "SHORT_DATE_FORMAT")

Parametrizing a Date on urls.py in Django

I have the following URL definition:
url(r'^date-add/(?P<entity_id>\d+)$', views.date_add, name='date_add'),
That allows me to call date_add function with the following URL:
/app_name/date-add/<id>
I would like to fix this to allow a date. For example:
/app_name/date-add/1/2013-04-23
How should I edit my urls.py definition in order to achieve this?
You can define your URL regex like this:
url(r'^date-add/(?P<entity_id>\d+)/(?P<date>\d{4}-\d{2}-\d{2})/$', views.date_add, name='date_add'),
and the view, obviously would be
def date_add(request, entity_id, date):
#convert to datetime object from string here.
Typically you break it down into named parameters corresponding to the year, month and date:
url(r'^date-add/(?P<entity_id>\d+)/(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})/$', views.date_add, name='date_add_with_param'),
Then you can use datetime.date to construct the datetime in your view, which should receive year, month and day as parameters.
This is the usual pattern in particular for archive views, where the URLs might get more specific as you drill down - /archive/2013/ and /archive/2013/11/ might both be valid, although of course you probably wouldn't have a single regexp matching either. It might be unnecessarily complex compared to the single named pattern regexp karthikr's answer shows, which you could then parse with datetime.strptime.
In either case you can also use somewhat more restrictive regexps if you like, like ones that don't allow a first digit other than 0, 1, 2 or 3 for the month.

django autoconverting datetime property

my datetime property is saving in mysql in this format 2011-03-17 00:00:00 but after fetchind the data with filter function it is giving March 17,2011 midnight but i have not say to do any this type of task. My question is how can i insist django to stic to show same value what is saved in MYSQL.
you'll want to use the datetime format, django's DateTimeField[1] really is a wrapper for datetime.datetime.
in the templates you can use the date[2] filter to apply the format you want for example:
{{ item.date|date:"Y-m-d H:i:s" }}
This should print out 2011-03-17 00:00:00 in the template. In views use datetimes.strftime[3]
[1] http://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
[2] http://docs.djangoproject.com/en/1.2/ref/templates/builtins/#date
[3] http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior
I have a feeling your database schema knows this is a date, right? In that case it's not being stored in the format you describe, but as some representation such as seconds since the era.
This means that when you retreave it your code has to do something with it to make it look right. If you don't tell it how to look it'll default to the format you see, but if you use strftime in your python code and a filter in your templates you can make it look however you like, including the original format how you saw it.
Of course the easy way out is to store it in the db as text...

Making Django queries with localized dates

In my form I have a DateField called booking_date that is rendered with the AdminDateWidget. The contents of the booking_date field needs to be internationalized. The problem appears when I want to use the value of the field in something like this:
booking = Booking.objects.get(booking_number='BN34D', booking_date='2010-11-21')
But if my date format is '%d.%m.%Y':
booking = Booking.objects.get(booking_number='BN34D', booking_date='21.11.2010')
I get a 'ValidationError: Enter a valid date in YYYY-MM-DD format'
How can I make the query regardless of the date format used?
You should parse it first with a localized version of the strftime format.
from datetime import datetime
d = datetime.strptime('...')
booking.objects.get(..., booking_date=d.date())
Use these formats in strptime:
http://linux.die.net/man/3/strftime
You shouldn't rely on passing directly from the user into the query.
Looks like you should be doing the following from your specific example:
d = datetime.strptime('%d.%m.%Y')
booking = Booking.objects.get(booking_nmber='BN34D', booking_date=d)
As I understand your question, you don't know for sure in advance, which locale will be used. That can bring you into unsolvable problems. ("10-11-12" could be Oct 11, 2012 or Nov 12, 2010 or ...)
So you must have a limited, distinguishable set of possible formats. Then you can do:
POSSIBLE_FORMATS = ('%d.%m.%Y', '%Y-%m-%d', '...')
for f in POSSIBLE_FORMATS:
try:
d = datetime.date.strptime(date_str, f)
break
except ValueError:
continue
raise ValueError
booking = Booking.objects.get(booking_number='BN34D', booking_date=d)
I have solved the problem using this:
from django.utils import formats
formats.get_format('DATE_INPUT_FORMATS')[0]
This format is then used for parsing the date like xyld showed.

Categories

Resources