カスタムフォームでDjangoの時刻/日付ウィジェットを使用する 質問する

カスタムフォームでDjangoの時刻/日付ウィジェットを使用する 質問する

デフォルトの管理者が使用する便利な 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 全般に関してはあまり詳しくないので、お手柔らかにお願いします...

ベストアンサー1

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

そうは言っても、これを成功させると決心した場合には、次のことを行う必要があります。

  1. ModelFormモデルに独自のサブクラスを定義し(アプリの forms.py に配置するのが最適)、 AdminDateWidget/ AdminTimeWidget/を使用するように指示しますAdminSplitDateTime(「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 ProductFormfrom my_app.models import Product

  3. テンプレートのヘッドに、{{ form.media }}JavaScript ファイルへのリンクを出力するように含めます。

  4. そして、ハックな部分: 管理日付/時刻ウィジェットは、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を使用することもできます(ありがとうアレックスこれを言及していただきありがとうございます):

    <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) に接続する必要があります。管理アプリケーションを経由するのではなく、自分でこれを行う必要があります。これにより、管理にログインしているかどうかに関係なくアクセスできるようになります (ジェレミー指摘していただきありがとうございます。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>

ありがとうルペフ​​ィアスコこの追加について。

おすすめ記事