zh第六周注释

zh_branch
张慧 3 months ago
parent 4ccff4e443
commit bfc2f8ca14

@ -0,0 +1,5 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

@ -0,0 +1 @@
views.py

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/src.iml" filepath="$PROJECT_DIR$/.idea/src.iml" />
</modules>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,11 @@
# 导入Django的admin模块用于在管理后台注册和管理数据模型
from django.contrib import admin
# Register your models here. # Django自动生成的注释提示在此处注册需要在管理后台显示的模型
# 定义一个管理配置类OwnTrackLogsAdmin继承自admin.ModelAdmin
# 这个类用于配置OwnTrackLog模型在Django管理后台的显示和操作方式
class OwnTrackLogsAdmin(admin.ModelAdmin):
# pass表示暂时不添加任何自定义配置使用默认的管理后台设置
# 后续可以在这里添加各种属性如list_display、search_fields等来自定义管理界面
pass

@ -0,0 +1,10 @@
# 导入Django的AppConfig类用于配置应用的元数据和初始化行为
from django.apps import AppConfig
# 定义一个应用配置类OwntracksConfig继承自AppConfig
# 该类用于配置名为'owntracks'的Django应用
class OwntracksConfig(AppConfig):
# name属性指定了应用的名称必须与应用的目录名一致
# 这个名称会被Django用于识别和管理该应用
name = 'owntracks'

@ -0,0 +1,47 @@
# 导入Django的models模块用于定义数据模型
from django.db import models
# 导入Django的时区工具用于处理时间相关操作
from django.utils.timezone import now
# Create your models here. # Django自动生成的注释提示在此处创建数据模型
# 定义一个名为OwnTrackLog的数据模型类继承自models.Model
# 这个模型用于存储OwnTracks一个位置追踪应用的位置日志信息
class OwnTrackLog(models.Model):
# 定义tid字段CharField表示字符串类型
# max_length=100限制最大长度为100字符
# null=False表示该字段不允许为空
# verbose_name='用户'用于在admin后台显示的字段名称
tid = models.CharField(max_length=100, null=False, verbose_name='用户')
# 定义lat字段FloatField表示浮点型用于存储纬度信息
# verbose_name='纬度'用于在admin后台显示的字段名称
lat = models.FloatField(verbose_name='纬度')
# 定义lon字段FloatField表示浮点型用于存储经度信息
# verbose_name='经度'用于在admin后台显示的字段名称
lon = models.FloatField(verbose_name='经度')
# 定义creation_time字段DateTimeField表示日期时间类型
# '创建时间'是字段的位置参数等同于verbose_name='创建时间'
# default=now设置默认值为当前时间使用Django的时区设置
creation_time = models.DateTimeField('创建时间', default=now)
# 定义对象的字符串表示方法
# 当打印该模型的实例时会返回tid字段的值
def __str__(self):
return self.tid
# Meta类用于定义模型的元数据
class Meta:
# ordering=['creation_time']指定查询该模型数据时的默认排序方式
# 按creation_time字段升序排列加负号表示降序如['-creation_time']
ordering = ['creation_time']
# verbose_name定义模型在admin后台的单数显示名称
verbose_name = "OwnTrackLogs"
# verbose_name_plural定义模型在admin后台的复数显示名称
verbose_name_plural = verbose_name
# get_latest_by='creation_time'指定使用creation_time字段来获取最新记录
# 可以通过模型管理器的latest()方法获取最新记录
get_latest_by = 'creation_time'

