news 2026/5/5 1:25:44

【RealEarthStudio】应用2:数据集渲染任务管理——后端搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【RealEarthStudio】应用2:数据集渲染任务管理——后端搭建

数据集渲染任务管理——后端搭建

  • 引言
  • 一、主要功能
  • 二、实现步骤
    • 2.1 创建App
      • (1)使用命令行创建App
      • (2)注册App
      • (3)配置路由
    • 2.2 创建Model
      • (1)配置媒体文件地址
      • (2)创建model
      • (3)迁移数据库
    • 2.3 在Admin中注册模型
    • 2.4 效果

引言

计算机专业硕士在读,主要研究方向是特定目标大斜视角目标检测与定位。因为要做的是特定目标,公开数据集较少,经过多方考虑还是决定要自建数据集。最终考虑的解决方案还是Blender+Python API的方式,项目起名叫RealEarthStudio
这系列文章主要对开发过程进行记录,方便我个人后续查看,也给相类似方向的同学提供一个思路。

【项目目录】:项目目录链接


一、主要功能

  • 功能:数据集渲染任务管理——后端搭建。

  • 背景:现在开始开发第二个应用,主要实现数据集渲染任务管理。

  • 效果

  • 码云项目链接:https://gitee.com/charlsewyq/RealEarthStudio


二、实现步骤

2.1 创建App

(1)使用命令行创建App

python manage.py startapp app2_rendering_task

(2)注册App

  • App目录下编辑apps文件:app2_rendering_task/apps.py
fromdjango.appsimportAppConfigclassApp2RenderingTaskConfig(AppConfig):default_auto_field="django.db.models.BigAutoField"name="app2_rendering_task"verbose_name="🏷️ 应用2:数据集渲染任务管理模块"
  • 主项目目录settings.py中添加app:
