基于Django框架的灾情数据查询接口和损失曲线查询接口

(一).灾情查询接口

(1)链接数据库后使用结合SQL语句进行查询(不推荐使用,可能数据库会有注入风险):

<1>API代码如下:

from django.http import JsonResponse                                # 从Django的http模块导入JsonResponse类,用于返回JSON格式的响应。
from app_query.models import ApiDisaster_internet,ApiDisaster_internet_image
from app_query.models import ApiVulnerability_curve_building,ApiVulnerability_curve_cotton
import datetime                                                     # 导入python的日期处理模块。
import psycopg2                                                     # 导入用于连接Postgresql数据库的库。


### 查询灾情数据接口
def disaster_query(request):
    ### 通过浏览器中输入,从GET请求查询中获取特定的参数值,如果没有提供对应的参数,就将变量设置为None。
    type = request.GET.get('type', None)
    region = request.GET.get('region', None)
    start_time_str = request.GET.get('start_time', None)
    end_time_str = request.GET.get('end_time', None)

    # 打印接收到的参数信息(用于调试)
    print(
        f"Received parameters: type={type}, region={region}, start_time={start_time_str}, end_time={end_time_str}")


    # 连接数据库
    dbConn = psycopg2.connect(
        dbname="data_agg",                                  # 连接名为data_agg的数据库。
        user='postgres',
        password='QYkj$2023$$',
        host='43.138.35.113',
        port=5432
    )
    cursor = dbConn.cursor()  # 创建一个游标对象,由于执行SQL查询。

    # 初始化一个 SQL 查询语句
    query = "SELECT * FROM disaster_internet"                 # 用于后面将查询条件添加到这条查询语句中。

    # 创建一个空列表condition,用于存储后续的查询条件
    conditions = []

    ### 如果有disaster_type参数,将条件disaster_type='{disaster_type}'添加到condition列表中,这意味这如果指定了灾害类型,查询将只选择该类型的记录。
    if type:
        conditions.append(f"type = '{type}'")

    ### 如果有 address参数,进行地址的模糊匹配查询
    if region:
        address_condition = ""                                  # 初始化一个空字符串,用于构建地址查询条件。
        for char in region:                                    # 遍历地址字符串(address)中的每个字符,并将其赋值给变量char。
            if address_condition:
                address_condition += " AND "                    # 如果地址不为空,添加 AND 连接符。
            address_condition += f"region LIKE '%{char}%'"     # 构建模糊匹配的地址查询条件,例如 address LIKE '%武%','%汉%'等,对每个字符进行模糊匹配。
        if address_condition:
            conditions.append(f"({address_condition})")         # 如果地址条件不为空,将其添加到 conditions 列表。



    # 如果有start_datetime_str和end_datetime_str参数,将字符串转换为datetime对象后,添加时间范围条件"datetime BETWEEN '{start_datetime}' AND '{end_datetime}'",用于筛选在指定时间范围内的记录。
    if start_time_str and end_time_str:
        # 如果有 start_datetime_str 和 end_datetime_str 参数,将其转换为 datetime 对象。
        start_time = datetime.datetime.strptime(start_time_str, '%Y-%m-%d')
        end_time = datetime.datetime.strptime(end_time_str, '%Y-%m-%d')
        # 添加时间范围查询条件到 condition 列表。
        conditions.append(f"datetime BETWEEN '{start_time}' AND '{end_time}'")

    # 如果有条件存在,将条件添加到初始查询语句中,使用WHERE和AND连接多个条件
    if conditions:
        query += " WHERE " + " AND ".join(conditions)                   # 如果 condition 列表不为空,将条件添加到查询语句中。

    # 执行构建好的SQL查询语句
    cursor.execute(query)
    # 获取查询结果的所有行
    rows = cursor.fetchall()                # 从数据库游标中获取所有查询结果的行,并将其存储在变量rows中。
    # 将查询结果转换为一个列表,列表中的每一个元素是一个字典,包含灾害类型,地址和时间三个字段的值,查询结果的每一行中提取的列值。
    result_data = []
    if rows:
        for row in rows:
            item = {
                'disaster_id': row[0],
                'type': row[1],
                'region': row[2],
                'datetime': row[3],
                'longitude': row[4],
                'latitude': row[5],
                'title': row[6],
                'abstract': row[7],
                'src_abstract': row[8],
                'src_content': row[9],
                'ai_abstract': row[10],
                'ai_engine': row[11],
                'ai_content': row[12],
                'image_url': row[13],
            }
            result_data.append(item)                     # 如果有查询结果(result),则将每一行item字典添加到 result 列表中。

    cursor.close()                                  # 关闭游标。
    dbConn.close()                                  # 关闭数据库连接。

