今私は最初のDjangoプロジェクトを作成しています.2人のチェスのWebサイトです。私はほとんど終わっており、今はテストを書いています。このプロジェクトには、プレイヤーとゲームの2つのオリジナルモデルがあります。プレイヤーモデルは、Userモデル、Player.user、そしてプレーヤーが現在であるゲームのインスタンスを示しゲームへの外部キー、Player.current_gameに一対一のフィールドを持つ。Game.draw_offered CharFieldですが値をとります「」抽選が提供されたかどうか、およびそれを提供したプレーヤーの色を示す「デフォルト」(デフォルト値)、「w」、または「b」である。Djangoの外部キーの仕組みを理解しようとしています
class Draw_ViewTestCase(TestCase):
def setUp(self):
self.user1 = User.objects.create_user(username="Test_User_1", password="test1")
self.user2 = User.objects.create_user(username="Test_User_2", password="test2")
self.factory = RequestFactory()
self.game = Game.objects.create()
self.player1 = Player.objects.create(user=self.user1, current_game=self.game, color="w")
self.player2 = Player.objects.create(user=self.user2, current_game=self.game, color="b")
def test_draw(self):
request = self.factory.get(reverse('draw'))
request.user = self.user1
#The draw view changes the draw_offered field of the player's current game to the player's color, and saves the current_game to the database
response = draw(request)
self.game.refresh_from_db()
assert self.game.draw_offered == self.player1.color
assert self.game == self.player2.current_game
#self.player2.current_game.refresh_from_db()
assert self.game.draw_offered == self.player2.current_game.draw_offered
すべてのアサーションが合格したが、最後の1をしていますが、最後の行に2つ目のコメントを解除した場合、それが通過する:私は、次のないテストケースを持っています。
何が起こっているのですか?私が理解しているように、外部キー属性self.player2.current_gameを参照すると、Djangoはデータベースルックアップを実行し、最新のフィールドを持つGameインスタンスを返します。 self.gameとself.player2.current_gameはデータベースの同じゲームレコードに対応し、self.game.refresh_from_db()が呼び出されたばかりなので、self.game.draw_offered == self.player2.current_game.draw_offeredどちらのゲームインスタンスも同じデータベースレコードを参照し、最新のフィールドを持っています。アサーションパスを作るためにself.player2.current_game.refresh_from_db()を呼び出さなければならないという事実は、私には意味をなさない - Djangoの外部キーについての私の理解によれば、self.player2.current_gameは自動的に更新されるべきであるデータベースを使用します。
これは私の理解です。あなたがx = self.player2と書くとき。current_gameでは、外部キー属性を介してオブジェクトを参照するときはいつでも、Djangoはデータベース参照を実行するため、xのフィールドは自動的に最新のデータベースに更新されます。あなたの答えは、self.player2.current_gameがメモリに格納されたオブジェクトを指し、データベースとは何の関係もない標準のPython属性参照によく似ていることを暗示しているようです。どちらが正しいか? – Vik78
いいえ、あなたの理解は間違っています、私が第3段落の冒頭で言うように。あなたが最初に*オブジェクトの外部キー属性を参照すると、Djangoはそれをフェッチするためにデータベースに行きます。ただし、それを親オブジェクトに格納するため、後続の参照でそれ以上のデータベース検索が行われることはありません。 (同様に、最初に 'select_related'を使用した場合、DjangoはJOINを実行して関連するオブジェクトを最初から取得してキャッシュしますので、dbの参照は行われません)あなたの場合、Djangoはあなたがそれを作成したときに、dbルックアップを行う必要はありません。 –
{player = request.user.player}、{game = player.current_game}のようなリクエストを受け取るビューがたくさんあり、その動作は{game}の属性に依存します。 {game}の属性が最新であることを保証するためにrefresh_from_db()文を含めるようにこれらのビューを書き直す必要がありますか、または外部キーを参照することでデータベースの参照が保証される特定の状況があります実行されるか?私のプロジェクトはそれなりにうまくいっているようですが、{game}の属性が古くなったら問題があると思います。あなたの助けてくれてありがとう、btw。 – Vik78