|
|
|
|
@ -0,0 +1,170 @@
|
|
|
|
|
# Create your views here.
|
|
|
|
|
# 导入必要的模块
|
|
|
|
|
import datetime # 处理日期时间
|
|
|
|
|
import itertools # 提供迭代器相关功能
|
|
|
|
|
import json # 处理JSON数据
|
|
|
|
|
import logging # 日志记录
|
|
|
|
|
from datetime import timezone # 时区处理
|
|
|
|
|
from itertools import groupby # 用于对序列进行分组
|
|
|
|
|
|
|
|
|
|
import django # Django框架核心
|
|
|
|
|
import requests # 发送HTTP请求
|
|
|
|
|
from django.contrib.auth.decorators import login_required # 登录验证装饰器
|
|
|
|
|
from django.http import HttpResponse # HTTP响应
|
|
|
|
|
from django.http import JsonResponse # JSON格式响应
|
|
|
|
|
from django.shortcuts import render # 渲染模板
|
|
|
|
|
from django.views.decorators.csrf import csrf_exempt # 禁用CSRF验证装饰器
|
|
|
|
|
|
|
|
|
|
from .models import OwnTrackLog # 导入当前应用的模型
|
|
|
|
|
|
|
|
|
|
# 配置日志记录器
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 禁用CSRF验证的视图函数,用于处理OwnTracks的日志记录
|
|
|
|
|
@csrf_exempt
|
|
|
|
|
def manage_owntrack_log(request):
|
|
|
|
|
try:
|
|
|
|
|
# 从请求中读取并解析JSON数据
|
|
|
|
|
s = json.loads(request.read().decode('utf-8'))
|
|
|
|
|
# 提取必要的字段
|
|
|
|
|
tid = s['tid']
|
|
|
|
|
lat = s['lat']
|
|
|
|
|
lon = s['lon']
|
|
|
|
|
|
|
|
|
|
# 记录日志信息
|
|
|
|
|
logger.info(
|
|
|
|
|
'tid:{tid}.lat:{lat}.lon:{lon}'.format(
|
|
|
|
|
tid=tid, lat=lat, lon=lon))
|
|
|
|
|
# 验证字段是否存在
|
|
|
|
|
if tid and lat and lon:
|
|
|
|
|
# 创建并保存新的日志记录
|
|
|
|
|
m = OwnTrackLog()
|
|
|
|
|
m.tid = tid
|
|
|
|
|
m.lat = lat
|
|
|
|
|
m.lon = lon
|
|
|
|
|
m.save()
|
|
|
|
|
return HttpResponse('ok') # 返回成功响应
|
|
|
|
|
else:
|
|
|
|
|
return HttpResponse('data error') # 数据不完整错误响应
|
|
|
|
|
except Exception as e:
|
|
|
|
|
# 记录异常信息
|
|
|
|
|
logger.error(e)
|
|
|
|
|
return HttpResponse('error') # 异常错误响应
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 需要登录才能访问的视图,用于显示地图
|
|
|
|
|
@login_required
|
|
|
|
|
def show_maps(request):
|
|
|
|
|
# 仅允许超级用户访问
|
|
|
|
|
if request.user.is_superuser:
|
|
|
|
|
# 获取当前UTC日期作为默认日期
|
|
|
|
|
defaultdate = str(datetime.datetime.now(timezone.utc).date())
|
|
|
|
|
# 从请求参数中获取日期,默认为当前日期
|
|
|
|
|
date = request.GET.get('date', defaultdate)
|
|
|
|
|
# 准备上下文数据
|
|
|
|
|
context = {
|
|
|
|
|
'date': date
|
|
|
|
|
}
|
|
|
|
|
# 渲染模板并返回
|
|
|
|
|
return render(request, 'owntracks/show_maps.html', context)
|
|
|
|
|
else:
|
|
|
|
|
# 非超级用户返回403禁止访问
|
|
|
|
|
from django.http import HttpResponseForbidden
|
|
|
|
|
return HttpResponseForbidden()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 需要登录才能访问的视图,用于显示日志日期列表
|
|
|
|
|
@login_required
|
|
|
|
|
def show_log_dates(request):
|
|
|
|
|
# 获取所有记录的创建时间
|
|
|
|
|
dates = OwnTrackLog.objects.values_list('creation_time', flat=True)
|
|
|
|
|
# 提取日期部分并去重排序
|
|
|
|
|
results = list(sorted(set(map(lambda x: x.strftime('%Y-%m-%d'), dates))))
|
|
|
|
|
|
|
|
|
|
# 准备上下文数据
|
|
|
|
|
context = {
|
|
|
|
|
'results': results
|
|
|
|
|
}
|
|
|
|
|
# 渲染模板并返回
|
|
|
|
|
return render(request, 'owntracks/show_log_dates.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 将GPS坐标转换为高德地图坐标的函数
|
|
|
|
|
def convert_to_amap(locations):
|
|
|
|
|
convert_result = []
|
|
|
|
|
# 创建迭代器
|
|
|
|
|
it = iter(locations)
|
|
|
|
|
|
|
|
|
|
# 每次处理30个坐标(高德API限制)
|
|
|
|
|
item = list(itertools.islice(it, 30))
|
|
|
|
|
while item:
|
|
|
|
|
# 格式化坐标为"经度,纬度;经度,纬度"形式
|
|
|
|
|
datas = ';'.join(
|
|
|
|
|
set(map(lambda x: str(x.lon) + ',' + str(x.lat), item)))
|
|
|
|
|
|
|
|
|
|
# 高德API密钥和接口地址
|
|
|
|
|
key = '8440a376dfc9743d8924bf0ad141f28e'
|
|
|
|
|
api = 'http://restapi.amap.com/v3/assistant/coordinate/convert'
|
|
|
|
|
# 请求参数
|
|
|
|
|
query = {
|
|
|
|
|
'key': key,
|
|
|
|
|
'locations': datas,
|
|
|
|
|
'coordsys': 'gps' # 源坐标系统为GPS
|
|
|
|
|
}
|
|
|
|
|
# 发送转换请求
|
|
|
|
|
rsp = requests.get(url=api, params=query)
|
|
|
|
|
result = json.loads(rsp.text)
|
|
|
|
|
# 处理转换结果
|
|
|
|
|
if "locations" in result:
|
|
|
|
|
convert_result.append(result['locations'])
|
|
|
|
|
# 处理下一批坐标
|
|
|
|
|
item = list(itertools.islice(it, 30))
|
|
|
|
|
|
|
|
|
|
# 合并所有转换结果并返回
|
|
|
|
|
return ";".join(convert_result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 需要登录才能访问的视图,用于获取轨迹数据
|
|
|
|
|
@login_required
|
|
|
|
|
def get_datas(request):
|
|
|
|
|
# 获取当前UTC时间
|
|
|
|
|
now = django.utils.timezone.now().replace(tzinfo=timezone.utc)
|
|
|
|
|
# 默认查询日期为今天
|
|
|
|
|
querydate = django.utils.timezone.datetime(
|
|
|
|
|
now.year, now.month, now.day, 0, 0, 0)
|
|
|
|
|
# 如果请求中指定了日期,则使用指定日期
|
|
|
|
|
if request.GET.get('date', None):
|
|
|
|
|
date = list(map(lambda x: int(x), request.GET.get('date').split('-')))
|
|
|
|
|
querydate = django.utils.timezone.datetime(
|
|
|
|
|
date[0], date[1], date[2], 0, 0, 0)
|
|
|
|
|
# 计算查询日期的下一天(用于范围查询)
|
|
|
|
|
nextdate = querydate + datetime.timedelta(days=1)
|
|
|
|
|
# 查询指定日期范围内的所有记录
|
|
|
|
|
models = OwnTrackLog.objects.filter(
|
|
|
|
|
creation_time__range=(querydate, nextdate))
|
|
|
|
|
result = list()
|
|
|
|
|
# 如果有查询结果
|
|
|
|
|
if models and len(models):
|
|
|
|
|
# 按tid分组处理记录
|
|
|
|
|
for tid, item in groupby(
|
|
|
|
|
sorted(models, key=lambda k: k.tid), key=lambda k: k.tid):
|
|
|
|
|
|
|
|
|
|
# 构建返回数据结构
|
|
|
|
|
d = dict()
|
|
|
|
|
d["name"] = tid
|
|
|
|
|
paths = list()
|
|
|
|
|
# 注释掉的代码:使用高德转换后的经纬度
|
|
|
|
|
# locations = convert_to_amap(
|
|
|
|
|
# sorted(item, key=lambda x: x.creation_time))
|
|
|
|
|
# for i in locations.split(';'):
|
|
|
|
|
# paths.append(i.split(','))
|
|
|
|
|
|
|
|
|
|
# 使用GPS原始经纬度
|
|
|
|
|
# 按创建时间排序并添加到路径列表
|
|
|
|
|
for location in sorted(item, key=lambda x: x.creation_time):
|
|
|
|
|
paths.append([str(location.lon), str(location.lat)])
|
|
|
|
|
d["path"] = paths
|
|
|
|
|
result.append(d)
|
|
|
|
|
# 返回JSON格式的结果
|
|
|
|
|
return JsonResponse(result, safe=False)
|