0

I have two models Shop and Address.

Shop 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()

Address 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)

I have created a custom Manager for Shop model

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

Now I want to find nearby shops using custom manager:

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

But i am getting this error:

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

How can I use filter my queryset by latitude to find nearby shop?

Clément Denoix
  • 1,504
  • 11
  • 18
user2858738
  • 520
  • 4
  • 15

1 Answers1

3

Your are querying your Shop model, not your Address model. Your Shop model don't have any field named latitude, as stated by your error.

You should use the field lookup to filter your Shops by the attribute of the linked object Address (documentation)

Since your Shop model is linked to your Address model by the field address, to filter the Shop by the Address attributes, you can do (ie for the latitude field):

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

Also, your two exclude methods could be rewritted like this (using the Q object):

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

I advice you to read the documentation linked above about the queryset API.

Clément Denoix
  • 1,504
  • 11
  • 18
  • on doing select_related() django internally does left outer join with the related table. I want to use latitude and longitude from the address table. – user2858738 Nov 17 '17 at 16:46
  • `select_related` add a join clause, but you still need to query the related instances attributes using the relation. I strongly advise you to read this: https://docs.djangoproject.com/en/1.11/topics/db/queries/#lookups-that-span-relationships – Clément Denoix Nov 17 '17 at 16:52