<2>models代码如下:

from django.db import models

# Create your models here.

class ApiDisaster_internet(models.Model):
    disaster_id = models.UUIDField(primary_key=True, verbose_name='灾害id')
    type = models.CharField(max_length=255, verbose_name='灾害类型')
    region = models.CharField(max_length=255, verbose_name='灾害区域')
    datatime = models.DateTimeField(verbose_name='灾害时间')
    longitude = models.CharField(max_length=255, verbose_name='经度')
    latitude = models.CharField(max_length=255, verbose_name='纬度')
    title = models.CharField(max_length=255, verbose_name='标题')
    abstract = models.CharField(max_length=255, verbose_name='摘要')
    # description = models.CharField(max_length=255, verbose_name='描述信息')
    src_abstract = models.CharField(max_length=255, verbose_name='原始摘要')
    src_content = models.TextField(verbose_name='原始描述', null=False)
    ai_abstract = models.CharField(max_length=255, verbose_name='AI提取后的摘要')
    ai_content = models.JSONField(verbose_name='AI提取后结构化的数据')
    ai_engine = models.CharField(max_length=32, verbose_name='存储是由哪个AI提取的')
    image_url = models.CharField(max_length=255, verbose_name='图片路径')

    class Meta:
        db_table = 'disaster_internet'

(2)基于Django框架自带的ORM进行查询(推荐使用):

### 灾情数据查询接口
# 从请求对象中获取查询参数
def disaster_query(request):
    type_param = request.GET.get('type', None)
    region_param = request.GET.get('region', None)
    start_time_str = request.GET.get('start_time', None)
    end_time_str = request.GET.get('end_time', None)

    # 用于调试(打印接收到的查询参数)
    print(f"Received parameters: type={type_param}, region={region_param}, start_time={start_time_str}, end_time={end_time_str}")

    # 创建一个查询集 queryset,并获取 ApiDisaster_internet 模型的所有对象。
    queryset = ApiDisaster_internet.objects.all()

    if type_param:
        queryset = queryset.filter(type=type_param)


    if region_param:
        # 改进地区匹配逻辑,将输入的地区字符串按空格分割后进行多个关键词的模糊匹配
        region_keywords = region_param.split()                  # 将地区参数字符串按空格进行分隔(若无空格则将如湖北省武汉市汉口江滩分割为['湖北省','武汉市','汉口江滩'])
        region_condition = models.Q()
        for keyword in region_keywords:
            region_condition &= models.Q(region__contains=keyword)      # 构建一个复合查询,通过与操作使得最终的查询结果满足所有的关键词条件。
        if region_condition:
            queryset = queryset.filter(region_condition)


    if start_time_str and end_time_str:
        utc_timezone = pytz.utc                                     # 设置时区对象。
        start_time = datetime.strptime(start_time_str, '%Y-%m-%d').replace(tzinfo=utc_timezone)
        end_time = datetime.strptime(end_time_str, '%Y-%m-%d').replace(tzinfo=utc_timezone)
        queryset = queryset.filter(datetime__range=(start_time, end_time))


    result_data = []
    if queryset.exists():
        result_data = list(queryset.values())

    if result_data:
        response_data = {
            "status": 200,
            "result": result_data,
            "message": "OK"
        }
        return JsonResponse(response_data, safe=False)
    else:
        response_data = {
            "status": 404,
            "result": [],
            "message": "No results found"
        }
        return JsonResponse(response_data, safe=False)

(二).损失曲线查询结果

(1)连接数据库之结合SQL语句对表进行查询:

<1>API代码如下:

