自定义Django信号不更新我的模型

2024-09-27 00:14:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现一个自定义信号,但我从来没有这样做过,所以我似乎已经搞砸了这个

以下是models.py中的代码:

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save, post_delete
from django.dispatch import Signal
from django.db.models import Max,Count
from django.apps import apps

# Create your models here.
class Player(models.Model):
    player_name = models.CharField(max_length=150)
    current_level_no = models.IntegerField(null=True)
    no_of_moves = models.IntegerField(null=True)    

    class Meta:
        verbose_name_plural = 'Players'

    def __str__(self):
        return self.player_name

class PlayerStats(models.Model):
    player_name = models.ForeignKey(to=Player, on_delete=models.CASCADE)
    level_no = models.IntegerField(null=True)
    moves = models.IntegerField(null=True)

    class Meta:
        verbose_name_plural = 'Players Stats'

# It works!
TotalLevels = 25
MaxCurrentLevel = PlayerStats.objects.aggregate(max_levels=Max('level_no'))['max_levels']
PlayerCount = Player.objects.aggregate(count_players=Count('player_name', distinct=True))['count_players']


def create_player(sender, instance, created, **kwargs):
    if created:
        new_username=instance.username
        Player.objects.create(player_name=new_username, current_level_no=None, no_of_moves=None)

def delete_player(sender, instance, **kwargs):
    deleted_username=instance.username
    Player.objects.filter(player_name=deleted_username).delete()

def create_player_stat(sender, instance, **kwargs):
    for x in range(1, TotalLevels+1):
        PlayerStats.objects.create(player_name=instance, level_no=x, moves=None)

UpdateLevelsSignal = Signal(providing_args=['Update'])
if MaxCurrentLevel != TotalLevels and PlayerCount != 0:
    UpdateLevelsSignal.send(UpdateLevelsSignal,Update=True)

def UpdateLevels(sender, Update,**kwargs):
    if Update:
        if MaxCurrentLevel < TotalLevels:
            for x in Player.objects.all().values_list('player_name', flat=True):
                instance = Player.objects.get(player_name=x)
                for y in range(TotalLevels-MaxCurrentLevel, TotalLevels+1):
                    PlayerStats.objects.create(player_name=instance, level_no=y, moves=None)
        else:
            for x in Player.objects.all().values_list('player_name', flat=True):
                instance = Player.objects.get(player_name=x)
                for y in range(MaxCurrentLevel-TotalLevels, MaxCurrentLevel+1):
                    PlayerStats.objects.filter(player_name=instance, level_no=y, moves=None).delete()

post_save.connect(create_player, sender=User)
post_delete.connect(delete_player, sender=User)

post_save.connect(create_player_stat, sender=Player)

UpdateLevelsSignal.connect(UpdateLevels, sender=UpdateLevelsSignal)

基本上是一个信号,根据一定的条件创建或删除一些模型对象,没什么太花哨的。但是,当我检查模型对象时,触发条件时没有发生任何变化

如果有人能指出我在这里做错了什么或提出解决方案,那将是有益的

一如既往,我非常感谢你的回答


Tags: djangoinstancenonamefromtrueobjectsmodels
1条回答
网友
1楼 · 发布于 2024-09-27 00:14:34

这并不能解决你的问题,但我不想在评论中提及。您应该将信号和接收器移动到它们自己的文件中的原因是限制模型文件中有多少业务逻辑。此外,它使它在处理多个应用程序时更具可扩展性

project/
  app1/
     apps.py
     models.py
     signals.py
     receivers.py
  app2/
     apps.py
     models.py
     receivers.py

在上述每个应用程序中,apps.py文件类似于:

class App1Config(AppConfig):

    def ready(self):
        # This makes Django load up the register the connected receivers.
        from project.app1 import receivers, signals

之所以要将接收者移动到他们自己的文件中,部分原因是要触发一个函数,该函数只影响app2中的模型/对象,但由app1中模型上的某个事件触发。例如:

#project/app2/receivers.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from project.app1.models import Foo
from .models import Bar

@receiver(post_save, sender=Foo)
def create_bar_for_foo(instance, created, *, raw=False, **kwargs):
    if created:
        Bar.objects.create(foo=foo)

你可以在app2/models.py里做那个接收器,但它会觉得不合适。如果它是一个与基于模型的事件无关的自定义信号,那么它会感觉特别陌生

我希望Django文档试图解释如何组织信号和接收器,但是Django的两勺书在解释它方面做了大量的工作

相关问题 更多 >

    热门问题