Change DateInput widget's format to SHORT_DATE_FORMAT - django

I'm trying to set the format of a DateInput to SHORT_DATE_FORMAT. However, the following code does not work work.
forms.py
from django.conf.global_settings import SHORT_DATE_FORMAT
class EventForm(ModelForm):
# ...
startDate = forms.DateField(
widget=forms.DateInput(
format=SHORT_DATE_FORMAT
)
)
In the views.py, an example entry is read from the database and a form is created using form = EventForm(instance=event1). The template then shows that widget using {{form.startDate}}. The input shows up correctly, only it's value is not a date but just "m/d/Y".
It would work if I'd set format='%m/%d/%Y', however, that defeats the purpose of the locale-aware SHORT_DATE_FORMAT. How can I properly solve that?

A possible solution is to overwrite the DateInput widget as follows.
from django.template.defaultfilters import date
class ShortFormatDateInput(DateInput):
def __init__(self, attrs=None):
super(DateInput, self).__init__(attrs)
def _format_value(self, value):
return date(value, formats.get_format("SHORT_DATE_FORMAT"))
It overwrites the super constructor so that the date format cannot be changed manually anymore. Instead I'd like to show the date as defined in SHORT_DATE_FORMAT. To do that, the _format_value method can be overwritten to reuse the date method defined django.templates.

Related

How to use django-jalali calendar in tempates?

Im new to Django and im trying to use django in a Persian app, therefore I need users pick i a date(jalali date) and send it to server.
I've used django-jalali in admin area and its working fine, but I need to use this in front-end too.
I've set locale to Asia/Tehran and Time Zone to fa but default date picker shows up Gregorian calendar. please help me with that. How can I solve this?
there is a package called django-jalali-date which provide you good tools to work with jalali dates. Here is an example of how you can add jalali_date input with datepicker from it's doc
from django import forms
from jalali_date.fields import JalaliDateField, SplitJalaliDateTimeField
from jalali_date.widgets import AdminJalaliDateWidget,
AdminSplitJalaliDateTime
class TestForm(forms.ModelForm):
class Meta:
model = TestModel
fields = ('name', 'date', 'date_time')
def __init__(self, *args, **kwargs):
super(TestForm, self).__init__(*args, **kwargs)
self.fields['date'] = JalaliDateField(label=_('date'), # date format is "yyyy-mm-dd"
widget=AdminJalaliDateWidget # optional, to use default datepicker
)
# you can added a "class" to this field for use your datepicker!
# self.fields['date'].widget.attrs.update({'class': 'jalali_date-date'})
self.fields['date_time'] = SplitJalaliDateTimeField(label=_('date time'),
widget=AdminSplitJalaliDateTime # required, for decompress DatetimeField to JalaliDateField and JalaliTimeField
)

Setting the Format for the Django DatetimeInput Widget

I would like to use the included Django DateTimeInput widget as a datetimepicker on my website. No matter what I try however, the widget returns a datetime value in an incorrect format which will not send to my database.
I need the format '%Y-%m-%d %H:%M:%S', but the widget returns '%d/%m/%Y %H:%M:%S'
This problem has been discussed a tad here:
http://stackoverflow.com/a/35968816/1382297
I believe the problem may be from setting the input_type to DateTime-local, but I don't know other options and cannot find any in the documentation. I've tried passing format='%Y-%m-%d %H:%M:%S' to the widget, as well as FORMAT_INPUTS = ['%Y-%m-%d %H:%M:%S'], and tried initializing these in the DateInput class, all with no luck.
Here is my forms.py
class DateTimeInput(forms.DateTimeInput):
input_type = 'datetime-local'
class EnterMatchForm(forms.ModelForm):
class Meta:
model = match
fields = ('match_name', 'player1', 'player2', 'victory', 'match_description', 'match_date')
widgets = {
'match_date': DateTimeInput(),
}
What is the right way to set up the widget so that it returns datetime values in the format Y-m-d H:M:S? Thanks in advance!
You have to pass input_formats not formats or FORMAT_INPUTS.
https://docs.djangoproject.com/en/3.0/ref/forms/fields/#datetimefield

Django: how to change the value of a field one changing another?

