Django Web架构:全面掌握Django模型字段(下)

news/2024/4/24 15:12:18/文章来源:https://blog.csdn.net/qq_28550263/article/details/136383570
Django Web架构
全面掌握Django模型字段(下)

- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSitehttp://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/136380968
HuaWei:https://bbs.huaweicloud.com/blogs/422968

【介绍】:在开发Django应用时,模型字段扮演着至关重要的角色。它们不仅定义了数据的结构,即数据库表的列,还规定了数据的行为和如何与之交互。通过精心设计的模型字段,开发者可以在数据库和应用层之间建立起一座桥梁,使得数据的存取、验证和处理变得既高效又安全。


上一节:《 全面掌握Django模型字段(上)

在这里插入图片描述


开始前,请先阅读上一节:《 全面掌握Django模型字段(上)

1. 字段与数据库交互

Django 模型中,字段与数据库的交互是通过各种选项和方法来控制的。这些选项和方法定义了如何将模型字段映射到数据库列、如何处理索引以及如何在 Python 对象和数据库值之间进行转换。本节重点讨论数据库列映射,包括 db_columndb_index 等选项的使用及其对数据库性能的影响。

1.1 数据库列映射

1.1.1 数据库列映射的概念和用法

数据库列映射是指如何将Django模型字段映射到数据库中的列。这一过程主要通过db_column、db_index等选项来控制。

1. db_column

db_column 选项允许开发者自定义字段在数据库中的列名。如果不指定db_columnDjango 默认使用字段的名称作为数据库列名。例如:

class Person(models.Model):name = models.CharField(max_length=100, db_column='person_name')

在上述示例中,虽然模型字段名为name,但在数据库中,该字段的列名将被映射为person_name。

在实际开发中:

  • 当模型字段名称与数据库列名不一致时,可以使用db_column来指定正确的数据库列名。

  • 当数据库列名是SQL保留字或包含非法字符时,使用db_column来避免潜在的冲突。

2. db_index

db_index 选项用于指定是否为字段创建数据库索引。默认情况下,db_index 设置为False,意味着不会为字段创建索引。如果设置为TrueDjango 将为该字段创建索引,这可以提高查询性能,但可能会降低写入性能并增加数据库的存储需求。
例如:

class Article(models.Model):title = models.CharField(max_length=100, db_index=True)

在上面的代码中,title 字段将被创建索引,这有助于提高基于文章标题的查询速度。

1.1.2 数据库列映射的应用场景

当频繁根据某个字段进行查询时,为该字段创建索引可以显著提高查询效率。需要权衡索引带来的查询性能提升与其对写入性能和存储空间的影响。

对数据库性能的影响:

  • 查询性能:为字段创建索引可以显著提高基于该字段的查询速度,尤其是在数据量大时。
  • 写入性能:每次插入或更新数据时,数据库都需要更新索引,这可能会降低写入性能。
  • 存储需求:索引需要额外的存储空间,对于大型数据库,这可能是一个考虑因素。

通过合理使用 db_columndb_index 等选项,开发者可以在保证数据模型清晰性的同时,优化数据库的性能和存储效率。

1.2 数据库值与Python值的转换

Django 模型中,字段值在从数据库读取和保存到数据库时,经常需要进行数据类型的转换。这一过程确保了数据在 Python 代码和数据库之间的正确传递和存储。Django 提供了几个方法来处理这种类型转换,主要包括 from_db_value()to_python() 方法,以及 pre_save()get_db_prep_save() 方法。下面将详细介绍这些方法的作用和使用场景。

1. from_db_value()方法

from_db_value() 方法用于将数据库中的值转换为 Python 类型的值。当 Django 从数据库中读取数据时,会自动调用此方法。这对于自定义字段特别有用,因为它允许开发者控制从数据库读取数据后的数据处理过程。

def from_db_value(self, value, expression, connection):if value is None:return valuereturn my_custom_transformation(value)

