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命令行解析之parse_known_args()函数和parse_args()使用区别介绍
Jan 24 Python
深入浅析python 中的匿名函数
May 21 Python
Python 2.7中文显示与处理方法
Jul 16 Python
Python实现查找数组中任意第k大的数字算法示例
Jan 23 Python
详解python执行shell脚本创建用户及相关操作
Apr 11 Python
Python 循环终止语句的三种方法小结
Jun 24 Python
利用python计算时间差(返回天数)
Sep 07 Python
学Python 3的理由和必要性
Nov 19 Python
Python 解决OPEN读文件报错 ,路径以及r的问题
Dec 19 Python
Python turtle库的画笔控制说明
Jun 28 Python
python实现简易名片管理系统
Apr 11 Python
Python Django / Flask如何使用Elasticsearch
Apr 19 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
smarty section简介与用法分析
2008/10/03 PHP
PHP开发规范手册之PHP代码规范详解
2011/01/13 PHP
解决FastCGI 进程超过了配置的活动超时时限的问题
2013/07/03 PHP
PHP图像裁剪缩略裁切类源码及使用方法
2016/01/07 PHP
Zend Framework框架实现类似Google搜索分页效果
2016/11/25 PHP
jQuery在iframe中无法弹出对话框的解决方法
2014/01/12 Javascript
JS获取IMG图片高宽的简单实例
2016/05/17 Javascript
原生js三级联动的简单实现代码
2016/06/07 Javascript
jquery之别踩白块游戏的简单实现
2016/07/25 Javascript
详解使用vue实现tab 切换操作
2017/07/03 Javascript
.vue文件 加scoped 样式不起作用的解决方法
2018/05/28 Javascript
json数据传到前台并解析展示成列表的方法
2018/08/06 Javascript
Vue一个案例引发的递归组件的使用详解
2018/11/15 Javascript
一个因@click.stop引发的bug的解决
2019/01/08 Javascript
vue操作动画的记录animate.css实例代码
2019/04/26 Javascript
Vue axios获取token临时令牌封装案例
2020/09/11 Javascript
Python yield 小结和实例
2014/04/25 Python
pymongo为mongodb数据库添加索引的方法
2015/05/11 Python
python自动翻译实现方法
2016/05/28 Python
python 实现数组list 添加、修改、删除的方法
2018/04/04 Python
PyCharm专业最新版2019.1安装步骤(含激活码)
2019/10/09 Python
基于Python脚本实现邮件报警功能
2020/05/20 Python
keras的siamese(孪生网络)实现案例
2020/06/12 Python
美国最便宜的旅游网站:CheapTickets
2017/07/09 全球购物
英国男士时尚网站:Dandy Fellow
2018/02/09 全球购物
AURALog面试题软件测试方面
2013/10/22 面试题
同步和异步有何异同,在什么情况下分别使用他们
2013/04/09 面试题
企业管理培训感言
2014/01/27 职场文书
致长跑运动员广播稿
2014/01/31 职场文书
我为党旗添光彩演讲稿
2014/09/13 职场文书
四查四看整改措施
2014/09/19 职场文书
工作证明英文模板
2014/10/21 职场文书
党的群众路线教育实践活动个人对照检查材料(医生)
2014/11/05 职场文书
工作期间打牌检讨书范文
2014/11/20 职场文书
公司辞职信模板
2015/05/13 职场文书
如何判断pytorch是否支持GPU加速
2021/06/01 Python