day22-Form内置序列化错误信息

本文介绍如何利用Ajax和Django的Form组件实现前端表单验证及复杂数据类型的序列化处理,包括自定义序列化器以支持ValidationError等。

一、前言

  今天我们来用个一个ajax的例子,来说明form的验证,还有一个就是,我们json.dumps的只能是python简单的数据类型,但是如果遇到复杂的数据类型,json.dumps是序列化不了的,那这个怎么办呐。我们用什么办法解决呐,下面我们就来学习一下,这个东西,还有一个就是我们在写,views代码的时候,我们可以另外建一个文件夹,所以我们整体的目录结构如下:

-sday22
	-app01  #app名字
		migrations  #初始化数据库的
		views       #写业务代码的
			- __init__.py
			- accounts.py #用户验证
			- blogs.py    #博客业务代码
			- ...
		.....
		forms       #写forms验证的
			- __init__.py
			- froms.py    #专业做forms验证的
			- ....
		....
	- sday22  #项目名
		.....
	- static  #静态资源
		....
	- templates  #模板
		...
	- manage.py

二、用ajax获取内置序列化错误信息

  前提,我们以后的项目编写,都按照上面的目录结构,所以我们的业务代码都是写在view文件夹下的

2.1、路由设置

说明:设置登录的url

from django.urls import path
from app01.views import accounts

urlpatterns = [
    path('login/', accounts.login),
]

2.2、视图函数编写

说明:这边要写很多,这边有from验证,django的序列化的转换,以及登录函数login,为了方便我们写在一个文件里面,但是下面是我分3块去写

1、forms验证

from django import forms
from django.forms import fields,widgets

class LoginForm(forms.Form):
    username = fields.CharField() #这跟login.html中的input标签的name属性的值一致
    password = fields.CharField(
        max_length=64,
        min_length=12
    )

2、定义JsonCustomEncoder类

说明:这个类特意是为了处理无法序列化复杂的数据类型的,上面  result = json.dumps(ret,cls=JsonCustomEncoder) #这边cls 是序列化的时候,对每一个字段序列化的时候,都会调用一个它的default方法,会在下面的login函数中用到

from django.core.exceptions import ValidationError
import json
class JsonCustomEncoder(json.JSONEncoder):  #直接在cls=JsonCustomEncoder类名,去序列化复杂的数据类型
    def default(self,field):
        if isinstance(field,ValidationError):  #field是否是ValidationError的一个对象
            return {'code':field.code,'messages':field.messages}
        else:
            return json.JSONEncoder.default(self,field)

3、login函数

说明:序列化的时候,复杂的数据类型,json是处理不了的,所以需要特殊处理,这边要定义个JsonCustomEncoder类

from django.shortcuts import render,HttpResponse
import json

def login(request):
    ret = {'status':True,'error':None,'data':None}
    if request.method == "GET":
        return render(request,'login.html')
    elif request.method == "POST":
        obj = LoginForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            # print(type(obj.errors))
            # ret['error'] = obj.errors.as_json()  # as_data 帮我返回的是原生的字典
            # print(type(obj.errors.as_data()))
            # for k,v in obj.errors.as_data().items():
            #     print(k,v)
            # ret = {'k1':'v1','k2':ValueError()}  #像这种复杂数据类型,json是不能序列化的,我们只能做局部处理
            #from django.forms.utils import ErrorDict  #通过源码得知:as_data 帮我返回的是原生的字典,as_json()是类似json格式的字符串
            # print(obj.errors.as_json())  #我拿到一个字符串,把这个字符串添加到error中

            # from django.core.exceptions import ValidationError  #看一下这个异常
            ret['error'] = obj.errors.as_data()
        result = json.dumps(ret,cls=JsonCustomEncoder)  #这边cls 是序列化的时候,对每一个字段序列化的时候,都会调用一个它的default方法
        return HttpResponse(json.dumps(result))

2.3、模板编写

说明:模板我们用ajax去请求,然后收到数据处理

<body>
    <form id="fm">
        {% csrf_token %}
        <p><input type="text" name="username" /></p>  #这边username 需要跟 from 里面的字段 是一模一样
        <p><input type="text" name="password" /></p>
        <a id="submit">提交</a>
    </form>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        $(function(){
            $('#submit').click(function(){
                $.ajax({
                    url:'/login/',
                    type:'post',
                    data:$('#fm').serialize(),
                    sucess:function(arg){
                        //console.log(arg);
                        arg = JSON.parse(arg);
                        console.log(arg)
                    },
                    error:function(){

                    }
                })
            })
        })
    </script>
</body>

最后返回的数据类型为:

"{\"data\": null, \"status\": true, \"error\": {\"username\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}],
 \"password\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}]}}"

三、总结

  1. python中的json函数,只能处理 简单的 数据类型,如果要处理复杂的数据类型,比如:datetime、ValidationError等这种复杂的数据类型,需要协助定义:JsonCustomEncoder类,然后json.dumps(ret,cls=JsonCustomEncoder)去引用
  2. python还有其他的复杂的序列化操作:http://www.cnblogs.com/zhangqigao/articles/8990400.html

转载于:https://www.cnblogs.com/zhangqigao/articles/8989193.html

