2017-01-22 109 views
0

我有一个模型,该模型从一个表中一个数据库中检索数据,以及检索其他两个表数据另外两个模型(StreetsCities)。所有这些信息都需要从LandVehicle模型中获取。我在计算如何从其他表格中检索数据到LandVehicle模型中的属性时遇到了一些问题。下面是阶级结构我的工作:模型属性返回空

class Vehicle(models.Model): 

    name = models.CharField(max_length=500) 
    lat = models.DecimalField(max_digits=15,decimal_places=6) 
    lon = models.DecimalField(max_digits=15,decimal_places=6) 
    radius = Decimal(.06) 

    @abstractproperty 
    def streets(self): 
     pass 

    @abstractproperty 
    def cities(self): 
     pass 

    @cached_property 
    def nearby_vehicles(self): 
     return Vehicle.objects.filter(lat__range=[self.lat - 2, self.lat + 2], lon__range=[self.lon - 2, self.lon + 2]) 

    # Meta 
    class Meta: 
     abstract = True 


class LandVehicle(Vehicle): 

    @property 
    def streets(self): 
     name_substr = self.name 
     if " " in name_substr: 
      name_substr = name_substr[:name_substr.index(" ")] 

     return LandVehicle.objects.filter(Q(streets__name__contains=self.name) | 
              Q(streets__name__contains=name_substr) | 
              (Q(streets__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(streets__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

    @property 
    def cities(self): 
     name_substr = self.name 
     if " " in name_substr: 
      name_substr = name_substr[:name_substr.index(" ")] 

     return LandVehicle.objects.filter(Q(cities__name__contains=self.name) | 
              Q(cities__name__contains=airport_name_substr) | 
              (Q(cities__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(cities__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

    # Meta 
    class Meta: 
     db_table = 'landvehicles' 

class Streets(models.Model): 
    # Meta 
    class Meta: 
     db_table = 'streets' 

class Cities(models.Model): 
    # Meta 
    class Meta: 
     db_table = 'cities' 

我不一定得到它的成立,现在的方式错误,但在访问视图中的数据,如vehicle.streets,如果vehicleLandVehicle的实例只是一个空变量。

我明白,我需要解析的数据,一旦我能找回它,但现在它似乎并没有被检索任何东西(不能为它打印出来东西要么)。

编辑/更新:

通过添加self参数,每个属性(上述改变),我收到一个错误:

Cannot resolve keyword 'streets' into field. Choices are: id, lat, lon, name 

至少我得到了一些错误,现在,但我仍然不确定如何访问属性。

+0

通过空的变量,你的意思是'None'?尝试在那里放置一些'print'来查看代码是否被执行。此外,代码看起来很奇怪 - 你的方法在任何地方都缺少“self”(作为第一个参数)。 – yedpodtrzitko

+0

@yedpodtrzitko如果我尝试在属性中打印文本到控制台(例如在“streets()'属性中打印”Test“),它会起作用,所以它似乎被执行,但如果我在属性到一个变量和打印,没有什么打印到控制台。我已将缺少的'self'参数添加到每个属性中,并更新了有关该错误的更多信息。 – swiftsly

回答

1

当然啊,我现在看到了。错误表示它 - 您试图在filter()表达式中使用streets作为列,但它不是任何地方定义的db列。您需要将该列定义为Field类(+为其进行迁移)的祖先,然后可以在db查询中使用它。

你也必须重命名属性streets所以别的东西,如果数据库列将被调用的方式。

编辑下面的注释:你可以兼得的事情,但他们不能明显地具有相同的名称。因此,例如这样:

class Vehicle(models.Model): 

    # ... 
    # a singular name 
    street = models.CharField(max_length=128) 

    @property 
    def streets(self): # plural 
     # you can use this instead of the 3 lines with `if` you have now 
     name_substr = self.name.split()[0] 

     #since the column is singular `street`, is needs to be singular in the query below too. 
     return LandVehicle.objects.filter(Q(street__name__contains=self.name) | 
              Q(street__name__contains=name_substr) | 
              (Q(street__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(street__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

至于你的问题是什么呢LandVehicle.objects.filter()做的是,它是写一个SQL查询,而无需实际编写原始SQL查询的便捷方式。然后Django将它转换为查询。因此,当您想通过街道名称筛选数据库记录时,必须在数据库中包含street列,以便数据库可以在数据上进行比较。

例如该位:Q(street__name__contains='foobar')被转换为SQL查询等select * from vehicle where street LIKE '%foobar%'。所以很显然,预计列street需要在那里。不仅用于过滤数据,还需要存储这些数据。

如果你不理解Django的ORM是如何工作的,请阅读文档的这一部分:https://docs.djangoproject.com/en/1.10/topics/db/queries/

+0

它开始有意义,但是我必须完全搞不清楚LandVehicle.objects.filter(Q(cities__name__contains = self.name))在做什么。正如你指出的那样,街道不是一个专栏,但最终目标是对于“街道”来说,表格列(包含所有列数据)可以解析为一个元组,所以为了澄清,我应该创建一个自定义字段,它将充当所有行数据? – swiftsly