@ -0,0 +1,105 @@
# 导入json模块用于处理JSON数据格式
import json
# 从Django测试框架导入必要的测试工具
# Client用于模拟用户在视图上的请求
# RequestFactory用于创建请求对象
# TestCase是Django测试的基础类
from django.test import Client, RequestFactory, TestCase
# 导入账户模型BlogUser用于测试用户相关功能
from accounts.models import BlogUser
# 从当前应用导入要测试的模型OwnTrackLog
from .models import OwnTrackLog
# Create your tests here. # Django自动生成的注释提示在此处编写测试代码
# 定义测试类OwnTrackLogTest继承自TestCase
# 该类包含对OwnTrackLog模型及相关视图的测试用例
class OwnTrackLogTest(TestCase):
# setUp方法在每个测试方法执行前运行用于初始化测试环境
def setUp(self):
# 创建一个测试客户端,用于模拟用户请求
self.client = Client()
# 创建一个请求工厂,用于构建复杂的请求对象
self.factory = RequestFactory()
# 定义具体的测试方法方法名以test_开头
def test_own_track_log(self):
# 定义一个符合要求的测试数据字典包含tid、lat、lon字段
o = {
'tid': 12,
'lat': 123.123,
'lon': 134.341
}
# 使用测试客户端发送POST请求到指定URL
# 发送JSON格式的数据指定content_type为application/json
self.client.post(
'/owntracks/logtracks', # 请求的URL
json.dumps(o), # 将字典转换为JSON字符串
content_type='application/json') # 指定内容类型
# 检查数据库中OwnTrackLog记录的数量
length = len(OwnTrackLog.objects.all())
# 断言记录数为1验证第一条数据成功保存
self.assertEqual(length, 1)
# 定义一个不完整的测试数据字典缺少lon字段
o = {
'tid': 12,
'lat': 123.123
}
# 再次发送POST请求使用不完整的数据
self.client.post(
'/owntracks/logtracks',
json.dumps(o),
content_type='application/json')
# 再次检查数据库中记录的数量
length = len(OwnTrackLog.objects.all())
# 断言记录数仍为1验证不完整数据没有被保存
self.assertEqual(length, 1)
# 测试未登录状态下访问/show_maps页面
rsp = self.client.get('/owntracks/show_maps')
# 断言返回状态码为302重定向验证未登录用户被重定向
self.assertEqual(rsp.status_code, 302)
# 创建一个超级用户,用于测试登录状态下的功能
user = BlogUser.objects.create_superuser(
email="liangliangyy1@gmail.com",
username="liangliangyy1",
password="liangliangyy1")
# 使用测试客户端登录刚刚创建的用户
self.client.login(username='liangliangyy1', password='liangliangyy1')
# 手动创建并保存一条OwnTrackLog记录
s = OwnTrackLog()
s.tid = 12
s.lon = 123.234
s.lat = 34.234
s.save()
# 测试登录状态下访问/show_dates页面
rsp = self.client.get('/owntracks/show_dates')
# 断言返回状态码为200成功
self.assertEqual(rsp.status_code, 200)
# 测试登录状态下访问/show_maps页面
rsp = self.client.get('/owntracks/show_maps')
# 断言返回状态码为200成功
self.assertEqual(rsp.status_code, 200)
# 测试登录状态下访问/get_datas页面
rsp = self.client.get('/owntracks/get_datas')
# 断言返回状态码为200成功
self.assertEqual(rsp.status_code, 200)
# 测试登录状态下带日期参数访问/get_datas页面
rsp = self.client.get('/owntracks/get_datas?date=2018-02-26')
# 断言返回状态码为200成功
self.assertEqual(rsp.status_code, 200)

@ -0,0 +1,28 @@
# 导入Django的path函数用于定义URL路径
from django.urls import path
# 从当前应用导入views模块包含视图函数
from . import views
# 定义应用的命名空间为"owntracks"
# 用于在模板中引用URL时避免命名冲突格式为"app_name:url_name"
app_name = "owntracks"
# 定义URL模式列表每个path对应一个URL路径与视图函数的映射
urlpatterns = [
# 定义路径'owntracks/logtracks'映射到views.manage_owntrack_log视图函数
# name='logtracks'为该URL指定名称用于在模板和代码中引用
path('owntracks/logtracks', views.manage_owntrack_log, name='logtracks'),
# 定义路径'owntracks/show_maps'映射到views.show_maps视图函数
# name='show_maps'为该URL指定名称
path('owntracks/show_maps', views.show_maps, name='show_maps'),
# 定义路径'owntracks/get_datas'映射到views.get_datas视图函数
# name='get_datas'为该URL指定名称
path('owntracks/get_datas', views.get_datas, name='get_datas'),
# 定义路径'owntracks/show_dates'映射到views.show_log_dates视图函数
# name='show_dates'为该URL指定名称
path('owntracks/show_dates', views.show_log_dates, name='show_dates')
]

@ -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)
Loading…
Cancel
Save