问题描述
我有两个模型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
时,也会使用AlternateLabel
信号创建一个post_save
。
@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,**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()
,我知道这是由于以下事实造成的:该方法试图使用新的{{1 }}实例AlternateLable
不存在。我一直在努力寻找一种方法来实现这一目标。我将不胜感激任何建议或指导。
解决方法
好吧,您可以通过主键访问实例的备用项。
只需使用:
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)
此解决方案完全可以正常工作,并且据我所知没有任何缺点。