Reputation: 9720
Some of my models have postgres-specific django.contrib.postgres.fields.DateTimeRangeField
s, and those fields are exposed in the corresponding admin panels. I expected that the ranges forms would consist of two Django-style datetime pickers, with a separate one for the date part and a separate part for the time part (just like the DateTimeField
would). However, I get two text inputs which expect input in a very particular format. Is there anything I am missing or have to configure separately?
The relevant code is:
from django.contrib.postgres.fields import DateTimeRangeField
...
class MyModel(models.Model):
time_off = DateTimeRangeField()
admin:
@register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
pass
Upvotes: 0
Views: 833
Reputation: 11
To get this working I needed to combine both parts of the split datetimefield (to fix the "list has no method strip()" as other commentors had noted). Some additional validation should probably be present here to ensure "value" has the correct format.
from django.contrib.admin.widgets import AdminSplitDateTime
from django.contrib.postgres.forms import RangeWidget, DateTimeRangeField
from django.forms import ModelForm
class CombinedDateTimeRangeField(DateTimeRangeField):
def combine(self, value):
if value:
return [f"{value[0][0]}:{value[0][1]}", f"{value[1][0]}:{value[1][1]}"]
return None
def clean(self, value):
value = self.combine(value)
return super().clean(value)
def has_changed(self, initial, data):
data = self.combine(data)
return super().has_changed(initial, data)
class MyModelForm(ModelForm):
time_off = CombinedDateTimeRangeField(widget=RangeWidget(AdminSplitDateTime))
class Meta:
model = MyModel
fields = "__all__"
@register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
Upvotes: 1
Reputation: 1211
I used the following:
from django.contrib.admin import widgets as admin_widgets
from django.contrib.postgres import fields as pg
from django.contrib.postgres import forms as pg_widgets
@register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
pg.DateRangeField: {
'widget': pg_widgets.RangeWidget(admin_widgets.AdminDateWidget),
},
}
Works perfectly, with a calendar pop-up, 'today' button, and everything. This is for a Date
, but you should get similar results with a DateTime
.
Upvotes: 4
Reputation: 3920
You are looking for SplitDateTimeWidget.
Simply change the admin part as:
class MyModelAdminForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'time_off': RangeWidget(SplitDateTimeWidget())
}
@register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelAdminForm
or use formfield_overrides
to override the widget if you wish.
Upvotes: 1