在这个示例中,my_custom_transformation 是一个假设的函数,用于对数据库中读取的原始值进行处理,将其转换为所需的Python类型。

2. to_python()方法

to_python() 方法确保 Django 能够将字段的值转换为合适的 Python 数据类型。这个方法在多个场景下被调用,包括从数据库读取数据时、以及通过表单或序列化过程对数据进行清洗时。

def to_python(self, value):if isinstance(value, MyDesiredType):return valuereturn my_conversion_logic(value)

在这个例子中,MyDesiredType是目标Python数据类型,my_conversion_logic是将值转换为MyDesiredType类型的逻辑。

3. pre_save()方法

pre_save() 方法在模型保存到数据库之前被调用。这个方法允许开发者在数据被保存之前对其进行最后的处理或验证。

def pre_save(self, model_instance, add):value = getattr(model_instance, self.attname)return my_pre_save_process(value)

这里,my_pre_save_process是对即将保存的值进行处理的函数,self.attname是字段在模型中的属性名。

4. get_db_prep_save()方法

get_db_prep_save() 方法用于在将数据保存到数据库之前,将 Python 类型的值转换为适合数据库存储的格式。这个方法通常与 pre_save()方法一起使用,以确保数据正确地保存到数据库。

def get_db_prep_save(self, value, connection):return my_db_preparation(value)

在这个例子中,my_db_preparation 是一个函数,用于将 Python 值转换为数据库可以接受的格式。
通过正确使用这些方法,开发者可以确保数据在 Python 代码和数据库之间正确、高效地转换,同时也为处理复杂数据类型提供了灵活性。这些方法的组合使用,特别是在自定义字段类型时,是非常重要的,它们帮助开发者确保数据的一致性和完整性。

2. 字段与表单交互

Django 中,模型字段与表单字段之间的交互是通过 formfield 方法实现的。这一机制不仅确保了数据的一致性和有效性,还提供了灵活性,允许开发者根据具体需求自定义表单字段。

2.1 formfield方法的作用

formfield方法负责将模型字段转换为表单字段。每种模型字段类型(如CharFieldIntegerField等)都有一个对应的默认表单字段类型。当模型表单被创建时,Django会自动调用模型字段的formfield方法,以生成相应的表单字段。

from django.db import models
from django.forms import CharField, Formclass MyModel(models.Model):my_field = models.CharField(max_length=100)def formfield(self, **kwargs):return super().formfield(**{'form_class': CharField,'max_length': self.max_length,**kwargs,})

2.2 自定义表单字段

虽然 Django 为大多数模型字段提供了合适的默认表单字段,但有时候默认的表单字段可能无法满足特定的需求。在这种情况下,开发者可以通过覆盖 formfield 方法来自定义表单字段。
自定义表单字段允许开发者指定不同的表单字段类型、设置额外的表单字段选项(如widgethelp_text等),或者添加自定义的验证逻辑。

from django import forms
from django.db import modelsclass CustomModelField(models.CharField):def formfield(self, **kwargs):defaults = {'widget': forms.Textarea}defaults.update(kwargs)return super().formfield(**defaults)

在上述示例中,自定义的模型字段 CustomModelField 通过覆盖 formfield 方法,指定了一个不同的表单控件 forms.Textarea,使得在表单中该字段将以文本区域(而非单行输入框)的形式展现。

2.3 影响数据的验证和处理

自定义表单字段的一个重要方面是它们如何影响数据的验证和处理。通过自定义表单字段,开发者可以实现特定的数据清洗和验证逻辑,确保用户输入的数据符合预期。

class CustomForm(forms.Form):custom_field = forms.CharField(widget=forms.Textarea)def clean_custom_field(self):data = self.cleaned_data['custom_field']# 在这里添加自定义验证逻辑return data

在上述 CustomForm表单中,通过定义clean_custom_field方法,开发者可以对custom_field 字段的数据进行自定义的清洗和验证。这种机制提供了极大的灵活性,使得开发者可以根据具体的业务需求,对数据进行精确的控制和处理。

