How to serialize localized date in Django - django

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

Related

TimeField returning None in Django

I have an existing database I need to pull data from the timestamp field in Django. I created the Django model as a TimeField, but when I query the data I get 'None' instead of the data in the timestamp field.
From my model class: (there is more in the model, I just condensed this for readability)
class Report(models.Model):
upload_time = models.TimeField()
date = models.CharField(max_length=9)
#staticmethod
def get_reports(**query):
reports = Report.objects.order_by('date').filter(query)
for report in reports:
print(report.upload_time)
In my views.py I have a method that checks for the date I am looking for to pull all reports from that date. The database saved the date as a string, so I get that ok, then just turn it into a datetime object and call my get_reports method by passing the date into it. It works to get everything from the report except the timestamp.
What am I missing?

Change date format in Django admin page [duplicate]

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.

I can not change the date format in django drf

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

Django query using datetime flter

In my (Post) model I have
published = models.DateField(null=True)
My urls include the year/month/day eg
/post/category-1/2017/11/06/some-post/
which I am capturing through kwargs in my urls.py
In my view my query is
model = Post.objects.get(slug=kwargs['slug'],published__year=kwargs['year'],
published__month=kwargs['month'],published__day=kwargs['day'])
However, this is not working. The only date element which works is for year. I've read some posts here which talk about unsetting USE_TZ in settings.py which is obviously not a solution.
I have tried using a DateTime field as well, but that makes no difference.
Any help much appreciated.
Have a look at :
import datetime
sDate = '2017/11/06'
dtDate = datetime.datetime.strptime(sDate, "%Y/%m/%d")
models = Post.objects.filter(slug=kwargs['slug'],published=dtDate)
But this implies that you have the correct value in sDate. So as kristab requested pls post your url pattern

Django rest framework: automatically create a url for each field of a model

I have large table of data (~30 Mb) that I converted into into a model in Django. Now I want to have access to that data through a REST API.
I've successfully installed the Django REST framework, but I'm looking for a way to automatically create a URL for each field in my model. My model has about 100 fields, and each field has about 100,000 entries.
If my model is named Sample,
models.py
class Sample(models.Model):
index = models.IntegerField(primary_key=True)
year = models.IntegerField(blank=True, null=True)
name = models.TextField(blank=True, null=True)
...97 more fields...
then I can access the whole model using Django REST framework like this:
urls.py
class SampleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Sample
fields = ( **100 fields**)
class SampleViewSet(viewsets.ModelViewSet):
queryset = Sample.objects.all()
serializer_class = SampleSerializer
router = routers.DefaultRouter()
router.register(r'sample', SampleViewSet)
But of course my browser can't load all of that data in a reasonable amount of time. I could manually make a different class and URL for each field, but there must be a better way... I want to be able to go to my_site.com/sample/year (for example) and have it list all of the years in JSON format, or my_site.com/sample/name and list all the names, etc.
Please help me figure out how to do this, thanks!
You might be able to do that using a custom viewset route.
You have this:
class ModelViewSet(ModelViewSet):
#list_route()
def sample_field(self, request):
desired_field = request.data.get('field', None)
if not desired_field:
return response # pseudocode
values = Model.objects.all().values_list(desired_field, flat=True)
# serialize this for returning the response
return Response(json.dumps(values)) # this is an example, you might want to do something mode involved
You will be able to get this from the url:
/api/model/sample_field/?field=foo
This extra method on the viewset will create a new endpoint under the samples endpoint. Since it's a list_route, you can reach it using /sample_field.
So following your code, it would be:
mysite.com/sample/sample_field/?field='year'
for example.
There are many interesting details in your question, but with this sample I think you might able to achieve what you want.
Try to use pagination. You can do it in almost the same way as in you question. Pagination in django lets you divide the results into pages. You don't have to display all the entries in the same page. I think this is the best option for you.
Refer django documentation on pagination:
Pagination in django