[解決済み] `SyntaxError: nonlocal 'topics_with_log_tag' のバインディングが見つからない` けど、バインディングはされている
質問
指定した'log'タグを持つトピックを取得したいのですが。
ネストされた関数内
get_topics_with_log_tag
変数
topics_with_log_tag
非局所的である。
def log(request):
"""Show all topics and entries with log tags"""
topics = Topic.objects.all()
#select entries with log tag
def get_topics_with_log_tag(topics):
nonlocal topics_with_log_tag
topics_with_log_tag = []
for topic in topics:
for entry in topic.entry_set.all():
if "#log" in entry.tags:
topics_with_log_tag.append(topic)
get_topics_with_log_tag(topics)
SyntaxError をスローします。
SyntaxError: no binding for nonlocal 'topics_with_log_tag' found
実際、私はそれをバインドしました
topics_with_log_tag = []
上記のコードを冗長に書き直すと、次のようになります。
topics = Topic.objects.all()
#select entries with log tag
def get_topics_with_log_tag(topics):
# nonlocal topics_with_log_tag
topics_with_log_tag = []
for topic in topics:
for entry in topic.entry_set.all():
if "#log" in entry.tags:
topics_with_log_tag.append(topic)
return topics_with_log_tag
topics_with_log_tag = get_topics_with_log_tag(topics)
の使い方のどこが問題なのでしょうか?
nonlocal
?
エラーが見つかりました。
Willem Van Onsemは、ネストされたforループの代わりに、データベースレベルのフィルタを導入しています。
models.py
class Topic(models.Model):
"""A topic the user is learning about."""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)
def __str__(self):
"""Return a string representation of the model."""
return self.text
class Entry(models.Model):
"""Something specific learned about a topic"""
topic = models.ForeignKey(Topic)
title = models.CharField(max_length=200)
text = models.TextField()
tags = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
解決方法は?
どのように
nonlocal
動作
を使用する場合
nonlocal
これは、Pythonが関数の開始時に、1つ上のスコープから同じ名前の変数を探すことを意味します(さらにその先も)。しかし、ここではそのような変数は定義されていません。1つ上の階層にある変数を定義することで解決できます。
def log(request):
"""Show all topics and entries with log tags"""
topics = Topic.objects.all()
#select entries with log tag
topics_with_log_tag = []
def get_topics_with_log_tag(topics):
nonlocal topics_with_log_tag
topics_with_log_tag = []
for topic in topics:
for entry in topic.entry_set.all():
if "#log" in entry.tags:
topics_with_log_tag.append(topic)
get_topics_with_log_tag(topics)
を使用することができます。
global
この場合、変数を宣言する必要はありませんが(この場合は上位で宣言します)、実はこれもアンチパターンです。
Django ORMで効率的なデータベースクエリ
しかし、ここでフィルタリングを実行する方法は、通常、非常に非効率的です。
Topic
を取得し、次に各トピックに対して追加のクエリを実行し、すべての
Entry
を指定し、次に各
Entry
を取得し、すべての
Tag
であるかどうかを調べ、そのタグが
#log
. ここで、10個のトピックがあり、1個のトピックに10個のエントリーがあり、1個のエントリーに5個のタグがあるとします。その結果、データベースレベルで500以上のクエリーを実行することになります。このようなフィルタを構築することができます。
topics_with_log_tag = Topics.objects.filter(entry__tags__contains='#log').distinct()
またはもっと読みやすい(複数行の式を可能にするために括弧が使用されています)。
topics_with_log_tag = (Topics.objects
.filter(entry__tags__contains='#log')
.distinct())
上記は、(あなたのコードと同じように)トピックを含むことに注意してください。
tags
例えば
'#logarithm'
. これは、ある部分文字列を含むかどうかだけをチェックするものです。これを防ぐには、より高度なフィルタリングを行うか、(エンドマーカーを使った)より優れたタグ表現が必要になります。
例えば、すべてのトピックがコンマで終わっている場合(例えば
'#foo,#bar,'
をクエリすることができます。
'#log,'
.
また、正規表現を用いて、新しいハッシュ文字や、文字列の終わりをチェックすることもできます。
関連
-
[解決済み] Django: OperationalError そのようなテーブルがない
-
[解決済み] Django: 基数が 10 の int() のリテラルが無効です。
-
[解決済み] NoReverseMatch at /
-
[解決済み] Django-Rest-Framework ルータ登録
-
[解決済み] Django - 円形モデルのインポートの問題
-
[解決済み] Django - テンプレートのforループで番号を反復する
-
[解決済み】Django - クエリ結果を制限する
-
[解決済み] djangoのテンプレートで文字列を連結する方法は?
-
[解決済み】Django MEDIA_URL と MEDIA_ROOT
-
[解決済み] Django restフレームワーク、同じModelViewSetで異なるシリアライザーを使用する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] django Forms のラジオボタン
-
[解決済み] Django における cleaned_data の用途は?
-
[解決済み] django 1.7 migrate で "table already exists" というエラーが発生する。
-
[解決済み] DISTINCT ON フィールドは、このデータベースバックエンドではサポートされていません。
-
[解決済み] django 上書きフォームクリーンメソッド
-
Django: OperationalError そのようなテーブルがない
-
エラーの場合 環境変数 DJANGO_SETTINGS_MODULE を定義する必要があります ... 問題解決
-
[解決済み】Djangoのフォームセットにフォームを動的に追加する
-
[解決済み】Djangoでメールテンプレートを作成する
-
[解決済み】Djangoのvalues_listとvaluesの比較