180

デフォルトの管理者がカスタム ビューで使用する気の利いた 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全体に関連して初めてなので、簡単に行ってください...

4

17 に答える 17

166

時間の経過とともにこの答えがますます複雑になり、多くのハックが必要になるので、おそらくこれを行うことに対して警告する必要があります。管理者の文書化されていない内部実装の詳細に依存しており、Djangoの将来のバージョンで再び機能しなくなる可能性があり、別のJSカレンダーウィジェットを見つけてそれを使用するよりも実装が簡単ではありません。

そうは言っても、この作業を行うことにした場合は、次のことを行う必要があります。

  1. モデルに独自のサブクラスを定義ModelFormし(アプリのforms.pyに配置するのが最適)、//を使用するように指示しますAdminDateWidgetAdminTimeWidgetAdminSplitDateTimemydate」などをモデルの適切なフィールド名に置き換えます)。

     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': Productcreate_objectfrom my_app.forms import ProductFormfrom my_app.models import Product

  3. テンプレートの先頭に{{ form.media }}、Javascriptファイルへのリンクを出力するためのインクルードを含めます。

  4. そして、ハッキーな部分:admin date / timeウィジェットは、i18n JSのものがロードされていることを前提としており、core.jsも必要ですが、どちらも自動的には提供しません。したがって、上記のテンプレートでは、次の{{ form.media }}ものが必要になります。

     <script type="text/javascript" src="/my_admin/jsi18n/"></script>
     <script type="text/javascript" src="/media/admin/js/core.js"></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>

この追加をしてくれたlupefiascoに感謝します。

于 2008-09-02T06:10:58.127 に答える
65

解決策はハックなので、JavaScript で独自の日付/時刻ウィジェットを使用する方が実現可能だと思います。

于 2008-09-16T13:39:39.303 に答える
14

私はこの投稿を何度も参照していて、ドキュメンテーションがデフォルトのウィジェットをオーバーライドするためのハックの少ない方法を定義していることに気づきました。

( ModelForm の __init__ メソッドをオーバーライドする必要はありません)

ただし、Carl が言及しているように、JS と CSS を適切に配線する必要があります。

フォーム.py

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


class ProductForm(forms.ModelForm):
    mydate = forms.DateField(widget=widgets.AdminDateWidget)
    mytime = forms.TimeField(widget=widgets.AdminTimeWidget)
    mydatetime = forms.SplitDateTimeField(widget=widgets.AdminSplitDateTime)

    class Meta:
        model = Product

デフォルトのフォーム フィールドを見つけるには、フィールド タイプを参照してください。

于 2009-09-08T06:42:05.557 に答える
13

1.4 バージョンのヘッド コード (新しいものと削除されたもの)

{% block extrahead %}

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

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/core.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.init.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/actions.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/calendar.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/DateTimeShortcuts.js"></script>

{% endblock %}
于 2012-07-12T07:06:08.117 に答える
12

はい、/admin/jsi18n/ URL をオーバーライドしてしまいました。

これが私のurls.pyに追加したものです。/admin/ URL の上にあることを確認してください

    (r'^admin/jsi18n', i18n_javascript),

そして、これが私が作成した i18n_javascript 関数です。

from django.contrib import admin
def i18n_javascript(request):
  return admin.site.i18n_javascript(request)
于 2009-01-02T22:53:21.183 に答える
10

Django 1.2 RC1 以降、Django 管理者の日付ピッカー ウィジェット トリックを使用している場合は、テンプレートに次を追加する必要があります。そうしないと、「/missing-admin-media-prefix」で参照されているカレンダー アイコンの URL が表示されます。 /」。

{% 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>
于 2010-05-12T11:03:15.340 に答える
7

Carl Meyer の回答を補足して、テンプレート内の有効なブロック (ヘッダー内) にそのヘッダーを配置する必要があることをコメントしたいと思います。

{% block extra_head %}

<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"/>

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
<script type="text/javascript" src="/media/admin/js/admin/RelatedObjectLookups.js"></script>

{{ form.media }}

{% endblock %}
于 2009-04-05T20:02:00.187 に答える
5

上記が失敗した場合、以下は最後の手段としても機能します

class PaymentsForm(forms.ModelForm):
    class Meta:
        model = Payments

    def __init__(self, *args, **kwargs):
        super(PaymentsForm, self).__init__(*args, **kwargs)
        self.fields['date'].widget = SelectDateWidget()

と同じ

class PaymentsForm(forms.ModelForm):
    date = forms.DateField(widget=SelectDateWidget())

    class Meta:
        model = Payments

これをforms.pyに入れてくださいfrom django.forms.extras.widgets import SelectDateWidget

于 2010-03-07T16:09:57.770 に答える
3

クラスをウィジェットに割り当てて、そのクラスを JQuery 日付ピッカーにバインドするだけではどうでしょうか?

ジャンゴフォーム.py:

class MyForm(forms.ModelForm):

  class Meta:
    model = MyModel

  def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['my_date_field'].widget.attrs['class'] = 'datepicker'

そして、テンプレート用のいくつかの JavaScript:

  $(".datepicker").datepicker();
于 2012-02-04T06:50:50.557 に答える
1

required=Falseを使用したSplitDateTimeの更新されたソリューションと回避策:

フォーム.py

from django import forms

class SplitDateTimeJSField(forms.SplitDateTimeField):
    def __init__(self, *args, **kwargs):
        super(SplitDateTimeJSField, self).__init__(*args, **kwargs)
        self.widget.widgets[0].attrs = {'class': 'vDateField'}
        self.widget.widgets[1].attrs = {'class': 'vTimeField'}  


class AnyFormOrModelForm(forms.Form):
    date = forms.DateField(widget=forms.TextInput(attrs={'class':'vDateField'}))
    time = forms.TimeField(widget=forms.TextInput(attrs={'class':'vTimeField'}))
    timestamp = SplitDateTimeJSField(required=False,)

form.html

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/admin_media/js/core.js"></script>
<script type="text/javascript" src="/admin_media/js/calendar.js"></script>
<script type="text/javascript" src="/admin_media/js/admin/DateTimeShortcuts.js"></script>

urls.py

(r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
于 2009-12-02T14:29:53.093 に答える
0

Django 10 の場合。myproject/urls.py: urlpatterns の先頭

  from django.views.i18n import JavaScriptCatalog

urlpatterns = [
    url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'),
.
.
.]

私のtemplate.htmlで:

{% load staticfiles %}

    <script src="{% static "js/jquery-2.2.3.min.js" %}"></script>
    <script src="{% static "js/bootstrap.min.js" %}"></script>
    {# Loading internazionalization for js #}
    {% load i18n admin_modify %}
    <script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/jquery.init.js" %}"></script>

    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/base.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/forms.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/login.css" %}">
    <link rel="stylesheet" type="text/css" href="{% static "/admin/css/widgets.css" %}">



    <script type="text/javascript" src="{% static "/admin/js/core.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/SelectFilter2.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/admin/RelatedObjectLookups.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/actions.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/calendar.js" %}"></script>
    <script type="text/javascript" src="{% static "/admin/js/admin/DateTimeShortcuts.js" %}"></script>
于 2016-10-09T17:39:01.907 に答える