事前に知っておくべきDjangoの機能

ジャンゴ



Djangoは素晴らしいです。 実際、Djangoの出現と開発によって世の中にどれだけの善が現れたかを書くと、非常に長い間書くことができ、それでもすべてを語ることはできません。 個人的に、私は4年半の間Djangoを絶えず使用してきましたが、この間Djangoはどんどん良くなっています。



それでも、ある時点で、ドキュメントにすべてが揃っているわけではないことに気付きます。 そして、ここでは問題を解決するためのオプションが異なって表示されます-Djangoのソースを開くことができ、Stackoverflowや他の場所(メーリングリストや公式Tracが役立つことが多い)でそれについて書いているのを見ることができますが、これらすべてを一緒にするとさらに良いです。



日常業務で必要になる可能性があるもののほんのいくつかの例を見てみましょうが、公式ドキュメントでは(これまでのところ)読みません。 ただし、何か他のものを追加する必要があると思われる場合-書き込み、これは本当にそうかもしれません。



1.すべてのモデルオブジェクトの選択(1ページに収まらないオブジェクトがある場合)および中間ページ(中間ページ)を持つ管理インターフェイスのアクション(管理アクション)。



管理インターフェースで独自のアクションがありますか? 中間ページを使用していますか? はいの場合、この非常に中間的なページを表示するときに、クエリセットがどこから来たのかを確認してください。



なぜなら、それがこの方法で行われた場合( ドキュメントで説明されているように ):



selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
      
      





次に、アクションがトリガーされるという事実に遭遇しますが、たとえば、選択されたモデルのすべてのオブジェクトではなく、最初の100個のオブジェクト(ページに100が表示されている場合)に対してのみです。



実際、通常、中間ページには、オブジェクト番号を持つ非表示フィールド( "_selected_action")を含むフォームが表示されます。



それは(ModelAdminで):



  class AssignBooksForm(forms.Form): _selected_action = forms.CharField(widget=forms.MultipleHiddenInput) user = forms.ModelChoiceField(queryset=User.objects.all(), label=u"", empty_label=None) def assign_books(self, request, queryset): form = None if 'cancel' in request.POST: self.message_user(request, u'  .') return elif 'assign' in request.POST: form = self.AssignBooksForm(request.POST) if form.is_valid(): user = form.cleaned_data['user'] for book in queryset: assign_book(book.pk, user.pk) self.message_user(request, u'  (%s)   %s.' % (queryset.count(), user.username)) return HttpResponseRedirect(request.get_full_path()) if not form: form = self.AssignBooksForm(initial={'_selected_action': queryset.values_list('os_id', flat=True)}) return render_to_response('books/assign_books.html', {'books': queryset, 'form': form, 'path':request.get_full_path()}, context_instance=RequestContext(request)) assign_books.short_description = u'  ' actions = ['assign_books']
      
      





しかし、実際の確率は、そのような線ではなく、



 form = self.AssignBooksForm(initial={'_selected_action': queryset.values_list('id', flat=True)})
      
      





このような行(たとえば、 ここ ):



 form = self.AssignBooksForm(initial={'_selected_action': request.POST.getlist(admin.ACTION_CHECKBOX_NAME)})
      
      





この場合、特に興味深いことがわかります。 ユーザーがすべてのオブジェクトを選択すると(列名の左側にあるボックスをチェックし、レコードのリストがある表の上にある[すべて選択...(...)]をクリックしたため)、JSは非表示フィールド「select_across」の値を1に設定するため、その後、ModelAdmin.response_action( contrib.admin.options)、select_across(BooleanField)がフォーム(contrib.admin.helpers.ActionForm)に設定されていることを検出すると、クエリセットをチェックされるオブジェクトに限定せず、完全なクエリセット(ただし内容もちろん、リクエストオブジェクト、response_actionメソッドは変更されません)。



そして、このようなものがテンプレートに表示されている場合:



 <p>      :</p> <ul> {% for book in books %} <li>{{ book }}</li> {% endfor %} </ul>
      
      