通过理解和利用Django模型字段与表单字段之间的交互机制,开发者可以构建出既灵活又强大的数据输入和验证逻辑,从而提升应用的用户体验和数据质量。

3. 字段的高级特性

3.1 关系字段

Django 中,关系字段允许模型之间建立链接,这是构建具有复杂数据关系的应用的基础。主要的关系字段包括 ForeignKeyManyToManyFieldOneToOneField 。每种字段类型都有其特定的用途和配置选项,可以用来实现不同类型的数据关系。

ForeignKey(外键)

ForeignKey 用于定义“多对一”的关系。例如,一个 Order 模型可能会有一个 ForeignKey 指向 Customer 模型,表示每个订单都关联到一个客户。
示例:

from django.db import modelsclass Customer(models.Model):name = models.CharField(max_length=100)class Order(models.Model):product = models.CharField(max_length=100)customer = models.ForeignKey(Customer, on_delete=models.CASCADE)

配置选项:

  • related_name:允许从 Customer 实例反向查询到所有相关的 Order 实例。
  • on_delete:定义当关联的 Customer 被删除时,对应的 Order 应如何处理。models.CASCADE 表示级联删除。

ManyToManyField(多对多关系)

ManyToManyField 用于定义 “多对多” 的关系。例如,一个 Student 模型和一个 Course 模型之间的关系,一个学生可以参加多个课程,一个课程也可以有多个学生参加。

例如:

class Student(models.Model):name = models.CharField(max_length=100)courses = models.ManyToManyField('Course', related_name='students')class Course(models.Model):name = models.CharField(max_length=100)

配置选项:

through:指定一个中间模型来详细定义多对多关系的额外数据。例如,可以通过through指定一个Enrollment模型来存储学生的选课时间等信息。

OneToOneField(一对一关系)

OneToOneField 用于定义“一对一”的关系。例如,一个 User 模型和一个UserProfile 模型,每个用户都有一个对应的用户档案,每个用户档案也只关联到一个用户。

例如:

from django.contrib.auth.models import Userclass UserProfile(models.Model):user = models.OneToOneField(User, on_delete=models.CASCADE)bio = models.TextField()

配置选项:
通常用于扩展已存在模型的信息。on_delete=models.CASCADE 确保当 User 被删除时,对应的 UserProfile 也会被删除。

3.2 字段查询与查找

在Django中,模型字段的查询和查找功能是通过一套丰富的API实现的,这些API允许开发者以几乎无限的方式查询数据库。此外,Django还提供了扩展这些查询能力的机制,包括注册自定义的查找和转换方法。本节将深入探讨如何利用这些功能,以及如何为模型字段添加自定义的查询方法。

查找注册API

Django的查找注册API允许开发者为模型字段注册自定义的查找逻辑。这是通过Field.register_lookup()方法实现的。查找是一种特殊的方法,用于在查询中指定如何比较字段和值。Django内置了多种查找类型,如exact、icontains等,但有时你可能需要定义特定于应用的查找逻辑。

示例:注册自定义查找
假设我们有一个需求,需要对CharField进行不区分大小写的精确匹配查找,但不使用iexact查找,因为我们想要实现一些特殊的逻辑。我们可以创建一个自定义查找类并注册它:

from django.db.models import CharField, Lookup@CharField.register_lookup
class InsensitiveExact(Lookup):lookup_name = 'iexact_custom'def as_sql(self, compiler, connection):lhs, lhs_params = self.process_lhs(compiler, connection)rhs, rhs_params = self.process_rhs(compiler, connection)params = lhs_params + rhs_paramsreturn f'LOWER({lhs}) = LOWER({rhs})', params

在这个例子中,InsensitiveExact 类继承自Lookup,并实现了as_sql方法,该方法定义了如何生成SQL查询。lookup_name属性定义了查找的名称,可以在查询中使用它,如 Model.objects.filter(field_name__iexact_custom='value')

