小编典典

以自定义形式使用 Django 时间/日期小部件

all

如何使用默认管理员在我的自定义视图中使用的漂亮的 JavaScript 日期和时间小部件?

我浏览了 Django 表单文档,它简要提到了
django.contrib.admin.widgets,但我不知道如何使用它?

这是我想要应用的模板。

<form action="." method="POST">
    <table>
        {% for f in form %}
           <tr> <td> {{ f.name }}</td> <td>{{ f }}</td> </tr>
        {% endfor %}
    </table>
    <input type="submit" name="submit" value="Add Product">
</form>

另外,我认为应该注意的是,我自己并没有真正为这个表单编写视图,我使用的是通用视图。这是来自 url.py 的条目:

(r'^admin/products/add/$', create_object, {'model': Product, 'post_save_redirect': ''}),

而且我对整个 Django/MVC/MTV 的事情都比较陌生,所以请放轻松…


阅读 87

收藏
2022-08-05

共1个答案

小编典典

随着时间的推移,这个答案越来越复杂,并且需要许多技巧,可能应该警告你不要这样做。它依赖于管理员未记录的内部实现细节,很可能在未来版本的 Django
中再次出现问题,而且实现起来并不比找到另一个 JS 日历小部件并使用它更容易。

也就是说,如果您决心完成这项工作,您必须执行以下操作:

  1. 为您的模型定义您自己的ModelForm子类(最好将其放在应用程序中的 forms.py 中),并告诉它使用AdminDateWidget// AdminTimeWidgetAdminSplitDateTime将“mydate”等替换为模型中的正确字段名称):

     from django import forms
    

    from my_app.models import Product
    from django.contrib.admin import widgets

    class ProductForm(forms.ModelForm):
    class Meta:
    model = Product
    def init(self, args, kwargs):
    super(ProductForm, self).init(
    args, **kwargs)
    self.fields[‘mydate’].widget = widgets.AdminDateWidget()
    self.fields[‘mytime’].widget = widgets.AdminTimeWidget()
    self.fields[‘mydatetime’].widget = widgets.AdminSplitDateTime()

  2. 将您的 URLconf 更改为传递'form_class': ProductForm而不是传递'model': Product给通用create_object视图(当然,这意味着from my_app.forms import ProductForm而不是from my_app.models import Product)。

  3. 在模板的头部,包含{{ form.media }}以输出指向 Javascript 文件的链接。

  4. 和 hacky 部分:管理日期/时间小部件假定 i18n JS 的东西已经加载,并且还需要 core.js,但不自动提供任何一个。因此,在您上面的模板中,{{ form.media }}您需要:

     <script type="text/javascript" src="/my_admin/jsi18n/"></script>
    

您可能还希望使用以下管理 CSS(感谢Alex提到这一点):

    <link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
    <link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>

这意味着 Django 的管理媒体 ( ADMIN_MEDIA_PREFIX) 位于 /media/admin/ -
您可以为您的设置更改它。理想情况下,您会使用上下文处理器将此值传递给您的模板,而不是对其进行硬编码,但这超出了此问题的范围。

这还需要手动将 URL /my_admin/jsi18n/ 连接到 django.views.i18n.javascript_catalog
视图(如果您不使用 I18N,则为
null_javascript_catalog)。您必须自己执行此操作,而不是通过管理应用程序,因此无论您是否登录到管理员都可以访问它(感谢Jeremy指出这一点)。URLconf 的示例代码:

(r'^my_admin/jsi18n', 'django.views.i18n.javascript_catalog'),

最后,如果您使用的是 Django 1.2 或更高版本,您需要在模板中添加一些额外的代码来帮助小部件找到它们的媒体:

{% load adminmedia %} /* At the top of the template. */

/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>
2022-08-05