django.db.utils.OperationalError:(1052,"字段列表中的列'名称'含糊不清")

qg_*_*137 6 python django django-rest-framework

在我的Django项目中,当我查询数据时,我得到以下错误:

django.db.utils.OperationalError:(1052,"字段列表中的列'名称'含糊不清")

使用:

http://localhost:8000/api/physicalserver/list/?switchesport__bandwidth=10
Run Code Online (Sandbox Code Playgroud)

但如果我使用:

http://localhost:8000/api/physicalserver/list/?switches__id=xxx
Run Code Online (Sandbox Code Playgroud)

它会工作正常.

我的ListAPIView代码:

class PhysicalServerListAPIView(ListAPIView):
    serializer_class = PhysicalServerListSerializer
    permission_classes = [AllowAny]
    pagination_class = CommonPagination
    def get_queryset(self):
        query_params = self.request.query_params
        filters = {'{}__contains'.format(key): value
               for key, value in query_params.items()
               }
        qs = PhysicalServer.objects.filter(**filters)
        return qs.extra(select={'length':'Length(name)'}).order_by('length', 'name')
Run Code Online (Sandbox Code Playgroud)

我的序列化代码:

class PhysicalServerListSerializer(ModelSerializer):
    bandwidth = serializers.SerializerMethodField()

    class Meta:
        model = PhysicalServer
        fields = "__all__"
        depth = 1

    def get_bandwidth(self, obj):
        return obj.switchesport.bandwidth
Run Code Online (Sandbox Code Playgroud)

我的物理服务器模型:

class PhysicalServer(models.Model):         
    name = models.CharField(max_length=32)

    switches = models.ForeignKey(to=Switches, on_delete=models.DO_NOTHING)
    physical_server_model = models.ForeignKey(to=PhysicalServerModel, null=True, on_delete=models.DO_NOTHING)
    switchesport = models.OneToOneField(to=SwitchesPort, related_name="physical_server", on_delete=models.DO_NOTHING)
    ...
Run Code Online (Sandbox Code Playgroud)

编辑-1

我的开关型号:

class Switches(models.Model):

    name = models.CharField(max_length=32)
    desc = models.CharField(max_length=256)
    routerdevice = models.ForeignKey(to=RouterDevice, related_name="switches")

    gatewaydevice = models.ForeignKey(to=GatewayDevice,  related_name="switches")

    ctime = models.DateTimeField(auto_now_add=True)
    uptime = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-name']

    def __str__(self):
        return self.name
    def __unicode__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

和我的SwitchesPort模型代码:

class SwitchesPort(models.Model):

    name = models.CharField(max_length=32, unique=True)  
    desc = models.CharField(max_length=256, null=True, blank=True)
    switches = models.ForeignKey(to=Switches, on_delete=models.CASCADE,related_name="switchesports")
    vlanedipv4networkgroup = models.ForeignKey(
        to=VlanedIPv4NetworkGroup,  
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="switchesports")

    bandwidth = models.IntegerField(default=10)

    ctime = models.DateTimeField(auto_now_add=True)
    uptime = models.DateTimeField(auto_now=True)

    class Meta:

        ordering = ['name']

    def __str__(self):
        return self.name
    def __unicode__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

编辑-2

我的PhysicalServerModel,(应该是PhysicalServerType):

class PhysicalServerModel(models.Model):

    name = models.CharField(max_length=32)
    desc = models.CharField(max_length=256)

    cpu = models.CharField(null=True, blank=True, max_length=64)  
    ram = models.CharField(null=True, blank=True, max_length=64)  
    disk = models.CharField(null=True, blank=True, max_length=64)
    bandwidth = models.CharField(null=True, blank=True, max_length=64, default=10)
    price = models.DecimalField(null=True, blank=True, max_digits=8, decimal_places=2, max_length=16)

    ctime = models.DateTimeField(auto_now_add=True)
    uptime = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-id']

    def __str__(self):
        return self.name
    def __unicode__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

我的djangorestframework版本是3.7.1,django版本是1.11.1.我MySQL用作我的数据库.


编辑-3

到目前为止,我们发现了问题引起,因为name现场是模糊的,当我试图通过其进行排序lengthPhysicalServerListAPIView:

 return qs.extra(select={'length':'Length(name)'}).order_by('length', 'name')
Run Code Online (Sandbox Code Playgroud)

如果我qs直接退回,我不会有这个问题.

Sim*_*tte 2

这是众所周知的限制extra();它不会正确地别名引用。我建议您远离它,因为它只能作为最后的手段

相反,你应该使用annotate(Length)

annotate(
    length=Length('name'),
).order_by('length', 'name')
Run Code Online (Sandbox Code Playgroud)

https://docs.djangoproject.com/en/2.0/ref/models/database-functions/#length

或者,如果仅出于订购目的而进行注释Length,则只需将其传递给order_by

.order_by(Length('name'), name)
Run Code Online (Sandbox Code Playgroud)

https://docs.djangoproject.com/en/2.0/ref/models/querysets/#order-by