自定义转换

转换是另一种强大的特性,允许在将数据库值转换为Python值时应用自定义逻辑。这通过覆盖字段的get_lookup()方法并返回一个自定义的转换类来实现。

示例:添加自定义转换
假设我们想要在查询结果返回之前,对某个字段的值进行自定义的处理,例如,对加密的字段进行解密:

from django.db.models import CharField, Transformclass DecryptTransform(Transform):lookup_name = 'decrypt'def as_sql(self, compiler, connection):lhs, params = compiler.compile(self.lhs)return f'DECRYPT({lhs})', paramsCharField.register_lookup(DecryptTransform)

在这个例子中,DecryptTransform类继承自 Transform,并实现了 as_sql 方法,该方法定义了如何生成 SQL查询以实现解密逻辑。现在,我们可以在查询中使用__decrypt来应用这个转换,如Model.objects.filter(field_name__decrypt='value')

通过使用查找注册API 和自定义转换,开发者可以极大地扩展 Django 的查询能力,实现复杂的查询逻辑和数据处理。这些高级特性为处理特殊的数据类型和查询需求提供了强大的工具。

4. 字段属性与方法解析

在Django中,每个模型字段都是Field类的一个实例或其子类的实例。这些字段类定义了如何在Python代码和数据库之间转换数据,以及如何在Django的ORM系统中使用这些数据。理解Field类的关键属性和方法对于高效地使用Django模型至关重要,尤其是在创建自定义字段时。

4.1 关键属性

name: 字段的名称。在模型中定义字段时使用的名称。
verbose_name: 字段的人类可读名称。如果未提供,Django会自动从字段的名称生成。
primary_key: 如果设置为True,该字段将作为模型的主键。
max_length: 用于CharField和TextField等字段,指定数据的最大长度。
default: 字段的默认值。可以是一个值或一个可调用对象。
null: 如果为True,允许字段在数据库中存储NULL值。对于非字符串字段,这通常用于表示“无数据”。
blank: 如果为True,字段在表单验证时可以为空。这与null不同,blank影响的是表单验证而非数据库存储。
choices: 一个由二元组组成的序列,用于定义字段的可选值。在表单和管理界面中,这些选项将显示为下拉列表。

4.2 关键方法

  • to_python(self, value): 将存储在数据库中的值转换为Python类型。这个方法在从数据库读取数据时被调用,以及在通过表单或序列化过程对数据进行清洗时。
def to_python(self, value):if isinstance(value, MyDesiredType):return valuereturn my_conversion_logic(value)
  • get_prep_value(self, value): 在将数据保存到数据库之前,将Python类型的值转换为适合数据库存储的格式。这个方法通常与pre_save方法一起使用,以确保数据正确地保存到数据库。
def get_prep_value(self, value):return my_db_preparation(value)
  • from_db_value(self, value, expression, connection): 用于从数据库类型转换为Python类型。这个方法在Django从数据库中读取数据时被调用。
def from_db_value(self, value, expression, connection):if value is None:return valuereturn my_custom_transformation(value)
  • pre_save(self, model_instance, add): 在模型保存到数据库之前被调用。这个方法允许开发者在数据被保存之前对其进行最后的处理或验证。
def pre_save(self, model_instance, add):value = getattr(model_instance, self.attname)return my_pre_save_process(value)
  • formfield(self, kwargs): 将模型字段转换为表单字段。这个方法负责创建表单字段的实例,可以通过覆盖这个方法来自定义表单字段的行为。
def formfield(self, **kwargs):defaults = {'form_class': MyFormField}defaults.update(kwargs)return super().formfield(**defaults)

4.3 自定义字段的实现

在定义自定义字段时,通常需要重写上述方法之一或多个,以实现特定的数据转换逻辑或验证逻辑。