リストが正しいこと(たとえば、最初の100個だけでなく、すべてのオブジェクトが含まれます)-books変数のテンプレートのコンテキストではquerysetであるためです。 しかし、フォームでは、クエリセットに基づく識別子のリストではなく、チェックされたチェックマークのリストである場合があります。 この場合、中間ページからフォームを送信すると、100個のエントリのみが既にクエリセットに含まれているため、アクションはそれらのエントリのみで実行されます。



ちなみに、 この投稿のコメントにはこれに関する議論があり、Tracのチケットもあります。



2.テキストファイルへの日付と時刻の記録。



一般に、非常に単純なタスクですが、ドキュメントでこれを行う方法は示されていません。 それにもかかわらず、フォーマッター辞書を指定する可能性はを渡すことで言及されており、小さな例でさえ与えられています(ただし、日時はありません)。



実際、すべてが本当にシンプルです:



 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '[%(levelname)s] %(asctime)s %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler' }, 'books_log_file':{ 'level': 'DEBUG', 'class': 'logging.FileHandler', 'formatter': 'verbose', 'filename': os.path.join(PROJECT_ROOT, 'logs/books.log'), }, }, 'loggers': { 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, 'books': { 'handlers': ['books_log_file', 'mail_admins'], 'level': 'INFO', 'propagate': True, }, } }
      
      





ここでは、もちろん、PROJECT_ROOTの設定がより高く設定されていることを前提としています。 たとえば、次のように:



 import os PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
      
      





また、他に何かする必要がある場合は、 Pythonのドキュメントを参照できます



3.元のテキスト文字列が英語で書かれていない場合のサイトのローカライズ。



Djangoに組み込まれたローカリゼーションシステムは、一般にうまく機能しますが、1つの機能があります。 実際、 JS行翻訳し 、これらの行が英語で書かれていない場合(ただし、たとえばロシア語)、英語の翻訳を作成するとすぐに(django-admin.py makemessages -l en -d djangojs)およびdjangojs.poをコンパイルすると、この翻訳は英語が選択されたときだけでなく、ロシア語が選択されたときにも表示され始めます。



つまり、ロシア語を選択すると、JSは英語の文字列を表示します(ロシア語の翻訳が見つからず、代わりに英語が使用されるためです-この場合、文字列の元は既にロシア語であるため、翻訳は実際には必要ありません)



解決策 (もちろん、ロシア語のテキストのロシア語の翻訳を作成するという考えをすぐに放棄したのでない限り)は非常に簡単です。



次のパターンをurls.pyに追加する必要があります。



 url(r'^jsi18n/null/$', 'django.views.i18n.null_javascript_catalog'),
      
      







そして、テンプレート(通常はbase.html)を編集して、そこに追加します:



 {% if request.LANGUAGE_CODE == 'ru' %} <script type="text/javascript" src="{% url django.views.i18n.null_javascript_catalog %}"></script> {% else %} <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script> {% endif %}
      
      





もちろん、django.views.i18n.javascript_catalogのurlpatternはすでに存在していると想定されています。



4.サイトを指定せずに単純なページ(フラットページ)を追加します。



現在の安定版のDjangoにはバグが1つあります。flatpagesアプリケーションを接続している場合、そのようなページを作成するときに、リストからサイトを選択するのを誤って忘れ、500エラーを受け取るか、DEBUGが有効になっている場合:



/ admin / flatpages / flatpage / add /のValueError

クエリ値としてNoneを使用することはできません



もちろん、開発者はすでにこのエラーを認識しています。さらに、3か月前に修正されました。 実際、それを修正するコミットでは、1行の変更(およびテスト)のみが行われているため、Djangoに自分で簡単にパッチを適用できます。 まだ安定していません(数日前のDjango 1.4.1のリリースを含む)



一般に、検索を使用し、かなり詳細なデータ収集を行い、テストします。 何らかの解決策でも機能しているように思える場合は、どこにでもニュアンスがあるかもしれないことに留意してください。 素晴らしい開発を!




All Articles