Python Web框架之Django框架Model基础详解


Posted in Python onAugust 16, 2019

本文实例讲述了Python Web框架之Django框架Model基础。分享给大家供大家参考,具体如下:

model是关于你的数据的单一的,确定的信息来源。 它包含您正在存储的数据的基本字段和行为。Django通过抽象化的模型层(models)为你的网络应用提供对于数据的结构化处理和操作处理,数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库,使用数据库API对数据库进行增删改查的操作。

使用哪种数据库,只需要在settings.py中配置即可,如:

<1> sqlite: django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

<2> mysql:引擎名称:django.db.backends.mysql

<3>如果想更改数据库

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'books',  #你的数据库名称
    'USER': 'root',  #你的数据库用户名
    'PASSWORD': '', #你的数据库密码
    'HOST': '', #你的数据库主机,留空默认为localhost
    'PORT': '3306', #你的数据库端口
  }
}

注意事项:

  • NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
  • USER和PASSWORD分别是数据库的用户名和密码。
  • 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
  • 然后,启动项目,会报错:no module named MySQLdb
  • 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
  • 所以,我们只需要找到项目名文件下的__init__,在里面写入:
import pymysql
pymysql.install_as_MySQLdb()

Model 字段

AutoField        根据实际ID自动增长的IntegerField . 你通常不需要直接使用;
                如果不指定,一个主键字段将自动添加到你创建的
BigIntegerField    一个64位整数, 类似于一个 IntegerField 这个字段默认的表单组件是一个TextInput.

IntegerField([**options])
一个整数。在Django所支持的所有数据库中,从 -2147483648 到 2147483647 范围内的值是合法的。默认的表单输入工具是TextInput.

BinaryField        用来存储原始二进制码的Field. 只支持bytes 赋值,注意这个Field只有很有限的功能。
                例如,不大可能在一个BinaryField 值的数据上进行查询
BooleanField    true/false 字段。默认表单挂件是一个CheckboxInput.
                如果你需要设置null 值,则使用NullBooleanField 来代替BooleanField。
                如果Field.default没有指定的话, BooleanField 的默认值是 None。
CharField        一个用来存储从小到很大各种长度的字符串的地方。
                如果是巨大的文本类型, 可以用 TextField.
                这个字段默认的表单样式是 TextInput.
                CharField必须接收一个额外的参数:
                CharField.max_length:字段的最大字符长度.max_length将在数据库层和Django表单验证中起作用, 用来限定字段的长度.

DateField        这是一个使用Python的datetime.date实例表示的日期. 有几个额外的设置参数:

                DateField.auto_now 每次保存对象时,自动设置该字段为当前时间。
                用于"最后一次修改"的时间戳。注意,它总是使用当前日期;它不只是一个默认值,你可以覆盖。

                DateField.auto_now_add        当对象第一次被创建时自动设置当前时间。用于创建时间的时间戳.
                它总是使用当前日期;和你可以覆盖的那种默认值不一样。

                该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,
                和一个“Today"的快捷按钮.包含了一个额外的invalid_date错误消息键.

    DateTimeField(DateField)    - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)    - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field) - 时间格式      HH:MM[:ss[.uuuuuu]]

DurationField(Field)用作存储一段时间的字段类型 - 类似Python中的timedelta.
            - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

DecimalField(max_digits=None, decimal_places=None[, **options]) 表示十进制浮点数

EmailField([max_length=254, **options])一个 CharField 用来检查输入的email地址是否合法。它使用 EmailValidator 来验证输入合法性。