### 损失曲线查询接口
def curve_query(request):
    type_param = request.GET.get('type', None)
    if type_param not in ['building', 'cotton']:
        return JsonResponse({"status": 400, "result": [], "message": "Invalid type parameter."}, safe=False)

    # 连接数据库
    dbConn = psycopg2.connect(
        dbname="data_agg",                                  # 连接名为data_agg的数据库。
        user='postgres',
        password='QYkj$2023$$',
        host='43.138.35.113',
        port=5432
    )
    cursor = dbConn.cursor()  # 创建一个游标对象,由于执行SQL查询。

    model_classes = {
        'building': ApiVulnerability_curve_building,
        'cotton': ApiVulnerability_curve_cotton
    }
    model = model_classes[type_param]
    query = f"SELECT * FROM {model._meta.db_table}"
    cursor.execute(query)
    rows = cursor.fetchall()
    result_data = []
    for row in rows:
        item = {}
        for index, field in enumerate(model._meta.fields):
            item[field.name] = row[index]
        result_data.append(item)

    cursor.close()
    dbConn.close()

    return JsonResponse({"status": 200, "result": result_data, "message": "Success"}, safe=False)

<2>models代码如下:


class ApiVulnerability_curve_building(models.Model):
    水深 = models.DecimalField(max_digits=10, decimal_places=2, primary_key=True)
    砖混结构农村住房 = models.FloatField()
    砖结构农村住房 = models.FloatField()
    砖混结构城市住房 = models.FloatField()
    砖结构城市住房 = models.FloatField()
    砖混结构商业用房 = models.FloatField()
    砖结构商业用房 = models.FloatField()
    框架结构商业用房 = models.FloatField()

    class Meta:
        db_table = 'VULNERABILITY_CURVE_BUILDING'


class ApiVulnerability_curve_cotton(models.Model):
    duration = models.DecimalField(max_digits=10, decimal_places=1, primary_key=True)
    loss = models.FloatField()

    class Meta:
        db_table = 'VULNERABILITY_CURVE_COTTON'

(2)基于Django自带的ORM框架进行查询:

### 损失曲线查询接口
def curve_query(request):
    type_param = request.GET.get('type', None)
    if type_param not in ['building', 'cotton']:
        return JsonResponse({"status": 400, "result": [], "message": "Invalid type parameter."}, safe=False)

    model = None
    if type_param == 'building':
        model = ApiVulnerability_curve_building
    elif type_param == 'cotton':
        model = ApiVulnerability_curve_cotton

    # 选取选定的models中的所有对象,并转换为字典列表形式赋值给result_data中。
    result_data = list(model.objects.all().values())

    ### 定义一个字典field_mappings,用于将中文列名映射为英文列名。
    field_mappings = {
        'building': {
            "水深": "water_depth",
            "砖混结构农村住房": "rural_housing_with_brick_concrete_structure",
            "砖结构农村住房": "rural_housing_with_brick_structure",
            "砖混结构城市住房": "urban_housing_with_brick_concrete_structure",
            "砖结构城市住房": "urban_housing_with_brick_structure",
            "砖混结构商业用房": "commercial_building_with_brick_concrete_structure",
            "砖结构商业用房": "commercial_building_with_brick_structure",
            "框架结构商业用房": "commercial_building_with_frame_structure"
        },
        'cotton':{}             # 棉花表是英文,不需要转换,所以留的空字典。
    }

    new_result_data = []

    for item in result_data:
        new_item = {}
        mapping = field_mappings[type_param]
        for key, value in item.items():              # key:键(数据库表中的列名),value:对应列的值。
            if key in mapping:                       # 检查当前的遍历到的key(列名)是否存在于映射字典mapping中(如果key在mapping中,说明这个列名有对应的英文映射)。
                new_item[mapping[key]] = value       # 将原始数据中的值赋给新字典中以英文列名(mapping[key])作为键的位置。
            else:
                new_item[key] = value                # 如果不存在于映射字典中(如cotton:{}这个空字典),我们就直接使用原始的键key(原始的列名)。
        new_result_data.append(new_item)             # 将处理后的字典new_item添加到列表new_result_data中。

    return JsonResponse({"status": 200, "result": new_result_data, "message": "Success"}, safe=False)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有梦想的小晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值