I have 2 fields in a model I need that when I change the value of a field to calculate the other
Example:
Date_mission1_equipe=models.DateField (null=True,blank=True,max_length=200)
Date_mission2_equipe=models.DateField (null=True,blank=True,max_length=200)
for example if i choose 01/01/2019 for Date_mission1_equipe automatically Date_mission2_equipe should be 02/01/2019
There are few ways to handle this. You could override the model save method. Or perhaps the cleanest is to use a pre_save signal, as shown below.
from django.db.models.signals import pre_save
def change_date(sender, instance, **kwargs):
my_object = MyModel.objects.get(id=instance.id)
if instance.Date_mission1_equipe:
a.Date_mission2_equipe = ...
pre_save.connect(change_date, sender=MyModel)
It is often recommended not to store calculated values like this in the database. Instead, just perform the calcaultion when you will need it.
from datetime import timedelta
class Mission(models.Model):
date_mission1_equipe = models.DateField(null=True, blank=True)
#property
def date_mission2_equipe(self):
return self.date_mission1_equipe + timedelta(days=1)
You can now do something like this:
first_mission = Mission.objects.get(id=1)
first_mission.date_mission1_equipe
<01/01/2019>
first_mission.date_mission2_equipe
<02/01/2019>
That's just an example. The date would probably need to be formatted for your needs, and will not automatically output in the format I put above.
Also, you do not need max_length on a DateField. It makes no sense for this field type.

Converting string into datetime within Django modelform

I would like to accept natural language strings into a DateTime field, on a form generated by a Django ModelForm. I found Converting string into datetime, which explains how to convert the input string into a DateTime object. (In this case, I'm using timestring for the conversion, instead of strptime as suggested in the answers, because I want to handle input like 'tomorrow'.) But I can't figure out where code this like should be placed within the ModelForm code. If the conversion code is placed in form_valid, it never gets run, because is_python runs first and complains that the text input is not a DateTime. When I override is_python, I get an error that I think comes from some kind of recursive loop.
Relevant code:
models.py
class Widget(models.Model):
name = models.CharField(max_length=100)
widget_date = models.DateTimeField
forms.py
from timestring import Date
class NaturalDateField(forms.DateField):
def to_python(self, value):
if not value:
return none
return Date(value, tz=timezone.get_current_timezone())
class WidgetForm(forms.ModelForm):
widget_date = NaturalDateField()
class Meta:
model = Widget
fields = ['name', 'widget_date']
views.py
class WidgetUpdate(UpdateView):
model = Widget
form_class = WidgetForm
The error on submit is Invlid date string >>. Tracing the code shows that the initial input string converts correctly (to something like '2014-12-26 00:00:00-08:00'), but then the validate() function from site-packages/django/forms/fields.py runs and that goes back into the timestring package for some reason and tries to run def __eq__(self, other): from Date.py, which I think tries to run Date(other), which fails since other is blank.
What is the best method to accept a text string in a ModelForm and then convert it to a field-specific string such as DateTime to be saved in the database?
Looking at that project, your code will return a timestring.Date object, which Django doesn't know what to do with. You probably just need to get the date value from there:
def to_python(self, value):
if not value:
return none
parsed_date = Date(value, tz=timezone.get_current_timezone())
return parsed_date.date
Try reusing builtin django date parsing methods:
class NaturalDateField(forms.DateField):
def to_python(self, value):
value = super(NaturalDateField, self).to_python(value)
return value.replace(tzinfo=timezone.get_current_timezone())

How to I change the rendering of a specific field type in Django admin?

For example I have an IntegerField and I want to change how it is displayed all across Django admin.
I considered subclassing it and overriding __str__ and __unicode__ methods but it doesn't seam to work.
class Duration(models.IntegerField):
def __unicode__(self):
return "x" + str(datetime.timedelta(0, self))
def __str__(self):
return "y" + str(datetime.timedelta(0, self))
Update: I just want to chage the way the field is displayed, not the edit control (widget).
I'm not sure what you want to do with the field, but if you want to change the HTML that is displayed, you need to either change the widget that the form field is using, or create your own custom widget:
https://docs.djangoproject.com/en/dev/ref/forms/widgets/
models.py
class LovelyModel(models.Model):
my_int = models.IntegerField()
forms.py
from widgets import WhateverWidgetIWant
class LovelyModelForm(forms.ModelForm):
my_int = models.IntegerField(widget=WhateverWidgetIWant())
class Meta:
model = LovelyModel
admin.py
from forms import LovelyModelForm
class LovelyModelAdmin(admin.ModelAdmin):
form = LovelyModelForm
What is it you are trying to do?
I think you need something like this (untested code)::
import datetime
from django.db import models
class Duration(models.IntegerField):
description = "Stores the number of seconds as integer, displays as time"
def to_python(self, value):
# this method can receive the value right out of the db, or an instance
if isinstance(value, models.IntegerField):
# if an instance, return the instance
return value
else:
# otherwise, return our fancy time representation
# assuming we have a number of seconds in the db
return "x" + str(datetime.timedelta(0, value))
def get_db_prep_value(self, value):
# this method catches value right before sending to db
# split the string, skipping first character
hours, minutes, seconds = map(int, value[1:].split(':'))
delta = datetime.timedelta(hours=hours, minutes=minutes, seconds=seconds)
return delta.seconds
This, however, changes how the field's value represented in Python at all, not only in admin, which may not be a desired behaviour. I.e., you have object.duration == 'x00:1:12', which would be saved to the database as 72.
See also documentation on custom fields.