Django:如何从相关模型中检索所有属性以进行 GeoJSON 序列化?
Django: How to retrieve all attributes from related models for GeoJSON serialization?
我有两个模型 Site
和 Cell
,每个站点都有多个 Cell。
from django.db import models
from django.contrib.gis.db.models import PointField
class SiteManager(models.Model):
def get_by_natural_key(self, name, state_code, location):
return self.get(name=name, state_code=state_code, location=location)
class Site(models.Model):
name = models.CharField(max_length=10)
state_code = models.PositiveSmallIntegerField()
location = PointField()
objects = SiteManager()
class Meta:
unique_together = [['name', 'state_code', 'location']]
def natural_key(self):
return (self.name, self.state_code, self.location)
class Cell(models.Model):
tech = models.CharField(max_length=5)
azimuth = models.IntegerField()
sector_id = models.CharField(max_length=10)
frequency_band = models.CharField(max_length=15)
power = models.DecimalField(decimal_places=2, max_digits=4)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
def natural_key(self):
return (self.tech, self.azimuth,) + self.site.natural_key()
natural_key.dependencies = ['astmaps.site']
我想检索完整的 Cell
属性以及 Site
模型中的相关属性,对我来说 Serialize
结果 Cell
的,进入 GeoJson
数据,我可以轻松地 Serialize
Site
模型,例如:
from django.core.serializers import serialize # GeoJSON Serializer
sites = Site.objects.all()
sitesData = serialize('geojson', sites, geometry_field='location',
fields=('name', 'state_code'))
这给了我一个 GeoJson
featureCollection
object 像:
{
"type":"FeatureCollection",
"crs":{
"type":"name",
"properties":{
"name":"EPSG:4326"
}
},
"features":[
{
"type":"Feature",
"properties": {
"name":"02101",
"state_code":2
},
"geometry":{
"type":"Point",
"coordinates":[
1.34944,
36.1586
]
}
}
]
}
但是当涉及到Cell
模型时,我总是无法从相关模型中成功获取几何字段null
。
由于 Cell
模型有 Site
模型作为相关模型,我使用函数 select_related()
来获取相关属性:
cells = Cell.objects.select_related('site').all()
cellsData = serialize('geojson', cells, geometry_field='site_location',
fields=('azimuth', ...))
但是 GeoJson
Serialize
函数无法从 cells
QuerySet
:
中识别 Site
模型属性
{
"type":"FeatureCollection",
"crs":{
"type":"name",
"properties":{
"name":"EPSG:4326"
}
},
"features":[
{
"type":"Feature",
"properties":{
"azimuth":340
},
"geometry":null
},
{
"type":"Feature",
"properties":{
"azimuth":340
},
"geometry":null
},
{
"type":"Feature",
"properties":{
"azimuth":240
},
"geometry":null
}
]
}
我已经在数据库上直接测试了 Django ORM 等效返回的查询:
cells = Cell.objects.select_related('site').all()
>>> print(cells.query)
SELECT "app_cell"."id", "app_cell"."tech", "app_cell"."azimuth", "app_cell"."sector_id", "app_cell"."frequency_band", "app_cell"."power", "app_cell"."site_id", "app_cell"."id", "app_site"."name", "app_site"."state_code", "app_site"."location"::bytea FROM "app_cell" INNER JOIN "app_site" ON ("app_cell"."site_id" = "app_site"."id")
这给了我正确的结果(两个模型的所有属性或列):
我还使用了Natural Keys
,这是外键和其他关系的序列化策略(正如我在文档中阅读并相应地更改了模型):
cellsData = serialize('geojson', cells, geometry_field='site_location',
fields=('azimuth', ...), use_natural_foreign_keys=True)
但同样的结果,Serialize 方法无法识别 Site
模型属性。
如何使用 GeoJSON Serializer
获取多个相关模型的所有属性以进行序列化?
我设法通过使用原始 sql
查询加上 PostGIS
扩展的 json_build_object
和 ST_AsGeoJSON
得到了我想要的:
from django.db import connection
def sites_list(request):
cursor = connection.cursor()
cursor.execute("""select json_build_object(
'type', 'FeatureCollection',
'features', json_agg(ST_AsGeoJSON(t.*)::json)
)
from ( SELECT "app_cell"."id", "app_cell"."tech", "app_cell"."azimuth", "app_cell"."sector_id",
"app_cell"."frequency_band", "app_cell"."power", "app_cell"."site_id", "app_site"."name"
AS "site_name", "app_site"."state_code", "app_cell"."location"::bytea::geometry AS "site_location"
FROM "app_cell" INNER JOIN "app_site" ON ("app_cell"."site_id" = "app_site"."id")
) as t(id, tech, azimuth, sector_id, frequency_band, power, site_id, site_name, state_code, geom);""")
geojson = cursor.fetchone()
return JsonResponse(geojson[0], safe=False)
我在 JavaScript
方面遇到了一些问题,使用时:
cursor.fetchall()
return JsonResponse(geojson, safe=False)
returned GeoJSON
对象被 [[]] 双括号包围,因为 cursor.fetchall()
return a tuple
, 所以,我'我们使用 cursor.fetchone()
获取仅由单个括号 [] 包围的 geoJSON 对象,并使用结果元组的索引 0 获取唯一的元组内容作为字符串,最后 JsonResponse
函数将 return 结果作为 JSON
对象。
我有两个模型 Site
和 Cell
,每个站点都有多个 Cell。
from django.db import models
from django.contrib.gis.db.models import PointField
class SiteManager(models.Model):
def get_by_natural_key(self, name, state_code, location):
return self.get(name=name, state_code=state_code, location=location)
class Site(models.Model):
name = models.CharField(max_length=10)
state_code = models.PositiveSmallIntegerField()
location = PointField()
objects = SiteManager()
class Meta:
unique_together = [['name', 'state_code', 'location']]
def natural_key(self):
return (self.name, self.state_code, self.location)
class Cell(models.Model):
tech = models.CharField(max_length=5)
azimuth = models.IntegerField()
sector_id = models.CharField(max_length=10)
frequency_band = models.CharField(max_length=15)
power = models.DecimalField(decimal_places=2, max_digits=4)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
def natural_key(self):
return (self.tech, self.azimuth,) + self.site.natural_key()
natural_key.dependencies = ['astmaps.site']
我想检索完整的 Cell
属性以及 Site
模型中的相关属性,对我来说 Serialize
结果 Cell
的,进入 GeoJson
数据,我可以轻松地 Serialize
Site
模型,例如:
from django.core.serializers import serialize # GeoJSON Serializer
sites = Site.objects.all()
sitesData = serialize('geojson', sites, geometry_field='location',
fields=('name', 'state_code'))
这给了我一个 GeoJson
featureCollection
object 像:
{
"type":"FeatureCollection",
"crs":{
"type":"name",
"properties":{
"name":"EPSG:4326"
}
},
"features":[
{
"type":"Feature",
"properties": {
"name":"02101",
"state_code":2
},
"geometry":{
"type":"Point",
"coordinates":[
1.34944,
36.1586
]
}
}
]
}
但是当涉及到Cell
模型时,我总是无法从相关模型中成功获取几何字段null
。
由于 Cell
模型有 Site
模型作为相关模型,我使用函数 select_related()
来获取相关属性:
cells = Cell.objects.select_related('site').all()
cellsData = serialize('geojson', cells, geometry_field='site_location',
fields=('azimuth', ...))
但是 GeoJson
Serialize
函数无法从 cells
QuerySet
:
Site
模型属性
{
"type":"FeatureCollection",
"crs":{
"type":"name",
"properties":{
"name":"EPSG:4326"
}
},
"features":[
{
"type":"Feature",
"properties":{
"azimuth":340
},
"geometry":null
},
{
"type":"Feature",
"properties":{
"azimuth":340
},
"geometry":null
},
{
"type":"Feature",
"properties":{
"azimuth":240
},
"geometry":null
}
]
}
我已经在数据库上直接测试了 Django ORM 等效返回的查询:
cells = Cell.objects.select_related('site').all()
>>> print(cells.query)
SELECT "app_cell"."id", "app_cell"."tech", "app_cell"."azimuth", "app_cell"."sector_id", "app_cell"."frequency_band", "app_cell"."power", "app_cell"."site_id", "app_cell"."id", "app_site"."name", "app_site"."state_code", "app_site"."location"::bytea FROM "app_cell" INNER JOIN "app_site" ON ("app_cell"."site_id" = "app_site"."id")
这给了我正确的结果(两个模型的所有属性或列):
我还使用了Natural Keys
,这是外键和其他关系的序列化策略(正如我在文档中阅读并相应地更改了模型):
cellsData = serialize('geojson', cells, geometry_field='site_location',
fields=('azimuth', ...), use_natural_foreign_keys=True)
但同样的结果,Serialize 方法无法识别 Site
模型属性。
如何使用 GeoJSON Serializer
获取多个相关模型的所有属性以进行序列化?
我设法通过使用原始 sql
查询加上 PostGIS
扩展的 json_build_object
和 ST_AsGeoJSON
得到了我想要的:
from django.db import connection
def sites_list(request):
cursor = connection.cursor()
cursor.execute("""select json_build_object(
'type', 'FeatureCollection',
'features', json_agg(ST_AsGeoJSON(t.*)::json)
)
from ( SELECT "app_cell"."id", "app_cell"."tech", "app_cell"."azimuth", "app_cell"."sector_id",
"app_cell"."frequency_band", "app_cell"."power", "app_cell"."site_id", "app_site"."name"
AS "site_name", "app_site"."state_code", "app_cell"."location"::bytea::geometry AS "site_location"
FROM "app_cell" INNER JOIN "app_site" ON ("app_cell"."site_id" = "app_site"."id")
) as t(id, tech, azimuth, sector_id, frequency_band, power, site_id, site_name, state_code, geom);""")
geojson = cursor.fetchone()
return JsonResponse(geojson[0], safe=False)
我在 JavaScript
方面遇到了一些问题,使用时:
cursor.fetchall()
return JsonResponse(geojson, safe=False)
returned GeoJSON
对象被 [[]] 双括号包围,因为 cursor.fetchall()
return a tuple
, 所以,我'我们使用 cursor.fetchone()
获取仅由单个括号 [] 包围的 geoJSON 对象,并使用结果元组的索引 0 获取唯一的元组内容作为字符串,最后 JsonResponse
函数将 return 结果作为 JSON
对象。