我有m-2-m相对值和i want to update the rel B after any rel A is added via the admin page.

Here the details:

我有2个型号,Match(rel A)和Player(rel B).我想更新Player.matches_played,每次在Match.team1或Match.team2中添加与该球员的新比赛.

How can i achieve this???

模型

class Match(models.Model):
    data=models.DateField(auto_now_add=False,auto_now=False)
    team1=models.ManyToManyField('players.Player',related_name='team_1')
    team2=models.ManyToManyField('players.Player',related_name='team_2')
    score_team1=models.IntegerField(validators=[MinValueValidator(0)])
    score_team2=models.IntegerField(validators=[MinValueValidator(0)])

class Player(models.Model):
    matches_played= models.IntegerField(validators=[MinValueValidator(0)], default=0)

I tried signals,但在post_save signal {instance.team1}或instance.team1.all()中返回an empty QuerySet,我认为这是正确的,因为M2M rel稍后会保存. 然后我try 了m2m_changed,但信号为is not fired,并通过管理页面保存.我错过了什么?


@receiver(post_save, sender=Match, dispatch_uid="update_player_game_count")
def update_player_games(sender, instance, created, **kwargs):
    print(f'created {instance.pk}')
    print(f'created {instance.team1}')
    print(f'created {instance.team2}')
    print(f'created {instance.score_team1}')
    print(instance.team1.all())
@receiver(m2m_changed, sender=Match, dispatch_uid="update_player_game_count")
def update_player_game(sender, instance, created, action, **kwargs):
    print(action)
    if action == 'post_add':
        print(action)

非常感谢您的帮助

我想到的是an alternative是通过Player中的属性检索数据,例如这样,but我认为,from a performance point of view,最好在每次添加匹配时更新行,然后在每次请求玩家时计算匹配数

例如

@property
def matches_played(self):
    return Match.objects.filter(team1__nome=self.nome).count()+Match.objects.filter(team2__nome=self.nome).count()

推荐答案

m2m_change signal [Django-doc]的发件人不是Match,而是Match.team1.through和/或Match.team2.through,所以:

@receiver(
    m2m_changed,
    sender=Match.team1.through,
    dispatch_uid='update_player_game_count1',
)
@receiver(
    m2m_changed,
    sender=Match.team2.through,
    dispatch_uid='update_player_game_count2',
)
def update_player_game(sender, instance, created, action, **kwargs):
    print(action)
    if action == 'post_add':
        print(action)

话虽如此,将匹配的次数存储为模型中的一个字段并没有太大意义.我们可以在需要时通过以下方式确定它:

from django.db.models import Count

Player.objects.annotate(
    total_matches=Count('team1', distinct=True) + Count('team2', distinct=True)
)

此外,我认为使用两个ManyToManyField本身并不是这里最好的建模.您可能想使用单个ManyToManyFieldthrough=… model [Django-doc]来确定玩家是为第一队还是第二队效力.

Django相关问答推荐

如何在Django上创建ManyToMany管理面板?

如何将Django项目连接到容器化的PostgreSQL数据库?

社工/社工简戈

更改Django的创建时间字段

在 Django 中重组多对多字段

无法创建超级用户,因为 Django 中的一列(外键)不能为空

Django 模型:如何查找自动生成的字段列表

防止 Django 从表单集中保存特定表单

是否可以在 Django 中重命名应用程序的组名?

直接在模型类上使用 Django 管理器与静态方法

Django:get_or_create 使用 together_unique 引发重复条目

Django populate() 不可重入

Django - 如何从模型中 Select 特定列?

django npm 和 node 包架构

Django:创建索引:非唯一,多列

这是验证 Django 模型字段的方法吗?

在 Django 中测试different layers的最佳实践是什么?

Django urls 直接到 html 模板

具有 2 种语言的 Django 站点

如何更改模型标签并给它一个自定义名称