How to filter geodjango based on longitude and latitude

寵の児 提交于 2019-12-06 00:28:33

Using south... it would take 3 migrations to address this. (Link: How to install South]

1) Add a PointField called point:

from django.contrib.gis.db import models  <-- NEW

# ...

class Location(models.Model):
    #other fields here
    lat = models.CharField(blank=True, max_length=100)
    lng = models.CharField(blank=True, max_length=100)

    point = models.PointField(null=True)  <-- NEW

2) Perform a schemamigration automagically

patrick@localhost:~$ python manage.py schemamigration my_app_name --auto

3) Perform a custom datamigration where you will create a point on each element from the existing CharField attributes

patrick@localhost:~$ python manage.py datamigration my_app_name latlng_to_point

Edit the file that is created by the datamigration management command:

# my_app_name/migrations/0034__latlng_to_point.py

from django.contrib.gis.geos import Point

# ...

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
        for location in orm['my_app_name.Location'].objects.all():
            location.point = Point(float(location.lng), float(location.lat), srid=4326)
            location.save()

    def backwards(self, orm):
        "Write your backwards methods here."
        for location in orm['data.Location'].objects.all():
            location.point = None
            location.save()

4) Delete the CharField from your model and remove null=True if you wish:

class Location(models.Model):
    # other fields here
    # DELETED lat = models.CharField(blank=True, max_length=100)
    # DELETED lng = models.CharField(blank=True, max_length=100)

    point = models.PointField(null=False)  <-- NEW: null=False

5) Create another schemamigration automatically

patrick@localhost:~$ python manage.py schemamigration my_app_name --auto

6) Run the migrations successfully! This is when changes are written to your DB, etc.

patrick@localhost:~$ python manage.py migrate my_app_name

Schema Migration

Fast forward 2016, and we have migrations built into django you no longer need south. You need only two migrations instead of three.

Step 1: change the model.

class Location(models.Model):
    #other fields here
    lat = models.CharField(blank=True, max_length=100)
    lng = models.CharField(blank=True, max_length=100)

    point = models.PointField(null=True)

step 2: create the migration

./manage.py makemigrations

Data Migration

This is the third step and involves editing the migration file created above, look at the operations section and add

migrations.RunSQL('''UPDATE myapp_location SET `point` = Point(lat,lng)''')

This query is for mysql. If you are using PostGis your query would be

migrations.RunSQL('''UPDATE myapp_location SET "point" = ST_MakePoint(lng,lat)''')

Note that the format for postgis is lng,lat Note that this is a single query and should execute reasonably quickly. To iterate through all the rows with python and update them one by one would mean a million queries if you have a million records!

Step 4: ./manage.py migrate

Step 5: drop the lat, lng columns from the model.

step 6: ./manage.py makemigrations

step 7: ./manage.py migrate

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!