I have drf model which is containe DateField. That field default format is "YYYY-MM-DD" just i want to convert "DD-MM-YYYY" how can is possible.
from rest_framework import serializers
from.models import SpaUser
from djoser.serializers import UserCreateSerializer as BaseUserRegistrationSerializer
import datetime
from rest_framework.settings import api_settings
class SpaUserSerializer(serializers.ModelSerializer):
date_joined = serializers.ReadOnlyField()
birthdate = serializers.DateField(format="%d-%m-%Y", input_formats=['%d-%m-%Y',])
If it is universal, in your settings file add "DATE_INPUT_FORMATS" to REST_FRAMEWORK settings like:
REST_FRAMEWORK = {
"DATE_INPUT_FORMATS": ["%d-%m-%Y"],
...
}
for more details check http://www.django-rest-framework.org/api-guide/settings/#date-and-time-formatting
To have it correctly work, input_formats is the argument you need to assign the format needed, format is the output format
birthdate = serializers.DateField(input_formats=['%d-%m-%Y',])
or you can set the default input format in your settings
DATE_INPUT_FORMATS = [
("%d-%m-%Y"),
]
By combining all your solutions, it works
REST_FRAMEWORK = {
# "DATE_INPUT_FORMATS": "%d-%m-%Y", doesn't works
'DATE_INPUT_FORMATS': [("%d-%m-%Y"),],it works
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
From DRF documentation regarding DateField
Format strings may either be Python strftime formats which explicitly
specify the format, or the special string 'iso-8601', which indicates
that ISO 8601 style dates should be used. (eg '2013-01-29')
So in your case format should be
format="%d-%m-%Y"
Although this thread is quite old, I found it when trying to solve a similar problem. Although the responses didn't give me the entire answer, they did push me to simply read DRF's quite helpful documentation on the topic:
https://www.django-rest-framework.org/api-guide/settings/#date-and-time-formatting
In my case, I am building a events calendar using Vuetify's v-calendar, Vue JS, and DRF. The v-calendar requires the format YYYY-MM-DD HH:MM, and prefers a string. I could simply store the string in my DB, but I preferred to store the datetime fields in native Python formatting for server-side processing should I ever need them. So, in my settings.py file, I added the following to my REST_FRAMEWORK setting:
'DATETIME_INPUT_FORMATS': ['%Y-%m-%d %H:%M',],
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
The first one takes a list (hence the brackets and comma), the second just takes a string. Then, in my serializer, I use:
start = serializers.DateTimeField()
On the front end, I take in the dates as the string objects, pass them to the calendar for display, and it works. When POSTing data, I simply pass them back in that same string format, and the DRF serializer encodes them as native Python for storage.
We have to differentiate between all these:
DATE_INPUT_FORMATS
To specify the date format for the input in POST request API.
DATETIME_FORMAT
To specify the DateTime format for serialized data like with GET request.
DATE_FORMAT
To specify the Date format for serialized data like with GET request.
And this is an example of how to use these settings in the settings.py file.
REST_FRAMEWORK = {
'DATE_INPUT_FORMATS': ["%Y-%m-%d %H", ],
'DATETIME_FORMAT': '%Y-%m-%d %H',
'DATE_FORMAT': '%Y-%m-%d %H'
}
Note: You should use these settings just if you want your serializer to have the same data or DateTime format.
But in case you have changed in some field you can just change the format for that field and here is an example of how to do like this:
class YourSerializer(serializers.ModelSerializer):
...
def to_representation(self, instance):
representation = super(YourSerializer, self).to_representation(instance)
representation['created_at'] = instance.created_at.strftime('%Y-%m-%d %H)
return representation
Or in a similar way
class YourSerializer(serializers.ModelSerializer):
created_at = serializers.DateTimeField(format='%Y-%m-%d %H')
In settings.py include:
REST_FRAMEWORK = {
'DATE_FORMAT': '%d-%m-%Y'
}
Related
I recently added a new model to my site, and I'm using an admin.py file to specify exactly how I want it to appear in the admin site. It works great, but I can't figure out how to get one of my date fields to include seconds in it's display format. I'm only seeing values like "Aug. 27, 2011, 12:12 p.m." when what I want to be seeing is "Aug. 27, 2011, 12:12*:37* p.m."
Try this in the ModelAdmin:
def time_seconds(self, obj):
return obj.timefield.strftime("%d %b %Y %H:%M:%S")
time_seconds.admin_order_field = 'timefield'
time_seconds.short_description = 'Precise Time'
list_display = ('id', 'time_seconds', )
Replacing "timefield" with the appropriate field in your model, of course, and adding any other needed fields in "list_display".
digging around I ended here but applied a different approach to my app.
Changing django admin default formats could be done changing the django locale formats for every type you want.
Put the following on your admin.py file (or settings.py) to change datetime default format at your django admin.
from django.conf.locale.es import formats as es_formats
es_formats.DATETIME_FORMAT = "d M Y H:i:s"
It will change the ModelAdmin's datetime formats on that file (or whole site if in settings).
It does not breaks admin datetime filters and order features as #Alan Illing has point out in comments .
hope this help in future
Extra info:
You can change it for every available locale in django, which are a lot.
You can change the following formats using this approach
from django.conf.locale.es import formats as es_formats
es_formats.DATETIME_FORMAT
es_formats.NUMBER_GROUPING
es_formats.DATETIME_INPUT_FORMATS
es_formats.SHORT_DATETIME_FORMAT
es_formats.DATE_FORMAT
es_formats.SHORT_DATE_FORMAT
es_formats.DATE_INPUT_FORMATS
es_formats.THOUSAND_SEPARATOR
es_formats.DECIMAL_SEPARATOR
es_formats.TIME_FORMAT
es_formats.FIRST_DAY_OF_WEEK
es_formats.YEAR_MONTH_FORMAT
es_formats.MONTH_DAY_FORMAT
If you've tried gabriel's answer but it did not work, try to set USE_L10N = False in settings.py, it works for me.
Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead
See: https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-DATETIME_FORMAT
The accepted answer is correct, however I found it a bit confusing to understand how/why it works. Below is a small example that I hope illustrates how to do this more clearly.
Django provides a few ways to display "custom" fields in your admin view. The way I prefer to achieve this behavior is to define a custom field in the ModelAdmin class and display that instead of your intended field:
from django.contrib import admin
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
class PersonAdmin(admin.ModelAdmin):
#admin.display(description='Birthday')
def admin_birthday(self, obj):
return obj.birthday.strftime('%Y-%m-%d')
list_display = ('name', 'admin_birthday')
Notice that instead of displaying the actual birthday field from the Person model, we define a custom field (admin_birthday) as a method in the PersonAdmin and display that instead by adding it to the list_display attribute. Furthermore, the admin.display() decorator modifies how Django will display this custom field in the admin view. Using this approach, the admin panel will show the NAME and BIRTHDAY fields but using your preferred date formatting for the date.
The reason I prefer this approach is you keep the Model field definitions separate from how you display them in the admin panel. You can read more about alternative approaches in the Django admin documentation.
How to prefill a DateTimeField from URL in django admin?
Let's say your model is :
class MyModel(models.Model):
name = models.CharField(max_length=14)
date = models.DateTimeField()
Then you can have the model "Add" form prefilled with values by passing them as GET parameters to the add view like:
/admin/app/mymodel/add/?name=Test
This is a really cool feature but how do you achieve this for a DateTimeField?
I tried many possible formats without success.
Update:
It seems impossible to do because django admin uses a SplitDateTimeWidget for DateTimeField. But if you don't mind using a different widget and loosing the datepicker, you can use a DateTimeInput widget instead.
The fastest way is to add this to your ModelAdmin class:
formfield_overrides = {
models.DateTimeField: {'widget': DateTimeInput},
}
First define the serialization/deserialization format:
DATETIME_FORMAT="%Y-%m-%d %H:%M:%S"
Then when you want to open the admin url use it:
copiedArguments = {
"fromDateTime": event.fromDateTime.strftime(DATETIME_FORMAT)
}
return HttpResponseRedirect(
u"{}?{}".format(reverse('admin:events_event_add'), urllib.urlencode(copiedArguments)))
last but not least extract the datetime in the model admin:
def get_changeform_initial_data(self, request):
initialData = super(EventAdmin, self).get_changeform_initial_data(request)
initialData["fromDateTime"] = datetime.datetime.strptime(request.GET["fromDateTime"],DATETIME_FORMAT)
return initialData
The problems seems to be with the widget. A DateField would work fine with ?date=yyyy-mm-dd, but a DateTimeField uses the SplitDateTimeWidget. It can not have a string as an initial value.
Maybe you could propose a patch to SplitDateTimeWidget to try to convert string values, or you could change the admin default widget for a DateTimeField (if that is possible).
Nowadays there's the get_changeform_initial_data ModelAdmin method.
I'm passing the query parameters like this:
?start=08/09/2022 12:30&end=08/09/2022 17:00
And it works fine by overriding the method like that:
def get_changeform_initial_data(self, request):
initial = super().get_changeform_initial_data(request)
if "end" in initial:
initial["end"] = datetime.datetime.strptime(initial["end"], "%d/%m/%Y %H:%M")
if "start" in initial:
initial["start"] = datetime.datetime.strptime(initial["start"], "%d/%m/%Y %H:%M")
return initial
It's also mentioned in this issue's comment, and useful for those facing the error 'str' object has no attribute 'utcoffset' when trying to prefill a datetime field from query parameters in Django admin.
I have a Django app with a model that contains a field of type DateTimeField.
I am pulling data from the web in the format of 2008-04-10 11:47:58-05.
I believe that the last 3 characters in this example are the timezone.
How can I preserve that data in the DateTimeField, and is there an easy conversion between the two? Setting the DateTimeField to simply contain a string of the above format throws a ValidationError.
Thank you!
You can also use Django's implementation. I would in fact prefer it and only use something else, if Django's parser cannot handle the format.
For example:
>>> from django.utils.dateparse import parse_datetime
>>> parse_datetime('2016-10-03T19:00:00')
datetime.datetime(2016, 10, 3, 19, 0)
>>> parse_datetime('2016-10-03T19:00:00+0200')
datetime.datetime(2016, 10, 3, 19, 0, tzinfo=<django.utils.timezone.FixedOffset object at 0x8072546d8>)
To have it converted to the right timezone when none is known, use make_aware from django.utils.timezone.
So ultimately, your parser utility would be:
from django.utils.dateparse import parse_datetime
from django.utils.timezone import is_aware, make_aware
def get_aware_datetime(date_str):
ret = parse_datetime(date_str)
if not is_aware(ret):
ret = make_aware(ret)
return ret
You can use
import dateutil.parser
dateutil.parser.parse('2008-04-10 11:47:58-05')
Which returns a datetime (that can be assigned to the DateTimeField).
I've been using this:
from django.utils.timezone import get_current_timezone
from datetime import datetime
tz = get_current_timezone()
dt = tz.localize(datetime.strptime(str_date, '%m/%d/%Y'))
String format of Django DateTimeField is "%Y-%m-%dT%H:%M:%S.%fZ".
Hence, conversion between eachother can be done using strptime() or strptime() using this format.
eg. for string formatted value (2016-10-03T19:00:00.999Z), it can be converted
to Django datetime object as :
from datetime import datetime
datetime_str = '2016-10-03T19:00:00.999Z'
datetime_object = datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ")
If you're using Django Forms, you can specify input_formats to your DateField. See the DateField documentation
If you are wanting to parse arbitrary date information, you could use something like parsedatetime and implement a method that Django calls to do the parsing before it hits the validators. (See this SO answer for a good summary of how validations work and when to insert them)
To make standard format:
from django.utils.dateparse import parse_datetime
formatted_datetime = parse_datetime(YOUR_STRING_DATETIME).strftime('%Y-%m-%d %H:%M:%S')
print(f"formatted_datetime: {formatted_datetime}")
You will see something like this:
2022-02-09 12:58:52
Be successful
Am building a Django app. And on the admin is is required to be able to search for items based on queries that might also include names of the month, year, etc.
The problem (I can't seem to find a solution to this on SO or elsewhere), is that the default format for dates in Django (ok, the way the dates have been persisted to the datastore) is %Y-%m-%d, but I wish to be able to search on say query like "June" from the Django Admin search.
How do I make it possible to search date fields using custom date formats, without converting the formats in which the dates are persisted?
Date and Time are stored in the database as a distinct type for them, because you should be able to do special date time operations like greater than, lesser than and not just string search.
Django ORM accepts the date-time as strings formatted in one of the standard formats including strings, integers and datetime objects .
Example:
Entry.objects.filter(pub_date__year=2006)
or
Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.now()
... ).filter(
... pub_date__gte=datetime(2005, 1, 1)
... )
You could use any one of the several libraries to parse the time in the string to datetime
objects. The easiest would be to use the awesome dateutil library:
import dateutil.parser
dateutil.parser.parse('2008-08-09T18:39:22Z')
#Following is returned
datetime.datetime(2008, 8, 9, 18, 39, 22, tzinfo=tzutc())
You've probably already found the answer but it could be useful to someone (like myself!) still looking into this.
Django 1.6+ :
You can customise the search results:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results
Previous Django versions:
You just need to use your own ChangeList to temporary change the date format in the query string. Note that the format is only changed temporarily so that the user won't see any change in the query string.
The example here below accepts UK date format, e.g. '31 Dec 1999' but it can easily changed to accept any date format (or just a month name like 'June' as requested by #nemesisfixx)
In your admin model customise the changelist class:
class MyModelAdmin(admin.ModelAdmin):
...
def get_changelist(self, request, **kwargs):
"""
Returns the ChangeList class for use on the changelist page.
"""
return MyChangeList
Then in MyChangeList class:
class MyChangeList(ChangeList):
def get_query_set(self, request):
# Allow date search with UK format
try:
date_search = datetime.datetime.strptime(self.query, '%d %b %Y').date().strftime('%Y-%m-%d')
except ValueError:
date_search = self.query
with temporary_value(self, 'query', date_search):
qs = super(MyChangeList, self).get_query_set(request)
return qs
I am building a web app that needs i18n support. It dispays dates and times in templates as well as via Ajax calls.
I have USE_I18N and USE_L10N set to True and 'django.middleware.locale.LocaleMiddleware' installed. In my template when I do value|date on a queryset passed in context it is correctly formatted to browser locale. When I serialize the output of my model it is not. I have read all the doc and can't see how to do it.
Basically I have a model with a DateTimeField. I am trying to return it to Javascript via Ajax in a localized format. I am using serialize to return it but the date time is not formatted to locale.
See below:
Model:
class Messages(models.Model):
message = models.CharField(max_length=500)
date_created = models.DateTimeField(auto_now_add=True)
thread_id = models.IntegerField(db_index=True)
Web Service View:
def get_message_thread(request):
message_thread = request.POST['message_thread']
message_threads = Messages.objects.filter(thread_id=message_thread)
from django.core.serializers import serialize
json = serialize("json", message_threads, fields=('id', 'message' 'date_created'))
return HttpResponse(json, 'content-type:javascript/json')
Does anyone have anty ideas on what I need to do to make a correctly locale formatted date time accessible to my javascript for display in my page?
Many thanks
Rich
You'll need to rething serialization but basic idea is as fallows:
from django.utils import formats
date_format = formats.get_format('DATE_FORMAT')
serialized_date = date.strftime(date_format)
More info can be found at django-documentation: Date format helper functions