FileField([upload_to=None, max_length=100)一个上传文件的字段。
FileField字段不支持primary_key 和unique参数,如果使用会生成 TypeError错误

FilePathField(path=None[, match=None, recursive=False, max_length=100])
一个 CharField ,内容只限于文件系统内特定目录下的文件名。有三个参数, 其中第一个是 必需的:

FloatField([**options])用Python的一个float 实例来表示一个浮点数.

ImageField([upload_to=None, height_field=None, width_field=None, max_length=100, **options])
继承了 FileField的所有属性和方法, 但还对上传的对象进行校验,确保它是个有效的image.

TextField([**options])大文本字段。该模型默认的表单组件是Textarea。

TimeField([auto_now=False, auto_now_add=False, **options])
时间字段,和Python中 datetime.time 一样。接受与DateField相同的自动填充选项。
表单默认为 TextInput.输入框。

URLField([max_length=200, **options])一个CharField 类型的URL此字段的默认表单widget为TextInput。

UUIDField([**options])一个用来存储UUID的字段。使用Python的UUID类。
当使用PostgreSQL数据库时,该字段类型对应的数据库中的数据类型是uuid

字段选项(Field options)——参数

Field.null 如果为True,Django将在数据库中将空值存储为NULL。默认值是 False。

Field.blank 如果为True,则该字段允许为空白。 默认值是 False。

Field.choices 它是一个可迭代的结构(比如,列表或是元组),
由可迭代的二元组组成(比如[(A, B), (A, B) ...]),用来给这个字段提供选择项。
如果设置了 choices ,默认表格样式就会显示选择框,而不是标准的文本框,而且这个选择框的选项就是 choices 中的元组。

Field.db_column 数据库中用来表示该字段的名称。如果未指定,那么Django将会使用Field名作为字段名.

Field.db_index 若值为 True, 则 django-admin sqlindexes 将会为此字段输出 CREATE INDEX 语句。

Field.error_messages 能够让你重写默认抛出的错误信息。通过指定 key 来确认你要重写的错误信息。

Field.primary_key若为 True, 则该字段会成为模型的主键字段。
如果你没有在模型的任何字段上指定 primary_key=True, Django会自动添加一个 AutoField 字段来充当主键。

Field.unique 如果为 True, 这个字段在表中必须有唯一值.

Field.unique_for_month 类似unique_for_date,只是要求字段对于月份是唯一的。

验证器

Field.validators 该字段将要运行的一个Validator 的列表。

元信息Meta——使用内部的class Meta 定义模型的元数据

from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"

模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural)。

在模型中添加class Meta是完全可选的,所有选项都不是必须的。

关系字段

关系数据库的威力体现在表之间的相互关联。

Django 提供了三种最常见的数据库关系:多对一(manyto-one),多对多(many-to-many),一对一(one-to-one)。

  • 多对一关系

Django 使用 django.db.models.ForeignKey 定义多对一关系。和使用其它字段类型一样:在模型当中把它做为一个类属性包含进来。

ForeignKey 需要一个位置参数:与该模型关联的类。

limit_choices_to 当这个字段使用模型表单或者Admin 渲染时(默认情况下,查询集中的所有对象都可以使用),

为这个字段设置一个可用的选项。它可以是一个字典、一个Q 对象或者一个返回字典或Q对象的可调用对象。

        Q(caption='root')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据

related_name    这个名称用于让关联的对象反查到源对象。它还是related_query_name 的默认值(关联的模型进行反向过滤时使用的名称)。

related_query_name    这个名称用于目标模型的反向过滤。如果设置了related_name,则默认为它的值,否则默认值为模型的名称

to_field 关联到的关联对象的字段名称。默认地,Django 使用关联对象的主键。

db_constraint控制是否在数据库中为这个外键创建约束。默认值为True

on_delete 当一个ForeignKey 引用的对象被删除时,Django 默认模拟SQL 的ON DELETE CASCADE 的约束行为,并且删除包含该ForeignKey的对象。这种行为可以通过设置on_delete 参数来改变。

    CASCADE级联删除;默认值。

    PROTECT抛出ProtectedError 以阻止被引用对象的删除,它是django.db.IntegrityError 的一个子类。

    SET_NULL把ForeignKey 设置为null; null 参数为True 时才可以这样做。

    SET_DEFAULT ForeignKey值设置成它的默认值;此时必须设置ForeignKey 的default 参数。

    SET() 设置ForeignKey 为传递给SET() 的值,如果传递的是一个可调用对象,则为调用后的结果。
    DO_NOTHING不采取任何动作。如果你的数据库后端强制引用完整性,它将引发一个IntegrityError ,除非你手动添加一个ON DELETE 约束给数据库自动

ManyToManyField一个多对多关联。

要求一个关键字参数:与该模型关联的类,与ForeignKey 的工作方式完全一样,包括递归关系 和惰性关系。
关联的对象可以通过字段的RelatedManager 添加、删除和创建。

如果源模型和目标不同,则生成以下字段:

id:关系的主键。