例如,如果你正在创建一个用于存储加密文本的自定义字段,你可能需要重写 to_pythonget_prep_value 方法,以确保数据在保存到数据库之前被加密,在从数据库读取时被解密。通过深入理解 Field 类的属性和方法,开发者可以创建功能强大且灵活的自定义字段,满足特定应用的需求。这不仅增强了 Django 模型的功能,也使得数据处理和验证更加灵活和强大。

例如,如果你需要一个自定义字段来处理复杂的数据结构,如嵌套的字典或列表,你可能需要重写 to_python 方法来确保这些复杂数据在从数据库读取时能够被正确地转换为 Python 数据结构。同时,get_prep_value方法需要被重写以确保这些复杂数据在保存到数据库前能够被转换为数据库能够存储的格式,如 JSON 字符串。

from django.db import models
import jsonclass JSONField(models.TextField):"""自定义字段,用于处理JSON数据。"""def from_db_value(self, value, expression, connection):if value is None:return valuereturn json.loads(value)def to_python(self, value):if isinstance(value, dict) or value is None:return valuereturn json.loads(value)def get_prep_value(self, value):if value is None:return valuereturn json.dumps(value)

这段代码中,JSONField 是一个自定义模型字段,用于处理存储在数据库中的 JSON 数据。通过重写 from_db_valueto_pythonget_prep_value 方法,该字段能够在 Python 字典和数据库中的 JSON 字符串之间自动转换数据。

5. 结论

在本文中,我们深入探讨了 Django 模型中字段与数据库的交互、字段与表单的交互以及字段的高级特性。通过了解数据库列映射、数据库值与 Python值的转换、字段查询与查找、字段属性与方法解析等方面的内容,我们能够更好地理解和利用 Django 模型中字段的功能和灵活性。

深入理解 Django 模型中字段的交互和特性,能够帮助开发者更好地设计和管理数据模型,提升应用的性能、灵活性和可维护性,从而为用户提供更好的使用体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_997183.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

item_fee-获得淘宝商品快递费用 API调用说明获取测试key

item_fee-获得淘宝商品快递费用 .通过传入商品id、区域id,来获取该商品的快递费用。 公共参数 点此获取API请求地址 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称&a…

JavaScript基础4之原型的原型继承、原型链和理解对象的数据属性、访问器属性

JavaScript基础 原型原型继承问题解决 原型链isPrototypeOf()Object.getPrototypeOf() 理解对象数据属性访问器属性 原型 原型继承 继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript中大多是借助原型对象实现继承的特性。…

按图搜索淘宝商品(拍立淘)

使用淘宝拍立淘接口的步骤通常包括: 注册成为淘宝开放平台的开发者:在淘宝开放平台网站上注册账号并完成认证。 创建应用以获取API密钥:在您的开发者控制台中创建一个应用,并获取用于API调用的密钥,如Client ID和Clie…

OpenHarmony教程指南—Ability的启动模式

介绍 本示例展示了在一个Stage模型中,实现standard、singleton、specified多种模式场景。 本实例参考开发指南 。 本实例需要使用aa工具 查看应用Ability 模式信息。 效果预览 使用说明 1、standard模式: 1)进入首页,点击番茄…

FreeRTOS day2

使用ADC采样光敏电阻数值,如何根据这个数值调节LED灯亮度 总结DMA空闲中断接收数据的使用方法 首先要要选择串口然后配置串口的参数,配置MDA通道选择接受数据,配置空闲中断,定义一个数据接收的容器,启动MDA传输当串口…

学习大语言模型(LLM),从这里开始

