Django信号:与从同一类继承的模型冲突

Django信号:与从同一类继承的模型冲突,django,orm,signals,fixtures,Django,Orm,Signals,Fixtures,在将信号应用于新模型时,我遇到了一个奇怪的行为,我不确定是什么错了,但这似乎与我使用抽象类的事实有关 模型(简化) 基本上,我有文章,照片(继承自帖子) 以及它们各自的类别 class Category(models.Model): class Meta: abstract = True parent = models.ForeignKey('self', null=True, blank=True, related_name='nested_categor

在将信号应用于新模型时,我遇到了一个奇怪的行为,我不确定是什么错了,但这似乎与我使用抽象类的事实有关

模型(简化) 基本上,我有文章照片(继承自帖子

以及它们各自的类别

class Category(models.Model):
    class Meta: 
        abstract = True 

    parent = models.ForeignKey('self', null=True, blank=True, related_name='nested_category', on_delete=models.SET_NULL)
    name   = models.CharField(max_length=50)
    count  = models.PositiveSmallIntegerField(default=0, editable=False)
    
class Article_category(Category):

    @classmethod
    def load(cls):
        cache.set('{}'.format(cls.__name__), cls.objects.all()) 

class Photo_category(Category):

    @classmethod
    def load(cls):
        cache.set('{}'.format(cls.__name__), cls.objects.all())
信号 一种正向递增计数器。每次创建文章/照片时,都会更新相应的类别计数,并将整个模型保存在缓存中(用于模板制作)

问题 您在上面看到的内容对于
@receiver(post\u save,sender=Photo)
来说就像一个符咒,但是当我添加
@receiver(post\u save,sender=Article)
时,fixture的DB初始化失败,我只得到清空的表(mariaDB)。这是唯一一条从失败走向成功的路线,我不明白为什么。由于count是在抽象类中定义的,我想知道它是否与之有关,因为我对将类似逻辑应用于类别没有任何问题:

# this works perfectly
@receiver(post_save, sender=Photo_category)
@receiver(post_delete, sender=Photo_category)
@receiver(post_save, sender=Article_category)
@receiver(post_delete, sender=Article_category)
def refresh_cached_category(sender, instance, using, **kwargs):
    cache.set('{}'.format(type(instance).__name__), type(instance).objects.all())
谢谢你的启发

完全回溯
回溯(最近一次呼叫最后一次):
文件“manage.py”,第21行,在
main()
文件“manage.py”,第17行,主
从命令行(sys.argv)执行命令
文件“/usr/local/lib/python3.7/site packages/django/core/management/__init__.py”,第381行,从命令行执行
utility.execute()
文件“/usr/local/lib/python3.7/site packages/django/core/management/__init__.py”,执行中第375行
self.fetch_命令(子命令)。从_argv(self.argv)运行_
文件“/usr/local/lib/python3.7/site packages/django/core/management/base.py”,第323行,在运行中,从
self.execute(*args,**cmd_选项)
文件“/usr/local/lib/python3.7/site packages/django/core/management/base.py”,执行中第364行
输出=self.handle(*args,**选项)
文件“/usr/local/lib/python3.7/site packages/django/core/management/commands/loaddata.py”,第72行,在handle中
self.loaddata(夹具标签)
loaddata中的文件“/usr/local/lib/python3.7/site packages/django/core/management/commands/loaddata.py”,第114行
自加载标签(夹具标签)
文件“/usr/local/lib/python3.7/site packages/django/core/management/commands/loaddata.py”,第181行,在load_标签中
对象保存(使用=自使用)
保存中的文件“/usr/local/lib/python3.7/site packages/django/core/serializers/base.py”,第223行
models.Model.save_base(self.object,using=using,raw=True,**kwargs)
save_base中的文件“/usr/local/lib/python3.7/site packages/django/db/models/base.py”,第790行
更新\字段=更新\字段,原始=原始,使用=使用,
文件“/usr/local/lib/python3.7/site packages/django/dispatch/dispatcher.py”,第175行,在send中
对于自身中的接收者。\u现场\u接收者(发送者)
文件“/usr/local/lib/python3.7/site packages/django/dispatch/dispatcher.py”,第175行,在
对于自身中的接收者。\u现场\u接收者(发送者)
文件“/usr/src/cms/website/observators.py”,第26行,将一个添加到计数中
cat=type(instance.category).objects.get(name=instance.category)
文件“/usr/local/lib/python3.7/site packages/django/db/models/manager.py”,第82行,在manager\u方法中
返回getattr(self.get_queryset(),name)(*args,**kwargs)
get中第408行的文件“/usr/local/lib/python3.7/site packages/django/db/models/query.py”
self.model.\u meta.object\u name
website.models.DoesNotExist:安装夹具“/usr/src/cms/./test/data\u dev.yaml”时出现问题:不存在项目类别匹配查询。

您不能在查询中筛选
name=instance.category
,因为这不是
str
。您需要在
name=instance.category.name
上进行筛选,但首先还需要确保
instance.category
不是
None
(因为它可以)

我不明白的是,为什么您首先执行一个查询,只是为了获取相同的对象:
instance.category
articleContegory.objects.get(name=instance.category.name)
假设名称是唯一的,除非您对数据库进行额外的查询

此外,如果您有两个类别具有相同的
名称
(您在模型中不排除这两个类别),则查询将引发异常。因此,您的代码应该是:

def add_one_to_count(sender, instance, **kwargs):
    if instance.category:
        instance.category.count = F('count')+1
        instance.category.save()
        cache.set('{}_category'.format(sender.__name__), type(instance.category).objects.all())

你说得对,我是个很圆滑的人。你的答案有效。我想我所经历的与对类似模型的额外查询有关
# this works perfectly
@receiver(post_save, sender=Photo_category)
@receiver(post_delete, sender=Photo_category)
@receiver(post_save, sender=Article_category)
@receiver(post_delete, sender=Article_category)
def refresh_cached_category(sender, instance, using, **kwargs):
    cache.set('{}'.format(type(instance).__name__), type(instance).objects.all())
 Traceback (most recent call last):
   File "manage.py", line 21, in <module>
     main()
   File "manage.py", line 17, in main
     execute_from_command_line(sys.argv)
   File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
     utility.execute()
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 72, in handle
    self.loaddata(fixture_labels)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 114, in loaddata
    self.load_label(fixture_label)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 181, in load_label
    obj.save(using=self.using)
  File "/usr/local/lib/python3.7/site-packages/django/core/serializers/base.py", line 223, in save
    models.Model.save_base(self.object, using=using, raw=True, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 790, in save_base
    update_fields=update_fields, raw=raw, using=using,
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 175, in send
    for receiver in self._live_receivers(sender)
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 175, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/usr/src/cms/website/observers.py", line 26, in add_one_to_count
    cat = type(instance.category).objects.get(name=instance.category)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 408, in get
    self.model._meta.object_name
 website.models.DoesNotExist: Problem installing fixture '/usr/src/cms/../test/data_dev.yaml': Article_category matching query does not exist.
def add_one_to_count(sender, instance, **kwargs):
    if instance.category:
        instance.category.count = F('count')+1
        instance.category.save()
        cache.set('{}_category'.format(sender.__name__), type(instance.category).objects.all())