Django 查询集不返回不同的值

Ale*_*exW 1 sqlite django django-queryset

我有一个查询,由于某种原因,即使我指定了不同的值,也不会返回不同的值,我认为这可能是因为唯一,所以我删除了它,但列表仍然相同

circuit_providers =  CircuitInfoData.objects.only('provider').values('provider').distinct()
Run Code Online (Sandbox Code Playgroud)

我只想要一份独特的提供商列表

模型.py

from __future__ import unicode_literals
from django.db import models
import string
import random
import time
import os

# Create your models here.
from service.models import ServiceContacts

def site_photos_path(instance, filename):
    file ,extension = os.path.splitext(filename)
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    chars=string.ascii_uppercase + string.digits
    random_string = ''.join(random.choice(chars) for _ in range(6))
    filename = '%s-%s%s' % (random_string,time.strftime("%d-%m-%H-%M-%S"),extension)
    return 'site_photos/{0}'.format(filename)

def service_upload_path(instance, filename):
    file ,extension = os.path.splitext(filename)
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    chars=string.ascii_uppercase + string.digits
    random_string = ''.join(random.choice(chars) for _ in range(6))
    filename = '%s-%s%s' % (random_string,time.strftime("%d-%m-%H-%M-%S"),extension)
    return 'service_files/{0}'.format(filename)    

def site_files_path(instance, filename):
    file ,extension = os.path.splitext(filename)
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    chars=string.ascii_uppercase + string.digits
    random_string = ''.join(random.choice(chars) for _ in range(6))
    filename = '%s-%s%s' % (random_string,time.strftime("%d-%m-%H-%M-%S"),extension)
    return 'site_files/{0}'.format(filename)   

provider_choices = (
        ('KCOM','KCOM'),
        ('BT','BT'),
        ('EE','EE'),
        ('THREE','THREE'),
    ) 
circuit_choices = (
        ('DSL','DSL'),
        ('VDSL','VDSL'),
        ('MPLS','MPLS'),
        ('4G','4G'),
        ('Internet Leased Line','Internet Leased Line'),
    )     

subnet_mask_choices = (
        ('/16','/16'),
        ('/24','/24'),
        ('/25','/25'),
        ('/26','/26'),
        ('/27','/27'),
        ('/28','/28'),
        ('/29','/29'),
        ('/30','/30'),
        ('/31','/31'),
    )       

class ShowroomConfigData(models.Model):
    location = models.CharField(max_length=50)
    subnet = models.GenericIPAddressField(protocol='IPv4')
    r1_loopback_ip = models.GenericIPAddressField(protocol='IPv4',verbose_name="R1 Loopback IP")
    r2_loopback_ip = models.GenericIPAddressField(protocol='IPv4',verbose_name="R2 Loopback IP")  
    opening_date = models.DateField(verbose_name="Showroom opening date")
    last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh")
    is_showroom = models.BooleanField(default=True,verbose_name="Is this site a showroom?")

    class Meta:
            verbose_name = "Showroom Data"
            verbose_name_plural = "Showroom Data"  
            ordering = ('location',)

    def __unicode__(self):
        return self.location   


class MajorSiteInfoData(models.Model):
    location = models.CharField(max_length=200)
    major_subnet = models.GenericIPAddressField(protocol='IPv4',verbose_name="Major Site Subnet")
    routed_subnet = models.GenericIPAddressField(protocol='IPv4',verbose_name="Routed Link Subnet")
    bgp_as = models.CharField(max_length=6,verbose_name="BGP AS Number")

    class Meta:
            verbose_name = "Major Site Data"
            verbose_name_plural = "Major Site Data"      

    def __unicode__(self):
        return self.location

class CircuitInfoData(models.Model):    
    showroom_config_data = models.ForeignKey(ShowroomConfigData,verbose_name="Install Showroom")
    major_site_info = models.ForeignKey(MajorSiteInfoData,verbose_name="Install Site") 
    circuit_type = models.CharField(max_length=100,choices=circuit_choices)    
    circuit_speed = models.IntegerField(blank=True)
    circuit_bearer = models.IntegerField(blank=True)
    provider = models.CharField(max_length=200,choices=provider_choices)
    ref_no = models.CharField(max_length=200,verbose_name="Reference No")

    class Meta:
        verbose_name = "Circuit Data"
        verbose_name_plural = "Circuit Data"
        ordering = ('showroom_config_data__location','circuit_speed')

    def __unicode__(self):
        return '%s | %s | %s | %s | %s' % (self.showroom_config_data.location,self.major_site_info.location, self.provider, self.service_type, self.ref_no)