<containing_model>_id:声明ManyToManyField 字段的模型的id。
<other_model>_id:ManyToManyField 字段指向的模型的id。

如果ManyToManyField 的源模型和目标模型相同,则生成以下字段:

id:关系的主键。
from_<model>_id:源模型实例的id。
to_<model>_id:目标模型实例的id。

这个类可以让一个给定的模型像普通的模型那样查询与之相关联的记录。

    to,                         # 要进行关联的表名
    related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
    related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
    limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
        # 如:
            - limit_choices_to={'nid__gt': 5}
            - limit_choices_to=lambda : {'nid__gt': 5}

            from django.db.models import Q
            - limit_choices_to=Q(nid__gt=10)
            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')

   symmetrical=None,# 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                # 做如下操作时,不同的symmetrical会有不同的可选字段
                    models.BB.objects.filter(...)
                    # 可选字段有:code, id, m1
                        class BB(models.Model):
                        code = models.CharField(max_length=12)
                        m1 = models.ManyToManyField('self',symmetrical=True)
                    # 可选字段有: bb, code, id, m1
                        class BB(models.Model):
                        code = models.CharField(max_length=12)
                        m1 = models.ManyToManyField('self',symmetrical=False)
        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
            from django.db import models
            class Person(models.Model):
                name = models.CharField(max_length=50)
            class Group(models.Model):
                name = models.CharField(max_length=128)
                members = models.ManyToManyField(
                    Person,
                    through='Membership',
                    through_fields=('group', 'person'),
                )
            class Membership(models.Model):
                group = models.ForeignKey(Group, on_delete=models.CASCADE)
                person = models.ForeignKey(Person, on_delete=models.CASCADE)
                inviter = models.ForeignKey(
                    Person,
                    on_delete=models.CASCADE,
                    related_name="membership_invites",
                )
                invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称

OneToOneField

一对一关联关系。概念上讲,这个字段很像是ForeignKey 设置了unique=True,不同的是它会直接返回关系另一边的单个对象。

它最主要的用途是作为扩展自另外一个模型的主键;例如,多表继承就是通过对子模型添加一个隐式的一对一关联关系到父模型实现的。

需要一个位置参数:与该模型关联的类。 它的工作方式与ForeignKey 完全一致,包括所有与递归关系和惰性关系相关的选项。

以下内容个人理解笔记:

class News(models.Model):
      title = models.CharField(max_length=10)
      favor = models.ManyToManyField('User',through="Favor",through_fields=("new_obj", 'user_obj'))
# obj = models.News.objects.get(id=1)
# v = obj.favor.all()
# print(v)
# obj.favor.add(1)不能用
# obj.favor.remove(1)不能用
# v = obj.favor.all()能用
# obj.favor.clear()能用,根据id删,不用name这个字段
# v = models.User.objects.all()
# v = models.User.objects.all().select_related('user_type')class User(models.Model):
      name = models.CharField(max_length=10)
      email = models.EmailField(max_length=10)
      user_type = models.ForeignKey('UserType') # 一对多
      # user_profile = models.ForeignKey('UserDetail',unique=True)
      user_profile = models.OneToOneField('UserDetail')
    class UserDetail(models.Model):
      pwd = models.CharField(max_length=32)
    class Favor(models.Model):
      new_obj = models.ForeignKey('News',related_name="n")
      user_obj = models.ForeignKey('User',related_name='u')
      name = models.CharField(max_length=64,null=True,blank=True)
    class UserType(models.Model):
      name = models.CharField(max_length=10)

访问外键(Foreign Key)值

python manage.py shell

当你获取一个ForeignKey 字段时,你会得到相关的数据模型对象。

>>> from django.db import connection
>>> from app01.models import User
>>> u=User.objects.get(id=1)
>>> u
<User: User object>
>>> u.user_type
<UserType: UserType object>
>>> u.user_type.name
'type1'

对于用ForeignKey 来定义的关系来说,在关系的另一端也能反向的追溯回来,
通过一个UserType对象,直接获取 user ,用 UserType.user_set.all() ,

实际上,user_set 只是一个 QuerySet(参考第5章的介绍),

所以它可以像QuerySet一样,能实现数据过滤和分切,属性名称user_set是由模型名称的小写加_set组成的。

>>> from app01.models import UserType
>>> t=UserType.objects.get(name='type1')
>>> t.user_set.all()
<QuerySet [<User: User object>, <User: User object>]>
  • 多对多

