在 django admin 中从 URL 预填充 DateTimeField

问题描述 投票:0回答:4

如何在 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},
}
django django-models django-admin
4个回答
6
投票

首先定义序列化/反序列化格式:

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

3
投票

问题似乎出在小部件上。

DateField
可以与
?date=yyyy-mm-dd
配合使用,但
DateTimeField
使用
SplitDateTimeWidget
。它不能将字符串作为初始值。

也许您可以建议对

SplitDateTimeWidget
进行补丁来尝试转换字符串值,或者您可以更改
DateTimeField
的管理默认小部件(如果可能的话)。


1
投票

现在有

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'
的人很有用。


0
投票

这是 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,
        },
    }
© www.soinside.com 2019 - 2024. All rights reserved.