【问题标题】:Geo Django Subclassing QuerysetGeo Django 子类化查询集
【发布时间】:2011-10-25 13:05:52
【问题描述】:

我正在使用 GeoDjango 搜索一堆不同类型的位置。例如,House 和 Appartment 模型都是 Location 的子类。

使用下面的子类化查询集,我可以执行诸如 Location.objects.all() 之类的操作并将其返回给我[<House: myhouse>, <House: yourhouse>, <Appartment: myappartment>],这是我的愿望。

但是,我还想确定到每个位置的距离。通常,如果没有子类化查询集,图表 2 中的代码会为我返回从给定点到每个位置的距离......[ (<Location: Location object>, Distance(m=866.092847284))]

但是,如果我尝试使用子类化查询集查找距离,则会收到如下错误:

AttributeError: 'House' 对象没有属性 'distance'

你知道我怎样才能保留返回子类对象查询集的能力,同时在子类对象上具有可用的距离属性吗?非常感谢任何建议。

图1:

class SubclassingQuerySet(models.query.GeoQuerySet):
    def __getitem__(self, k):
        result = super(SubclassingQuerySet, self).__getitem__(k)
        if isinstance(result, models.Model) :
            return result.as_leaf_class()
        else :
            return result
    def __iter__(self):
        for item in super(SubclassingQuerySet, self).__iter__():
            yield item.as_leaf_class()

class LocationManager(models.GeoManager):
    def get_query_set(self):
        return SubclassingQuerySet(self.model)

class Location(models.Model):
    content_type = models.ForeignKey(ContentType,editable=False,null=True)
    objects = LocationManager()

class House(Location):
    address = models.CharField(max_length=255, blank=True, null=True)
    objects = LocationManager()

class Appartment(Location):
    address = models.CharField(max_length=255, blank=True, null=True)
    unit = models.CharField(max_length=255, blank=True, null=True)
    objects = LocationManager()

图2:

from django.contrib.gis.measure import D 
from django.contrib.gis.geos import fromstr
ref_pnt =  fromstr('POINT(-87.627778 41.881944)')

location_objs = Location.objects.filter(
        point__distance_lte=(ref_pnt, D(m=1000) 
              )).distance(ref_pnt).order_by('distance')
[ (l, l.distance) for l in location_objs.distance(ref_pnt) ]   # <--- errors out here

【问题讨论】:

    标签: django django-models django-queryset geo subclassing


    【解决方案1】:

    我正忙着解决这个问题。这个怎么样:

    class QuerySetManager(models.GeoManager):
        '''
        Generates a new QuerySet method and extends the original query object manager in the Model
        '''
        def get_query_set(self):
            return super(QuerySetManager, self).get_query_set()
    

    其余的可以从这个DjangoSnippet开始。

    【讨论】:

      【解决方案2】:

      您必须在所有子类中重新分配经理。

      来自 Django 文档:

      在非抽象基类上定义的管理器不会被子类继承。如果您想重用非抽象基础中的管理器,请在子类上显式地重新声明它。这些类型的管理器可能相当特定于它们所定义的类,因此继承它们通常会导致意想不到的结果(特别是就默认管理器而言)。因此,它们不会传递给子类。

      https://docs.djangoproject.com/en/dev/topics/db/managers/#custom-managers-and-model-inheritance

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-18
        • 2011-02-02
        • 1970-01-01
        • 2015-08-05
        • 2018-12-20
        • 2021-12-10
        • 2019-07-21
        • 1970-01-01
        相关资源
        最近更新 更多