正向查找

>>> from app01.models import News
>>> n=News.objects.get(id=1)
>>> n.favor.all()
<QuerySet [<User: User object>, <User: User object>]>
>>> n.favor.filter(name='nu1')
<QuerySet [<User: User object>]>

反向查找

>>> u.news_set.all()
<QuerySet [<News: News object>]>

希望本文所述对大家基于Django框架的Python程序设计有所帮助。

Python 相关文章推荐
python删除列表中重复记录的方法
Apr 28 Python
Python随手笔记第一篇(2)之初识列表和元组
Jan 23 Python
python urllib urlopen()对象方法/代理的补充说明
Jun 29 Python
python自动查询12306余票并发送邮箱提醒脚本
May 21 Python
Python:Numpy 求平均向量的实例
Jun 29 Python
python利用re,bs4,requests模块获取股票数据
Jul 29 Python
Python调用钉钉自定义机器人的实现
Jan 03 Python
pytorch中的自定义数据处理详解
Jan 06 Python
Python pip install如何修改默认下载路径
Apr 29 Python
tensorflow从ckpt和从.pb文件读取变量的值方式
May 26 Python
python中pandas库中DataFrame对行和列的操作使用方法示例
Jun 14 Python
让文件路径提取变得更简单的Python Path库
May 27 Python
pycharm配置git(图文教程)
Aug 16 #Python
Django如何实现上传图片功能
Aug 16 #Python
Python如何调用JS文件中的函数
Aug 16 #Python
用Python批量把文件复制到另一个文件夹的实现方法
Aug 16 #Python
Python Web框架之Django框架cookie和session用法分析
Aug 16 #Python
python中hasattr()、getattr()、setattr()函数的使用
Aug 16 #Python
Python中IP地址处理IPy模块的方法
Aug 16 #Python
You might like
PHP函数getenv简介和使用实例
2014/05/12 PHP
PHP实现自动识别Restful API的返回内容类型
2015/02/07 PHP
Java中final关键字详解
2015/08/10 PHP
基于php实现随机合并数组并排序(原排序)
2015/11/26 PHP
Div Select挡住的解决办法
2008/08/07 Javascript
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
如何将一个String和多个String值进行比较思路分析
2013/04/22 Javascript
JavaScript实现iframe自动高度调整和不同主域名跨域
2016/02/27 Javascript
jQuery 获取屏幕高度、宽度的简单实现案例
2016/05/17 Javascript
浅谈JS继承_寄生式继承 &amp; 寄生组合式继承
2016/08/16 Javascript
js判断是否为空和typeof的用法(详解)
2016/10/07 Javascript
Bootstrap基本插件学习笔记之Alert警告框(20)
2016/12/08 Javascript
jqueryUI tab标签页代码分享
2017/10/09 jQuery
微信小程序实现即时通信聊天功能的实例代码
2018/08/17 Javascript
JS 实现获取验证码 倒计时功能
2018/10/29 Javascript
JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例
2018/12/14 Javascript
Vue3.x源码调试的实现方法
2019/10/13 Javascript
JS中数组实现代码(倒序遍历数组,数组连接字符串)
2019/12/29 Javascript
Python中获取网页状态码的两个方法
2014/11/03 Python
Django中使用locals()函数的技巧
2015/07/16 Python
实例介绍Python中整型
2019/02/11 Python
Python神奇的内置函数locals的实例讲解
2019/02/22 Python
PYTHON EVAL的用法及注意事项解析
2019/09/06 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
python可以用哪些数据库
2020/06/22 Python
Python 存取npy格式数据实例
2020/07/01 Python
python实现数字炸弹游戏程序
2020/07/17 Python
css3媒体查询中device-width和width的区别详解
2020/03/27 HTML / CSS
YOOX美国官方网站:全球著名的多品牌时尚网络概念店
2016/09/11 全球购物
维珍澳洲航空官网:Virgin Australia
2017/09/08 全球购物
总裁岗位职责
2013/12/04 职场文书
应届大学生自荐信
2013/12/05 职场文书
可贵的沉默教学反思
2014/02/06 职场文书
党支部换届选举方案
2014/05/08 职场文书
房地产经营管理专业自荐信
2014/09/02 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书