在见识了ChatGPT的各种强大能力后,不少 NLP一线从业人员很自然地想到,以后开发者只要借助 ChatGPT,就可以做到现在大部分NLP工程师在做的事,比如文本分类、实体抽取、文本推理等。甚至随着大语言模型(largelanguagemod…

力扣刷题Days11第二题--141. 环形链表(js)

目录 1,题目 2,代码 2.1快慢指针 2.2,哈希表 3,学习与总结 3.1自己尝试写快慢指针 反思 1,题目 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达&…

时光机关:探秘Java中的Timer和TimerTask

欢迎来到我的博客,代码的世界里,每一行都是一个故事 时光机关:探秘Java中的Timer和TimerTask 前言Timer和TimerTask的基本概念Timer:TimerTask:为何它们是 Java 中任务调度的得力工具: Timer的使用方法创建…

python中的文件操作2

文件遍历 在Python中,遍历文件通常指的是逐行读取文件中的内容。这种方式对于处理大型文件特别有用,因为它不需要一次性将整个文件加载到内存中。下面是几种常见的遍历文件内容的方法: 1. 使用with语句和for循环 这是最推荐的方式&#xf…

appium解锁android真机系统的屏幕

在使用appium进行app自动化操作的过程中,经常遇到的第一个难题就是如何解锁系统屏幕,也就是亮屏解锁。 实际上解决办法如下:在desired_capabilities中增加两个参数unlockType和unlockKey,类似的示例代码如下: desire…

外包干了2年,技术退步明显

先说一下自己的情况,研究生,19年进入广州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

Stable Diffusion 模型分享:Realistic Stock Photo(真实的库存照片)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八下载地址模型介绍

利用Python爬取高德地图全国地铁站点信息

利用Python中的requests库进行地铁站点信息的获取,同时将数据保存在本机excel中 # 首先引入所需要的包 import requests from bs4 import BeautifulSoup import pandas as pd import json# 发送 GET 请求获取网页内容 url http://map.amap.com/subway/index.html response r…

vue3页面内容切换(类似登录、注册内容切换)

一、内容描述 页面有俩块内容,分别是验证码登录页面内容,账号密码登录页面内容。有俩种处理方式,一个是写俩个页面跳转使用,还有一种是一个页面俩个内容,切换的只是不同的内容,相同的内容保留。一般都是选择…

比肩Gen-2,全新开源文生视频模型

著名开源平台Stability.ai在官网宣布,推出全新文生视频的扩散模型Stable Video Diffusion,已开源了该项目并公布了论文。 据悉,用户通过文本或图像就能生成高精准,14帧和25帧的短视频。目前,Stable Video Diffusion处…

【常见索引使用】⭐️Mysql中索引的类型以及使用方式和失效场景

目录 一、前言 二、数据准备 三、索引的分类 四、索引示例 示例1、主键索引(Primary Key Index)与 唯一索引(Unique Index) 示例2、前缀索引(Prefix Index) 示例3、联合索引(复合索引&am…

Unity3D学习之XLua实践——背包系统

文章目录 1 前言2 新建工程导入必要资源2.1 AB包设置2.2 C# 脚本2.3 VSCode 的环境搭建 3 面板拼凑3.1 主面板拼凑3.2 背包面板拼凑3.3 格子复合组件拼凑3.4 常用类别名准备3.5 数据准备3.5.1 图集准备3.5.2 json3.5.3 打AB包 4 Lua读取json表及准备玩家数据5 主面板逻辑6 背包…

什么是工业协议网关?作用是什么?

在工业自动化和智能制造领域,数据的采集、传输和处理是实现设备监控、远程控制和优化的关键。而工业协议网关,作为连接工业设备与上层管理系统的桥梁,发挥着至关重要的作用。今天,我们就来深入解析一下HiWoo Box这一工业协议网关的…

【three.js】22. Imported Models导入模型

22. Imported Models导入模型 介绍 Three.js 可以让你创建很多原始几何体,但是当涉及到更复杂的形状时,我们最好使用专用的 3D 软件建模。 在本课中,我们将使用已经制作好的模型,但我们将在以后的课程中学习如何完全在 3D 软件中…

《汇编语言》第3版 (王爽)第10章检测点解析

第10章 检测点 检测点10.1:补全程序,实现从内存1000:0000处开始执行指令。 解析: 我们知道retf指令是用栈中的数据,同时修改CS和IP寄存器中的内容,实现远转移,而且是先出栈的数据放入IP中,后出栈的数据放入…