如何在 django admin 中从 URL 预填充
DateTimeField
?
假设您的型号是:
class MyModel(models.Model):
name = models.CharField(max_length=14)
date = models.DateTimeField()
然后,您可以通过将值作为 GET 参数传递到添加视图来预先填充模型“添加”表单,例如:
/admin/app/mymodel/add/?name=Test
这是一个非常酷的功能,但是如何在 DateTimeField 中实现此功能?
我尝试了很多可能的格式但没有成功。
更新:
这似乎不可能做到,因为 django admin 使用
SplitDateTimeWidget
来表示 DateTimeField
。但如果您不介意使用不同的小部件并失去日期选择器,则可以使用 DateTimeInput
小部件代替。
最快的方法是将其添加到您的
ModelAdmin
课程中:
formfield_overrides = {
models.DateTimeField: {'widget': DateTimeInput},
}
首先定义序列化/反序列化格式:
DATETIME_FORMAT="%Y-%m-%d %H:%M:%S"
然后当您想打开管理网址时使用它:
copiedArguments = {
"fromDateTime": event.fromDateTime.strftime(DATETIME_FORMAT)
}
return HttpResponseRedirect(
u"{}?{}".format(reverse('admin:events_event_add'), urllib.urlencode(copiedArguments)))
最后但并非最不重要的一点是在模型管理中提取日期时间:
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
问题似乎出在小部件上。
DateField
可以与 ?date=yyyy-mm-dd
配合使用,但 DateTimeField
使用 SplitDateTimeWidget
。它不能将字符串作为初始值。
也许您可以建议对
SplitDateTimeWidget
进行补丁来尝试转换字符串值,或者您可以更改 DateTimeField
的管理默认小部件(如果可能的话)。
现在有
get_changeform_initial_data
ModelAdmin 方法。
我传递的查询参数如下:
?start=08/09/2022 12:30&end=08/09/2022 17:00
通过重写这样的方法,它可以正常工作:
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
在此问题的评论中也提到了,对于那些在 Django 管理中尝试从查询参数预填充日期时间字段时遇到错误
'str' object has no attribute 'utcoffset'
的人很有用。
这是 Django 的错误。您必须重写 SplitDateTimeWidget 的解压缩方法。将此代码放在您的管理类附近
class FixedSplitDateTimeWidget(SplitDateTimeWidget):
def decompress(self, value):
if isinstance(value, str):
value = datetime.fromisoformat(value)
return super().decompress(value)
class FixedHiddenSplitDateTimeWidget(SplitHiddenDateTimeWidget):
def decompress(self, value):
if isinstance(value, str):
value = datetime.fromisoformat(value)
return super().decompress(value)
class FixedSplitDateTimeForm(forms.SplitDateTimeField):
widget = FixedSplitDateTimeWidget
hidden_widget = FixedHiddenSplitDateTimeWidget
并将此代码添加到您的管理类中。
formfield_overrides = {
models.DateTimeField: {
"form_class": FixedSplitDateTimeForm,
"widget": FixedSplitDateTimeWidget,
},
}