Django查询集在尝试获取具有多个外键的集合时给出attribute_error

时间:2016-04-26 15:29:01

标签: django django-models django-views

首先,这是我的模特。每个字符串有1到3个表演者,每个表演者链接到几个字符串:

class Performer(models.Model) :
    name = models.CharField(max_length=60, default="None")
    description = models.TextField(null=True, default=None)

class String(models.Model) :
    index = models.IntegerField(null=True, default=None)
    step = models.IntegerField(null=True, default=None)
    process = models.CharField(max_length=100,null=True, default=None)
    description = models.TextField(null=True, default=None)
    performer = models.ForeignKey(Performer, related_name='performer',   on_delete=models.CASCADE, null=True, default=None)
    performer2 = models.ForeignKey(Performer, related_name='performer2', on_delete=models.CASCADE, null=True, default=None)
    performer3 = models.ForeignKey(Performer, related_name='performer3', on_delete=models.CASCADE, null=True, default=None)

我需要制作与单个表演者相关的所有弦乐的集合。但是,如果我尝试使用string_set获取所有字符串,其中任何Performer外键都指向该字符串,如下所示:

p = Performer.objects.get(name="smth")# so p is a performer object
s = p.string_set.all()

我遇到了这个问题:

 AttributeError: 'Performer' object has no attribute 'string_set'

此外,我还尝试使用相关名称的过滤器,但这给了我同样的错误。有没有办法根据所有指向相同类型的外键字段之一获取_set?

1 个答案:

答案 0 :(得分:3)

通过在related_nameperformerperformer2关系中提供performer3,您可以覆盖related_name类的默认Performer链接是string_set。现在要获得每个关系的String,你必须得到如下所示:

p = Performer.objects.get(name="smth")# so p is a performer object
p.performer.all() #first one which would actually be a queryset
p.performer1.all() #second one which would actually be a queryset
p.performer2.all() #third one which would actually be a queryset

只有当您有一个String和一个Performer相互关联时才会出现这种情况,但您应该记住p.performer1.all()之类的查询实际上可以返回2个或更多String {{ 1}}与此Performer有关系的对象。这会使事情变得更加麻烦。

请记住,ForeignKey会创建一对多关系...

您提供的模型结构会出现您想要的过滤问题。更好的模型设计如下所示:

class Performer(models.Model) :
    name = models.CharField(max_length=60, default="None")
    description = models.TextField(null=True, default=None)
    strings = models.ManyToManyField(String, related_name='performers')

class String(models.Model) :
    index = models.IntegerField(null=True, default=None)
    step = models.IntegerField(null=True, default=None)
    process = models.CharField(max_length=100,null=True, default=None)
    description = models.TextField(null=True, default=None)

此设计允许您执行:

p = Performer.objects.get(name="smth")# so p is a performer object
s = p.strings.all()