2017-11-17 4 views
0

私はShopAddressの2つのモデルを持っています。Djangoのカスタムマネージャは、関連するモデルを使用して近くにフィルタリングします

ショップModel

class Shop(BaseModel): 
    name = models.CharField(
     max_length=100, 
     blank=True, 
     null=True 
    ) 
    address = models.ForeignKey(
     Address, 
     blank=True, 
     null=True, 
     on_delete=models.SET_NULL 
    ) 
    objects = LocationManager() 

住所Model

class Address(BaseModel): 
    latitude = models.DecimalField(
     max_digits=16, 
     decimal_places=14, 
     blank=True, 
     null=True 
    ) 
    longitude = models.DecimalField(
     max_digits=16, 
     decimal_places=14, 
     blank=True, 
     null=True 
    ) 
    status = models.NullBooleanField(null=True) 

私はショップモデル

class LocationManager(models.Manager): 
    def nearby(self, latitude, longitude, proximity): 
     """ 
     Return all object which distance to specified coordinates 
     is less than proximity given in kilometers 
     """ 
     # Great circle distance formula 
     # acos will not work in sqlite 
     gcd = """ 
      6371 * acos(
       cos(radians(%s)) * cos(radians(latitude)) 
       * cos(radians(longitude) - radians(%s)) + 
       sin(radians(%s)) * sin(radians(latitude)) 
      ) 
     """ 
     queryset = self.get_queryset().select_related(
      'address' 
     ).exclude(
      latitude=None 
     ) 
     .exclude(
      longitude=None 
     ) 
     .annotate(
      distance=RawSQL(
       gcd, 
       (
        latitude, 
        longitude, 
        latitude 
       ) 
      ) 
     ).filter(
      distance__lt=proximity 
     ).order_by('distance') 

     return queryset 

用のカスタムマネージャを作成したが、今私は、カスタムマネージャを使用して近くのお店を見つけたいです:

Shop.objects.nearby(13.244334,72.329832,20) 

しかし、私はこのエラーを取得しています:

Cannot resolve keyword 'latitude' into field. Choices are: address, address_id, name 

にはどうすれば近くのお店を見つけることがlatitudeで私のクエリセットをフィルタリングする使用することができますか?

答えて

3

AddressモデルではShopモデルを照会しています。 Shopモデルには、エラーによって示されているように、latitudeという名前のフィールドがありません。

あなたShopモデルがフィールドaddressしてAddressモデルにリンクされているので、あなたがでShopをフィルタリングするために、リンクされたオブジェクトAddressdocumentation

の属性によって、あなたのShop Sをフィルタリングするために、フィールドのルックアップを使用する必要がありますAddress属性は、あなたが(すなわちlatitudeフィールドのために)行うことができます。また

Shop.objects.filter(address__latitude=<your_lookup_here>) 

、あなたの2つのexcludeメソッドは次のようにrewrittedすることができた(USIを

Shop.objects.exclude(
    Q(address__latitude__isnull=True) 
    | Q(address__longitude__isnull=True) 
) 

私はクエリセットAPIに関する上記のリンクのドキュメントを読むためにあなたのアドバイス:Qオブジェクト)をngの。

+0

on select_related()djangoは内部的に関連テーブルと外部結合を行います。私はアドレステーブルから緯度と経度を使いたい。 – user2858738

+0

'select_related'はjoin節を追加しますが、関係を使って関連するインスタンスの属性を問い合わせる必要があります。私はこれを読むことを強くお勧めします:https://docs.djangoproject.com/en/1.11/topics/db/queries/#lookups-that-span-relationships –

関連する問題