Run Code Online (Sandbox Code Playgroud)

下面的 shell 的结果

[root@network-tools infternal]# python manage.py shell
Python 2.7.5 (default, Nov 20 2015, 02:00:19)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from networks.models import CircuitInfoData
>>> d = CircuitInfoData.objects.values('provider').distinct()
>>> for item in d:
...  print item
...
{'provider': u'BT'}
{'provider': u'BT'}
{'provider': u'KCOM'}
{'provider': u'BT'}
{'provider': u'BT'}
{'provider': u'KCOM'}
.....
>>> print d.query
SELECT DISTINCT "networks_circuitinfodata"."provider", "networks_showroomconfigdata"."location", "networks_circuitinfodata"."circuit_speed" FROM "networks_circuitinfodata" INNER JOIN "networks_showroomconfigdata" ON ("networks_circuitinfodata"."showroom_config_data_id" = "networks_showroomconfigdata"."id") ORDER BY "networks_showroomconfigdata"."location" ASC, "networks_circuitinfodata"."circuit_speed" ASC
>>>
Run Code Online (Sandbox Code Playgroud)

我注意到的一件事是,当我如上所述在 shell 中打印项目时

#### with def __unicode__(self): #####

>>> from networks.models import CircuitInfoData
>>> d = CircuitInfoData.objects.only('provider').distinct()
>>> for i in d:
...  print i
...
Location1 | Showroom | BT | DSL | N/A
Location2 | Showroom | BT | MPLS | XXXX
Location2 | Showroom | KCOM | MPLS | XXXX
Location3 | Showroom | BT | MPLS | XXXX
Location3 | Showroom | BT | DSL | N/A
Location4 | Showroom | KCOM | MPLS | XXXXX
...

#### with out def __unicode__(self): #####

>>> from networks.models import CircuitInfoData
>>> d = CircuitInfoData.objects.only('provider').distinct()
>>> for i in d:
...  print i
...
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
CircuitInfoData_Deferred_circuit_bearer_circuit_cfb3d62ef325a6acfc8ddcb43c8ae1c6 object
...

#### with either ####

>>> for i in d:
...  print i.provider
...
BT
BT
KCOM
BT
BT
KCOM
...
Run Code Online (Sandbox Code Playgroud)

e4c*_*4c5 5

不同的文档说

\n
\n

返回在其 SQL 查询中使用 SELECT DISTINCT 的新 QuerySet。\n这会消除查询结果中的重复行。

\n

默认情况下,查询集不会消除重复行。实际上,\n这很少会成为问题,因为\nBlog.objects.all() 等简单查询\n\n\xe2\x80\x99t 可能会引入重复结果行的可能性。

\n
\n

不同为您提供不同的行,但您只查看记录中的一个字段,并且该字段中的项目可以重复,除非它具有唯一约束。在这种情况下,你不需要。

\n

如果你碰巧使用 postgresql 你可以这样做

\n
CircuitInfoData.objects.distinct(\'provider\')\n
Run Code Online (Sandbox Code Playgroud)\n

实现您的目标。

\n

更新: \n既然您在评论中提到您使用 sqlite,请使用此解决方案。

\n
CircuitInfoData.objects.values(\'provider\').distinct()\n
Run Code Online (Sandbox Code Playgroud)\n

这将起作用,因为现在每一行只有一列。结果查询将类似于

\n
SELECT DISTINCT "someapp_circuitinfodata"."name" FROM "someapp_circuitinfodata"\n
Run Code Online (Sandbox Code Playgroud)\n

更新2:

\n

请注意,您已覆盖该__unicode__函数。

\n
def __unicode__(self):\n     return \'%s | %s | %s | %s | %s\' % \n       (self.showroom_config_data.location,self.major_site_info.location, \n       self.provider, self.service_type, self.ref_no)\n
Run Code Online (Sandbox Code Playgroud)\n

您指的是相关模型中的字段。这将是非常昂贵的(除非你使用select_related)。另请注意,如果您迭代查询集并使用 print 进行调试,则会产生误导性的结果(因为您看到的是 的输出__unicode__,这是一个相当复杂的函数)

\n