17

私の質問がばかげていることが判明した場合は申し訳ありませんが、私は Django を初めて使用するので、どこにも答えが見つかりませんでした。

私は次のモデルを持っています:

class BlackListEntry(models.Model):
  user_banned = models.ForeignKey(auth.models.User,related_name="user_banned")
  user_banning = models.ForeignKey(auth.models.User,related_name="user_banning")

さて、次のようなオブジェクトを作成しようとすると:

BlackListEntry.objects.create(user_banned=int(user_id),user_banning=int(banning_id))

次のエラーが表示されます。

Cannot assign "1": "BlackListEntry.user_banned" must be a "User" instance.

もちろん、次のようなものに置き換えると:

user_banned = User.objects.get(pk=user_id)
user_banning = User.objects.get(pk=banning_id)
BlackListEntry.objects.create(user_banned=user_banned,user_banning=user_banning)

すべて正常に動作します。質問は:

私のソリューションはデータベースにヒットして両方のユーザーを取得しますか? はいの場合、ID を渡すだけで回避できますか?

4

2 に答える 2

25

あなたの質問への答えは: はい。

Django はデータベースに (少なくとも) 3 回ヒットします。2 回目は 2 つの User オブジェクトを取得し、3 回目は目的の情報をコミットします。これにより、絶対に不要なオーバーヘッドが発生します。

ちょうど試して:

BlackListEntry.objects.create(user_banned_id=int(user_id),user_banning_id=int(banning_id))

これらは、Django ORM によって生成される FK フィールドのデフォルトの名前パターンです。このようにして、情報を直接設定し、クエリを回避できます。

すでに保存されている BlackListEntry オブジェクトを照会する場合は、次のように、2 つのアンダースコアを使用して属性をナビゲートできます。

BlackListEntry.objects.filter(user_banned__id=int(user_id),user_banning__id=int(banning_id))

これは、Django クエリセットのプロパティにアクセスする方法です。二重下線付き。次に、属性の値と比較できます。

非常に似ていますが、機能はまったく異なります。最初のものは属性を直接設定し、2番目のものはdjangoによって解析され、「__」で分割され、データベースを正しい方法でクエリします.2番目の部分は属性の名前です。

ID ではなく、実際の User オブジェクトとuser_bannedいつでも比較できます。user_banningただし、これらのオブジェクトをまだ持っていない場合、これは役に立ちません。

それが役に立てば幸い。

于 2012-10-01T23:10:39.827 に答える
0

ユーザーをフェッチすると、データベースにヒットすると思います...

これを回避するには、ここで説明する方法を使用して更新を行う生の SQL を記述する必要があります。

https://docs.djangoproject.com/en/dev/topics/db/sql/

そのルートに進むことにした場合は、SQL インジェクション攻撃から身を守る責任があることに注意してください。

もう 1 つの方法は、user_banned および user_banning オブジェクトをキャッシュすることです。

しかし、おそらく、ユーザーを取得して BlackListEntry を作成するだけでは、顕著なパフォーマンスの問題は発生しません。生のSQLをキャッシュまたは実行しても、わずかなメリットしかありません。これが問題になる前に、おそらく他の問題に遭遇するでしょう。

于 2012-10-01T22:55:49.467 に答える