在 Django 中使用信号更新外键值
Update Foreignkey values using Signals in Django
我有两个模型 Label
和 AlternateLabel
。每个Label
可以关联多个AlternateLabel
,即它们之间存在ForeignKey关系。
class Label(models.Model):
name = models.CharField(max_length=55, blank=True, unique=True)
lower_range = models.FloatField(null=True, blank=True)
upper_range = models.FloatField(null=True, blank=True)
def __str__(self) -> str:
return f"{self.name}"
class AlternateLabel(models.Model):
name = models.CharField(max_length=55, blank=False)
label = models.ForeignKey(to=Label, on_delete=models.CASCADE)
class Meta:
unique_together =('name', 'label')
def __str__(self) -> str:
return f"{self.name}"
def __repr__(self) -> str:
return f"{self.name}"
创建 Label
时,也会使用 post_save
信号创建一个 AlternateLabel
。
@receiver(post_save, sender=Label)
def create_alternatelabel(sender, instance, created, **kwargs):
"""
when label is created an alternate label with name as label is also created
"""
if created:
AlternateLabel.objects.get_or_create(
name = instance.name,
label = instance
)
我还希望 AlternateLabel
在更新 Label
名称时更新 我试过这个
@receiver(post_save, sender=Label)
def save_alternatelabel(sender, instance, created, **kwargs):
"""
when label is saved an alternate label with name as label is also saved
"""
Label.alternatelabel_set.filter(
name=instance.name,
label = instance
).first().save()
但是,在更新 Label
时我收到错误 None type object has not method save()
,我知道这是因为此方法试图用新的 AlternateLable
找到 AlternateLable
=14=] 实例 name
不存在。几个小时以来,我一直在努力寻找一种方法来实现这一目标。我将不胜感激任何建议或指导。
嗯,您可以通过主键访问实例的备用项。
只需使用:
instance.alternatelabel_set.update(name=instance.name)
但是我建议在 Label
上创建方法并使用它们而不是信号
在观点和形式上。
例如:
class Label(models.Model):
name = models.CharField(max_length=55, blank=True, unique=True)
lower_range = models.FloatField(null=True, blank=True)
upper_range = models.FloatField(null=True, blank=True)
def __str__(self) -> str:
return f"{self.name}"
def set_name(self, name):
self.name = name
self.save()
self.alternatelabel_set.update(name=name)
由于 Label
可以关联多个 AlternateLabel
,我不能使用 .update
方法。因此我最终使用了 Django pre_save
信号。当 Label
更新时,它的 id
保持不变。因此,在将新的 Label
名称保存到数据库之前,使用 instance.id
从数据库中获取原始名称,使用它可以修复 AlternateLabel
。然后可以更新。
@receiver(pre_save, sender=Label)
def save_alternatelabel(sender, instance, **kwargs):
"""
when label name is updated, an alternate label name is also updated.
"""
try:# getting old label name
old_label_name = Label.objects.get(id=instance.id).name
# getting alternate_label with old label name | this will get the alternate label
# which has to be changed
alternate_label = AlternateLabel.objects.get(name = old_label_name)
# changing alternate_label.name to new name
alternate_label.name = instance.name
alternate_label.save()
except Exception as e:
print(e)
据我所知,此解决方案完全符合要求并且没有缺点。
我有两个模型 Label
和 AlternateLabel
。每个Label
可以关联多个AlternateLabel
,即它们之间存在ForeignKey关系。
class Label(models.Model):
name = models.CharField(max_length=55, blank=True, unique=True)
lower_range = models.FloatField(null=True, blank=True)
upper_range = models.FloatField(null=True, blank=True)
def __str__(self) -> str:
return f"{self.name}"
class AlternateLabel(models.Model):
name = models.CharField(max_length=55, blank=False)
label = models.ForeignKey(to=Label, on_delete=models.CASCADE)
class Meta:
unique_together =('name', 'label')
def __str__(self) -> str:
return f"{self.name}"
def __repr__(self) -> str:
return f"{self.name}"
创建 Label
时,也会使用 post_save
信号创建一个 AlternateLabel
。
@receiver(post_save, sender=Label)
def create_alternatelabel(sender, instance, created, **kwargs):
"""
when label is created an alternate label with name as label is also created
"""
if created:
AlternateLabel.objects.get_or_create(
name = instance.name,
label = instance
)
我还希望 AlternateLabel
在更新 Label
名称时更新 我试过这个
@receiver(post_save, sender=Label)
def save_alternatelabel(sender, instance, created, **kwargs):
"""
when label is saved an alternate label with name as label is also saved
"""
Label.alternatelabel_set.filter(
name=instance.name,
label = instance
).first().save()
但是,在更新 Label
时我收到错误 None type object has not method save()
,我知道这是因为此方法试图用新的 AlternateLable
找到 AlternateLable
=14=] 实例 name
不存在。几个小时以来,我一直在努力寻找一种方法来实现这一目标。我将不胜感激任何建议或指导。
嗯,您可以通过主键访问实例的备用项。
只需使用:
instance.alternatelabel_set.update(name=instance.name)
但是我建议在 Label
上创建方法并使用它们而不是信号
在观点和形式上。
例如:
class Label(models.Model):
name = models.CharField(max_length=55, blank=True, unique=True)
lower_range = models.FloatField(null=True, blank=True)
upper_range = models.FloatField(null=True, blank=True)
def __str__(self) -> str:
return f"{self.name}"
def set_name(self, name):
self.name = name
self.save()
self.alternatelabel_set.update(name=name)
由于 Label
可以关联多个 AlternateLabel
,我不能使用 .update
方法。因此我最终使用了 Django pre_save
信号。当 Label
更新时,它的 id
保持不变。因此,在将新的 Label
名称保存到数据库之前,使用 instance.id
从数据库中获取原始名称,使用它可以修复 AlternateLabel
。然后可以更新。
@receiver(pre_save, sender=Label)
def save_alternatelabel(sender, instance, **kwargs):
"""
when label name is updated, an alternate label name is also updated.
"""
try:# getting old label name
old_label_name = Label.objects.get(id=instance.id).name
# getting alternate_label with old label name | this will get the alternate label
# which has to be changed
alternate_label = AlternateLabel.objects.get(name = old_label_name)
# changing alternate_label.name to new name
alternate_label.name = instance.name
alternate_label.save()
except Exception as e:
print(e)
据我所知,此解决方案完全符合要求并且没有缺点。