INSTALLED_APPS=[...,# 我的应用'app2_rendering_task.apps.App2RenderingTaskConfig',]

(3)配置路由

  • App目录下创建urls.py
fromdjango.urlsimportpathfrom.importviews app_name='app2_rendering_task'urlpatterns=[# 子路由]
  • 主项目目录urls.py修改:
fromdjango.contribimportadminfromdjango.urlsimportpath,include urlpatterns=[...# app2: 数据集渲染任务管理模块path("api/app2/",include("app2_rendering_task.urls")),]

2.2 创建Model

我想创建渲染任务Model,包含以下字段:

  • 渲染ID:字符串类型,模型的唯一标识,自动生成
  • 渲染时间:时间类型,上传模型的时间,根据后台时间自动记录
  • 目标模型:多对多,对应目标模型Modelapp1_model_management.TargetModel
  • 场景模型:多对多,对应场景模型Modelapp1_model_management.SceneModel
  • 日光方位角:浮点类型,阳光照射的方位角(限制为0-360°,默认为0°)
  • 日光高低角:浮点类型,阳光照射的高低角(限制为0-90°,默认为90°)
  • 相机距离:JSON类型,相机距离目标模型的距离数组(限制为正值)
  • 相机高低角:JSON类型,相机照射的高低角数组(限制为0-90°)
  • 相机方位角间隔:浮点类型,阳光照射的方位角(限制为0-360°,默认为45°)
  • 渲染图像分辨率(宽):整型,渲染图像的宽。
  • 渲染图像分辨率(高):整型,渲染图像的宽。
  • 渲染图像像素:计算属性,渲染图像的像素值。
  • 模型器类别:字符串类型,渲染器类别(EEVEE或CYCLES)
  • 渲染图像地址:文件地址类型,只读,用于存储渲染结果,删除数据时自动删除对应文件夹中的文件

(1)配置媒体文件地址

  • 主项目目录创建文件夹:media
  • settings.py中添加以下内容:
MEDIA_URL='/media/'MEDIA_ROOT=os.path.join(BASE_DIR,'media')
  • 配置媒体文件服务:
    主项目目录下编辑urls.py文件:
...# 只在DEBUG模式下提供媒体文件服务ifsettings.DEBUG:urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

(2)创建model

还需要完成以下功能:

  • 自动生成UUID,确保模型ID不重复
  • 自动记录时间
  • 把目标模型和
  • 删除数据时同步删除模型文件
  • 修改文件数据时替换模型文件

App目录下编辑model文件:app2_rendering_task/models.py

importosimportuuidfromdjango.dbimportmodelsfromdjango.utilsimporttimezonefromdjango.core.exceptionsimportValidationErrorimportshutilfromapp1_model_management.modelsimportTargetModel,SceneModel# ====== 验证器 ======defvalidate_azimuth(value):ifnot(0<=value<=360):raiseValidationError("方位角必须在 0° 到 360° 之间。")defvalidate_elevation(value):ifnot(0<=value<=90):raiseValidationError("高低角必须在 0° 到 90° 之间。")defvalidate_positive_number_list(value):"""验证是否为正数列表"""ifnotisinstance(value,list):raiseValidationError("必须是一个列表。")foriteminvalue:ifnotisinstance(item,(int,float))oritem<=0:raiseValidationError("所有值必须是正数。")defvalidate_elevation_list(value):"""验证高低角列表 0-90"""ifnotisinstance(value,list):raiseValidationError("必须是一个列表。")foriteminvalue:ifnotisinstance(item,(int,float))ornot(0<=item<=90):raiseValidationError("所有高低角必须在 0° 到 90° 之间。")# ====== 模型 ======defrendered_result_path(instance,filename):"""场景模型上传路径"""returnos.path.join("Render",f"{instance.render_time}-{instance.render_id}")classRenderingTask(models.Model):RENDERER_CHOICES=[('EEVEE','EEVEE'),('CYCLES','Cycles'),]# 任务信息render_id=models.UUIDField("渲染ID",default=uuid.uuid4,editable=False,unique=True,help_text="渲染任务的唯一标识")render_time=models.DateTimeField(verbose_name="渲染时间",default=timezone.now)# 模型target_models=models.ManyToManyField(TargetModel,verbose_name="目标模型",blank=True,related_name="rendering_tasks")scene_models=models.ManyToManyField(SceneModel,verbose_name="场景模型",blank=True,related_name="rendering_tasks")# 日光参数sun_azimuth=models.FloatField("日光方位角",default=0.0,validators=[validate_azimuth],help_text="阳光照射的方位角(0°-360°)")sun_elevation=models.FloatField("日光高低角",default=90.0,validators=[validate_elevation],help_text="阳光照射的高低角(0°-90°)")# 相机参数camera_distances=models.JSONField("相机距离",default=list,blank=True,validators=[validate_positive_number_list],help_text="相机到目标的距离列表(正值)")camera_elevations=models.JSONField("相机高低角",default=list,blank=True,validators=[validate_elevation_list],help_text="相机高低角列表(0°-90°)")camera_rotation_step=models.FloatField("相机方位角间隔",default=45.0,validators=[validate_azimuth],help_text="相机方位角采样间隔(0°-360°)")# 渲染分辨率image_width=models.PositiveIntegerField("渲染图像分辨率(宽)",default=1920)image_height=models.PositiveIntegerField("渲染图像分辨率(高)",default=1080)# 渲染器类别renderer_type=models.CharField("渲染器类别",max_length=10,choices=RENDERER_CHOICES,default='EEVEE')# 渲染结果文件rendered_result=models.FileField("渲染图像地址",upload_to=rendered_result_path,blank=True,null=True,help_text="系统自动生成的渲染结果图像(只读)")classMeta:verbose_name="01-渲染任务"verbose_name_plural="01-渲染任务"ordering=['-render_time']def__str__(self):returnf"{self.render_id}"@propertydefimage_pixels(self):"""计算属性:总像素数"""returnself.image_width*self.image_heightdefsave(self,*args,**kwargs):"""可选:在保存前调用 full_clean() 进行验证"""self.full_clean()super().save(*args,**kwargs)defdelete(self,*args,**kwargs):""" 重写 delete 方法: 1. 先删除关联的渲染输出文件夹 2. 再调用父类 delete 删除数据库记录 """ifself.rendered_result:# 获取文件的绝对路径folder_dir=self.rendered_result.path# 如果文件存在则删除ifos.path.isdir(folder_dir):shutil.rmtree(folder_dir)# 调用父类的delete方法删除数据库记录super().delete(*args,**kwargs)

(3)迁移数据库

# 生成迁移文件python manage.py makemigrations app2_rendering_task# 应用迁移python manage.py migrate app2_rendering_task

2.3 在Admin中注册模型

App目录下编辑admin文件:app2_rendering_task/admin.py

fromdjango.contribimportadminfrom.modelsimport*fromdjango.utils.safestringimportmark_safe@admin.register(RenderingTask)classRenderingTaskAdmin(admin.ModelAdmin):list_display=['render_id','render_time','renderer_type','image_width','image_height','render_progress_display']search_fields=['render_id']list_filter=['renderer_type','render_time']readonly_fields=['render_id','render_time','render_progress','rendered_result']# 字段分组显示fieldsets=(('任务信息',{'fields':('render_id','render_time','renderer_type','render_progress')}),('模型配置',{'fields':('target_models','scene_models')}),('光照参数',{'fields':('sun_azimuth','sun_elevation')}),('相机参数',{'fields':('camera_distances','camera_elevations','camera_rotation_step')}),('图像设置',{'fields':('image_width','image_height')}),('渲染结果',{'fields':('rendered_result',)}))@admin.display(description="渲染状态")defrender_progress_display(self,obj):ifobj.render_progress==0:# 如果状态是pending,显示一个链接returnmark_safe(f'<a href="#">开始渲染</a>')else:# 否则显示当前状态returnf"{obj.render_progress}%"

2.4 效果



版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/4 18:27:35

LobeChat能否实现AI导游?旅游推荐与行程规划助手

LobeChat 能否实现 AI 导游&#xff1f;旅游推荐与行程规划助手 在智能出行日益普及的今天&#xff0c;旅行者不再满足于千篇一律的攻略模板。他们希望获得真正“懂自己”的建议&#xff1a;带孩子的家庭想知道哪些景点推婴儿车最方便&#xff1b;摄影爱好者关心清晨几点到西湖…

作者头像 李华
网站建设 2026/5/2 13:00:25

AI如何帮你生成高效密码字典?

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个密码字典生成工具&#xff0c;能够根据用户输入的关键词、个人信息&#xff08;如生日、姓名等&#xff09;自动生成常见密码组合。支持自定义规则&#xff0c;如长度限制、…

作者头像 李华
网站建设 2026/5/4 22:10:10

无人机产业变革前夜:当飞行器开始“思考”

算法定义硬件的时代&#xff0c;无人机正从飞行平台演变为自主决策系统在森林防火巡查中&#xff0c;无人机不仅能识别火情&#xff0c;还能区分枯树与潜在火情&#xff1b;在城市高空&#xff0c;它可以辨别企业团建与非法聚集&#xff1b;在应急救援中&#xff0c;它能穿越浓…

作者头像 李华
网站建设 2026/5/1 2:27:11

深度解析 - 软件包依赖安装机制与故障排除

一、问题现象重述 在Anolis OS 8.6系统&#xff08;基于RHEL 8.6&#xff09;中&#xff0c;已通过yum 4.7.0安装A-1.0.0和B-1.0.0软件包。当挂载OS-v2的ISO作为yum源后&#xff0c;执行yum install A B时出现以下典型现象&#xff1a; 系统提示需要安装多个新增依赖包部分依…

作者头像 李华