Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用于RawSql的queryset字段的Django sql名称_Python_Django - Fatal编程技术网

Python 用于RawSql的queryset字段的Django sql名称

Python 用于RawSql的queryset字段的Django sql名称,python,django,Python,Django,我需要生成一个相当大的GeoJSON数据集。将queryset序列化为geojson是可行的,但速度非常慢。就我而言,大约30秒。使用PostGISST_AsGeoJSON({geometry\u field})::json然后从该查询集创建数据结构需要几秒钟,产生完全相同的结果 因此,为了在我的代码中使用这个方法,我有一个函数geojson\u queryset(queryset,geom\u字段,pk\u字段,其他字段)(在下面完整引用)。我最初写道: features_queryset

我需要生成一个相当大的GeoJSON数据集。将queryset序列化为geojson是可行的,但速度非常慢。就我而言,大约30秒。使用PostGIS
ST_AsGeoJSON({geometry\u field})::json
然后从该查询集创建数据结构需要几秒钟,产生完全相同的结果

因此,为了在我的代码中使用这个方法,我有一个函数
geojson\u queryset(queryset,geom\u字段,pk\u字段,其他字段)
(在下面完整引用)。我最初写道:

 features_queryset = queryset.extra(
     select={'geojson_queryset_result': f'ST_AsGeoJSON({geometry_field})::json'})\
     .values(*all_fields)
但是在读取QuerySet API doc for extra()时,该方法已被弃用,应该写成:

features_queryset = queryset.annotate(
    geojson_queryset_result=RawSQL(f'ST_AsGeoJSON({geometry_field})::json', [])
).values(*all_fields)
我不关心这里的SQL注入,因为这些字段完全不受用户输入的影响,我们只有一个
geom
、一个
simplified\u geom
location

但问题是,当queryset执行连接时,“geom”的名称可能会变得模棱两可<代码>区域.objects.filter(foo=1)很好,但是如果区域也有geom字段,则
区域.objects.filter(zone\uu foo=1)
将失败

在RawSQL中使用参数不起作用,因为它们用于值,而不是列名,所以它们被引用

因此,我的问题是如何将
geom
转换为正确的sql列表达式,如
a0.geom

完整代码: sql\u injection\u geom\u regex=re.compile(r'[^a-zA-Z0-9']

def geojson_queryset(queryset, geometry_field, pk_field='id', fields=[]):
    """
    This method is fast way to serialize to GeoJSON a queryset. The regular serializer is extremely slow and will need
    to be parsed from text to return in a Response object. This method is roughly 20x faster.
    :param queryset: queryset to return data from
    :param geometry_field: the field to be serialized to geojson
    :param pk_field: GeoJSON requires a primary key value, defaults to 'id'
    :param fields: List of fields to include in the result
    :return: a GeoJSON FeatureCollection with the requested data.
    """
    all_fields = [pk_field, *fields, 'geojson_queryset_result']
    # Try to avoid SQL injection in the geom_field name
    if sql_injection_geom_regex.match(geometry_field):
        raise ValueError("invalid geom field name")

    features_queryset = queryset.annotate(
        geojson_queryset_result=RawSQL(f'ST_AsGeoJSON({geometry_field})::json', [])
    ).values(*all_fields)

    # features_queryset = queryset.extra(
    #     select={'geojson_queryset_result': f'ST_AsGeoJSON({geometry_field})::json'})\
    #     .values(*all_fields)

    features = []
    for row in features_queryset:
        features.append({
            'type': 'Feature',
            'id': row['id'],
            'geometry': row['geojson_queryset_result'],
            'properties': {field: row[field] for field in fields}
        })

    return {
        'type': 'FeatureCollection',
        'crs': {
            'type': 'name',
            'properties': {
                'name': 'EPSG:4326'
            }
        },
        'features': features
    }