笔记: 通用关系并不能解决这里的问题,因为它用于防止外键的代码重复非互连楷模。
通过 Generic Relation 我们可以为 Artist 和 Venue 创建一个通用模型 Bookings,但是创建的每个 Bookings 对象对它们来说都是不同的。此外,任何一个创建的Bookings对象将无法为另一个提供ForeignKey。
最直接的方式要实现这一点,是通过仅提供 artist 和 venue ForeignKey 中的一个来创建对象。然后在第一次保存后更新另一个。您可以通过要求 null 和 blank 在两个外部字段上都为真来实现这一点,然后在 clean 方法中减轻它。请注意,必须在重写的save 方法中手动调用 clean 方法,否则默认情况下不会调用它。这是Bookings模型:
class Bookings(models.Model):
requester = models.CharField(max_length=50)
artist = models.ForeignKey(Artist,null=True,blank=True,on_delete=models.CASCADE,related_name="artist_booking")
venue = models.ForeignKey(Venue,null=True,blank=True,on_delete=models.CASCADE,related_name="venue_booking")
def clean(self):
if self.artist and self.venue:
raise ValidationError('A booking cannot have both an artist and a venue.')
super(Bookings,self).clean()
def save(self,*args,**kwargs):
self.clean()
if not self.requester:
if self.artist:
self.requester="artist:"+self.artist.name
elif self.venue:
self.requester="venue:"+self.venue.name
super(Bookings,self).save(*args,**kwargs)
要创建它,
booking1=None
try:
# If you create booking with both artist and venue
# at the same time,it should throw `ValidationError`.
booking1=Bookings.objects.create(artist=artist)
except Exception as e:
print(e)
venue = Venue.objects.create(...)
booking1.venue = venue
booking1.save()
# Get event requester from booking object.
event_requester,name = booking1.requester.split(":")
if event_requster=="artist":
do_something(name)
elif event_requester=="venue":
do_something_else(name)