<think>我们被要求解释NetCDF和TIFF格式之间的区别。根据用户提供的引用,我们可以总结如下: 1. **NetCDF(Network Common Data Form)**: - 是一种用于存储多维科学数据(如气象、海洋、气候等)的格式。 - 支持多个维度(例如经度、纬度、时间、高度等)和变量(如温度、降水等)。 - 包含丰富的元数据(如单位、坐标参考、数据来源等),这些元数据以属性(全局属性和变量属性)的形式存储。 - 结构灵活,由用户自定义,包括维度(dimensions)、变量(variables)、属性(attributes)和数据(data)[^2]。 - 通常用于存储时间序列的多维数据,例如逐日降水数据。 2. **TIFF(Tagged Image File Format)** 或 **GeoTIFF**: - 是一种主要用于存储栅格图像(例如卫星影像、数字高程模型等)的格式。 - GeoTIFF是TIFF的扩展,增加了地理参考信息(如坐标系统、投影参数、地理变换等),使其能够表示地理空间数据。 - 通常用于存储单波段或多波段的栅格数据,但不直接支持多维数据(如时间序列)。如果需要存储时间序列,通常需要多个独立的TIFF文件。 - 元数据支持相对有限,但可以通过标签(tags)来存储一些地理信息[^3]。 ### 主要区别总结: | 特性 | NetCDF | TIFF/GeoTIFF | |------|--------|--------------| | **数据结构** | 多维数组(支持多个维度,如时间、高度等) | 二维栅格(或带波段的二维栅格) | | **元数据** | 丰富的元数据(全局和变量属性) | 地理参考信息(GeoTIFF)和有限的标签 | | **适用领域** | 科学数据(气象、海洋、气候等) | 地理空间图像(遥感、地形图等) | | **时间序列** | 原生支持(时间作为维度) | 需要多个文件(每个时间点一个文件) | | **坐标系统** | 通过维度变量和属性描述 | 通过GeoTIFF标签定义 | | **转换工具** | 可使用gdal_translate等工具转换为GeoTIFF[^3] | 可使用gdal_translate从NetCDF中提取并转换 | ### 转换说明: 根据引用[1]和[3],可以使用工具(如Python的gdal库)将NetCDF文件转换为TIFF格式。这通常涉及以下步骤: 1. 从NetCDF文件中读取特定变量(例如降水)。 2. 提取指定时间步长的数据切片。 3. 将数据切片写入GeoTIFF文件,并设置地理参考信息。 示例命令(使用gdal_translate): ```bash gdal_translate -of GTiff NETCDF:"input.nc":precip output.tif ``` ### 相关问题: §§相关问题§§ 1. 如何将NetCDF文件中的特定变量转换为GeoTIFF格式? 2. 在转换过程中如何保留NetCDF文件中的元数据? 3. 如何从多时间步长的NetCDF文件中批量导出GeoTIFF? 4. GeoTIFF能否存储三维数据(如高程)?</think>### NetCDF与TIFF格式的核心区别 #### 1. **数据结构差异** | 特性 | NetCDF (.nc) | TIFF/GeoTIFF (.tif) | |--------------|---------------------------------------|-----------------------------------| | **维度支持** | 原生支持多维数据(时间、高度等)[^1] | 主要支持二维空间数据 | | **数据组织** | 基于维度+变量+属性的层级结构[^2] | 基于像素矩阵的栅格结构 | | **元数据** | 内置全局/局部属性(单位、坐标系等) | 需通过GeoTIFF扩展存储地理信息 | #### 2. **科学数据存储能力 - **NetCDF优势**: - 可直接存储时间序列(如1961-2022逐日降水)[^1] - 支持动态添加维度(如气象模式中的预测步长) - 变量间关联性强(如降水与温度共享同一经纬度网格) ```python # 典型NetCDF结构 dimensions: time = 365 # 时间维度 lat = 720 # 纬度维度 lon = 1440 # 经度维度 variables: float precip(time, lat, lon) # 降水变量 units = "mm/day" ``` - **GeoTIFF局限**: - 单文件仅存储单一时刻/波段数据 - 时间序列需拆分多个文件(如`precip_20220101.tif`) - 地理信息依赖外部标签(需GDAL等工具解析) #### 3. **地理空间特性对比 - **坐标参考**: - NetCDF:通过`grid_mapping`变量定义投影[^2] ```nc int crs; crs:proj4_params = "+proj=longlat +datum=WGS84" ``` - GeoTIFF:通过内部GeoKey目录存储投影(如EPSG代码) - **数据值存储**: - NetCDF:支持科学数据类型(如`int16`缩放值) - GeoTIFF:优化图像存储(支持LZW压缩、分块存储) #### 4. **典型应用场景 | 场景 | 推荐格式 | 原因说明 | |---------------------|--------------|------------------------------| | 气象/海洋时序数据 | NetCDF | 多维支持、元数据完整性 | | 遥感影像分发 | GeoTIFF | 广泛软件兼容性 | | 气候模式输出 | NetCDF | 变量关联性、高效存储 | | GIS空间分析 | GeoTIFF | 与ArcGIS/QGIS无缝集成 | #### 5. **转换关系(基于引用[3]) ```mermaid graph LR A[NetCDF] --gdal_translate--> B(单时刻GeoTIFF) A --Xarray+rioxarray--> C[时序GeoTIFF集] B --gdal_merge.py--> D[镶嵌图像] C --ArcGIS多维工具--> E[时序栅格立方体] ``` > **关键区别总结**:NetCDF是**科学数据容器**,适合存储多维关联数据集;GeoTIFF是**地理空间栅格标准**,适合空间分析和制图输出。在气象领域,常组合使用:NetCDF存储原始数据,转换GeoTIFF进行可视化[^3]。 --- ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值