1

ManyToMany 関係を持つ 2 つのモデルがあります。コードは次のとおりです。

class Player(models.Model):

    first_name = models.CharField(max_length = 30, verbose_name = u"First name")
    last_name = models.CharField(max_length = 50, verbose_name = u"Last name")

    def __unicode__(self):
        return "%s %s" % (self.last_name, self.first_name)

class Tournament(models.Model):
    title = models.CharField(max_length = 100, verbose_name = u"Tournament's title")
    players = models.ManyToManyField(Player,verbose_name = u"Tournament's players")

    def __unicode__(self):
        return self.title

    def save(self, **kwargs):
        Tournament(title = self.title)
        all_players = Player.objects.all()
        for member in all_players:
            member_of_tournament = member.tournament_set.filter(title = self.title)
            for j in member_of_tournament:
                print member.tournament_set.filter(title = self.title)
                self.players.add(member)

        super(Tournament, self).save(**kwargs)

初めてトーナメントを保存すると、タイトルだけが保存されます。しかし、次に保存すると、プレイヤーも保存され、トーナメントに関連付けられます。トーナメントと同時にそれらを保存するにはどうすればよいですか?

4

1 に答える 1

4

ここにいくつかの問題があると思います:

class Tournament(models.Model):
    title = models.CharField(max_length = 100, verbose_name = u"Tournament's title")
    players = models.ManyToManyField(Player,verbose_name = u"Tournament's players")

    def __unicode__(self):
        return self.title

    def save(self, **kwargs):
        Tournament(title = self.title)
        all_players = Player.objects.all()
        for member in all_players:
            member_of_tournament = member.tournament_set.filter(title = self.title)
            for j in member_of_tournament:
                print member.tournament_set.filter(title = self.title)
                self.players.add(member)

        super(Tournament, self).save(**kwargs)

一般に、モデルの save メソッドに m2m 関係を持たせたくありません (この場合、そのロジックはどのような場合でもあまり良くありません)。

save メソッド自体にいくつかの問題があるので、それらに対処しましょう。

def save(self, **kwargs):
    Tournament(title = self.title)

上記の最後の行は何もしていません。Tournament のインスタンスをインスタンス化しますが、変数には保存しません。とにかく、実際にはすでにトーナメントのインスタンスがあります(この場合、selfと呼ばれます)。

    all_players = Player.objects.all()
    for member in all_players:
        member_of_tournament = member.tournament_set.filter(title = self.title)

ここでは、クエリに一致するかどうかに関係なく、DB 内のすべてのプレーヤーをループします。

これは本当に非効率的です。

次の行には、member_of_tournament = member.tournament_set.filter(title = self.title). これは複数形なので、members_of_tournamentこれは配列/リスト/クエリセットなので、これを呼び出す必要があります。

正直なところ、残りの戦略が何であるかはわかりませんが、おそらくそのようにすべきではないと言えば十分です.

カスタム保存メソッド全体に乗るだけで、これを駆動しているビューで次のようにする必要があります。

tournament = Tournament(title=title)
tournament.save()
players_i_care_about = [players, go, here]

tournament.players = players_i_care_about #(removes all players and saves new players)

また

for player in players_i_care_about:
    tournament.players.add(player) #(only adds these players, doesn't remove any players)

この理由は、ビューはどのプレーヤーがどのトーナメントに属しているかを知っていますが、モデルはそのロジックにとらわれない必要があります。

于 2013-11-09T15:41:32.520 に答える