swiftsly
swiftsly

Reputation: 839

Filter query with range within Model

I'm trying to execute a query with the range test in my class (MapArea), but I don't seem to have a grasp on the visibility of objects in Models as I get NameError: name 'MapArea' is not defined.

My class is as follows:

class MapArea(models.Model):

    lat = models.DecimalField(max_digits=15,decimal_places=6)
    lon = models.DecimalField(max_digits=15,decimal_places=6)
    nearby_streets = MapArea.objects.filter(lat__range=[self.lat - 2, self.lat + 2], lon__range=[self.lon - 2, self.lon + 2])

    # Meta
    class Meta:
        abstract = True

Setting nearby_streets to MapArea.objects.filter(lat__range=[self.lat - 2, self.lat + 2], lon__range=[self.lon - 2, self.lon + 2]) is what causes the NameError: name 'MapArea' is not defined.

It seems like MapArea should be defined according to other answers, but I don't seem to be accessing it correctly. How can I access MapArea.objects.filter() in order to use the range test feature?

Thank you in advance.

Upvotes: 0

Views: 164

Answers (1)

Resley Rodrigues
Resley Rodrigues

Reputation: 2288

You cannot have a model field with such a behaviour. All the model fields are stored in the database, but nearby_streets seems to be something you query, so it's better as a method or property.

You could do something like this

class MapArea(models.Model):

    lat = models.DecimalField(max_digits=15,decimal_places=6)
    lon = models.DecimalField(max_digits=15,decimal_places=6)

    # Meta
    class Meta:
        abstract = True

    @property
    nearby_streets = MapArea.objects.filter(lat__range=[self.lat - 2, self.lat + 2], lon__range=[self.lon - 2, self.lon + 2])

And in the rest of your code you can access it from any instance of MapArea as such map_area.nearby_streets

Keep in mind that properties, just like methods are computed every time they are called, so if you call nearby_streets twice, it will hit the database twice...

You could use cached_property instead of property, so that the database is hit only once.

Upvotes: 2

Related Questions