第十一章 ORM基础操作

1.orm的字段和参数

1.1 常用字段
1.AutoFiled 自增
  • 自增的整型字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django会自动创建主键

  • 一个model不能有两个AutoFiled字段。

2.intergerfield 整数
  • 不需要额外参数

  • 范围:-2147483648 ~ 2147483647

3.CharFiled 字符串
  • 必须提供 max_length参数,表示字符的最大长度

4. DateField
  • 日期类型,格式为YYYY-MM-DD,相当于python中的datetime.date的实例

  • 参数:

    • auto_now:修改时,时间自动改变

    • auto_now_add:创建时,自动添加当前时间(使用orm操作时有效)

    • 与default两两互斥,不能同时使用

5.DateTimeField
  • 日期时间字段,格式为YYYY-MM-DD HH:MM[:ss [.uuuuuu]] [TZ],相当于Python中的datetime.datetime的实例

    • python console —> Django console(测试使用)

# models.py
birth = models.DateTimeField(auto_now_add=True)

  auto_now_add=True    # 新增数据的时候会自动保存当前的时间,修改的时候不会变
    auto_now=True        # 新增、修改数据的时候会自动保存当前的时间
    auto_now_add和auto_now不能同时设置,是互斥的
#view.py
from app01 import models
obj = models.Person.objects.create(name='henry', age=19)

 

  • 修改时,只有相应字段会变化,auto_now会自动更新到当前时间

  • models中修改参数,在数据库中会生效

6. DecimalField(Field)
  • 10进制小数

  • 参数:

    • max_digits,小数总长度

    • decimal_places,小数位长度

7. FloatField()
  • 浮点型

8. 其他
  1. BoolenField(Field)

    • 存储bool值,可以使用在性别等(只有两种情况)

  2. TextField(Field)

    • null=True

  3. EmailField(CharField)

    • 存储到数据库之前,会校验格式

  4. BinaryField(Field)

    • 二进制类型

9. 自定义字段
  1. 重写init方法,一般都是通过*args和**kwargs传参

  2. 在框架中一般使用super(类,self),在加上自己的操作

  3. 定义db_type(self, connection)

# models.py
class MyCharField(models.Field):
    """自定义的char类型的字段类"""
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs)
         # 指定生成数据库字段的类型
    def db_type(self, connection):
        """限定生成数据库表的字段类型为char,长度为max_length指定的值"""
        return 'char(%s)' % self.max_length
  • 使用自定义字段
# models.py
class Test(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=20)
    # 使用自定义的char类型的字段,MyCharField为自定义的char
    cname = MyCharField(max_length=20)
1.2 字段参数(11)
1. null=True
# 默认null=False,表示数据存入时可以为空
cname = models.CharField(max_length=25, null=True)
2. blank=True
  • 前端页面上可以填入空值,实际上存入数据库的是空字符串

  • 创建admin账户

# django,admin 是否为空,创建时需要 enable admin 否则自己注册admin和添加url路径
console:
>>> python manage.py createsuperuser
>>> 用户名、emial、密码(8位,不能是纯数字)
  • 注册model类
# app的 admin.py 中
from django.contrib import admin
from . import models
# 注册,类
admin.site.register(models.Person)
# form表单,数据库最终存储空的字符串
cname = models.CharField(max_length=25, null=True, blank=True)
  • 多列显示
# admin.py
from django.contrib import admin
from rabc import models
class PermissionConf(admin.ModelAdmin):
      # 展示多列
      list_display = ['id', 'url', 'title']
    # 可编辑的
    list_editable = ['url', 'title']
admin.site.register(models.Permission, PermissionConf)

 

  • form表单填写时可以为空,可以不执行数据库迁移命令

3. db_column='new_name'
    • 指定数据库的字段名

    • db_column:列名

# 数据库的字段为username,表已经存在不修改字段名使用
name = CharField(max_length=25, db_column='username')
4. default='xxx'
  • 设置默认值

  • 添加新的字段时使用

gender = models.BooleanFiled(default=0)
5. primary_key=True
  • 指定主键

pid = models.AutoField(primary_key=True)

The primary key field is read-only. If you change the value of the primary 
key on an existing object and then save it, a new object will be created alongside
the old one.
# 主键字段只能读取,不能修改,一旦修改,django会默认创建一个新的对象
6. db_index=True
  • 给当前字段添加索引

age = models.IntegerField(db_index=True)
7. unique=True
  • 唯一约束

name = models.CharField(max_length=32, unique=True)
8. 与admin相关(5)
  • verbose_name

  • '提示'(改变amdin中前端显示)

name = models.CharField(max_length=32, verbose_name='姓名')
  • editable=False(不能编辑,admin不会显示到前端)
# null 和 blank 一般成对出现
addr = models.CharField(max_length=50, null=True, blank=True,
verbose_name='地址', editable=True)
  • help_text='不要写乳名'
name = models.CharField(max_length=32, 
                        verbose_name='姓名', 
                        help_text='xxx')
  • choices((0, 'female'), (1, 'male'))

  • 参数使用list或tuple类型数据

# select框,(数据库存储的数据,'前端显示')
# choices参数需要使用 tuple 嵌套tuple 进行设定
class Peroson(models.Model):
    gender = models.BooleanField('性别',choices=((0,'female'),(1, 'male')))


class Test(models.Model):
    gender_list = (('0', 'female'), (1, 'male'),)
    gender = models.CharField(max_length=1, choices=gender_list)
>>> from app01 import models
>>> p = models.Test()
>>> p.gender='0'
>>> p.get_gender_display()
'female'

2. Model Meta(6)

  • **表的参数

class Person(models.Model):
    pid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=18)
    class Meta:
          # 设置默认排序
        ordering = ('pk',...)      # 此处有坑,请谨慎驾驶
        # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
        db_table = "person"
        # admin中显示的表名称,此时在主页面上会显示‘个人信息s’
        verbose_name = '个人信息'
        # verbose_name_plural和 verbose_name 一般成对使用
        verbose_name_plural = '所有用户信息'
        # 联合索引 
        index_together = [ ("name", "age"), ]  # 应为两个存在的字段
        # 联合唯一索引
        unique_together = (("name", "age"),)   # 应为两个存在的字段

3. ORM操作(13)

3.1 orm_test
  • 测试文件准备

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','orm_practice.settings')
import django
django.setup()
# models导入必须在setup之后
from app01 import models
3.2 orm操作
  1. 返回对像列表(8)

    • all/filter/exclude/values/values_list/order_by/reverse/disctinct

  2. 返回对象(3)

    • get/first/last

  3. 返回bool值(1)

    • exists

  4. 返回数字(1)

    • count

# orm操作
# 获取所有对象
1.obj = models.Person.objects.all()
# 获取一个对象
2.obj = models.Person.objects.get(pk=1)
# 获取满足条件的所有数据,QuerySet类型,查询不到为[ ]
3.obj = models.Person.objects.filter(age=18)
# 获取 不 满足条件的所有数据
4.obj = models.Person.objects.exclude(age=18)
# 获取所有字段和字段值,QuerySet类型(里面嵌套dict), 参数不写默认所有
# 按照指定的顺序获取
5.obj = models.Person.objects.values(字段名1, 字段名2...)
# 获取所有 字段值 ,QuerySet类型(里面嵌套tuple), 参数不写默认所有
# 按照指定的顺序获取
6.obj = models.Person.objects.values_list(字段名1, 字段名2...)
# 默认生序排序, -pk 表示降序排序,可以指定多个字段
7.obj = models.Person.objects.all().order_by('age', '-pk')
# 反转, 前提是排好序的
8.obj = models.Person.objects.all().order_by('pk').reverse()
# 去重,内容完全相同可以去重,受默认排序影响,不支持字段去重
9.obj = models.Person.objects.values('age').distinct()
# 计数
10.obj = models.Person.objects.all().count()
# first/last, 没有则是None, 取第一/最后一个元素,没有则为None
11.obj = models.Person.objects.all/filter().first()
12.obj = models.Person.objects.values().first()
# exists,判断查询的数据是否存在,必须是QuerySet
13.obj = models.Person.objects.get(pk=1).exists()

4. 双下线方法(8)

  • 在单表中,提供范围查找的方法

  • 字段__双下方法

4.1 __gt/lt= 大于/小于
# gt greater than, 大于2
obj = models.Person.objects.filter(pk__gt=2)
# lt, 小于2
obj = models.Person.objects.filter(pk__lt=2)
4.2 __gte/lte= 大于等于/小于等于
# gte/lte, 大于等于/小于等于
obj = models.Person.objects.filter(pk__gte=2)
4.3 __range=[1,3]
# 组合,或者range,闭区间
obj = models.Person.objects.filter(pk__gte=2,pk__lt=3)
obj = models.Person.objects.filter(pk__range=[2,3])
4.4 __in=[1,3]
# in,条件判断,符合list中条件的
obj = models.Person.objects.filter(pk__in=[1, 3])
4.5 __contains='h'
  • __icontains

# contains='xxx',区分大小写, __icontains='h',忽略大小写
obj = models.Person.objects.filter(name__contains='h')
4.6 __startswith/endswith
  • __istartswith/iendswith

# startswith='h', 和 __istartswith='' / endswith
obj = models.Person.objects.filter(name__startswith='h')
4.7 __year='2019'
# 筛选年份,不支持月和日
obj = models.Person.objects.filter(birth__year='2019')
obj = models.Person.objects.filter(birth__contains='2019-06')
4.8 __isnull=True
  • 查询字段可为空的

obj = models.Person.objects.filter(birth__isnull=True)

5. Foreign Key

from django.db import models
class Publisher(models.Model):
   name = models.CharField(max_length=32)
    
class Book(models.Model):
   title = models.CharField(max_length=32)
   pub = models.ForeignKey('Publisher', related_name='books' ,on_delete=models.CASCADE)
5.1 基于对象的查询
  • related_name

# Book --> Publisher:正向查询
book_obj = models.Book.objects.get(pk=1).pub
  • 反向查询
# 反向查询
pub_obj = models.Publisher.objects.get(pk=1)
# 关联的 类名小写_set,set集合,pub_obj必须唯一
pub_obj.book_set        # 关系管理对象
pub_obj.book_set.all()  # 关联的所有书籍
# 指定 realated_name进行反向查询名称
pub_obj.books.all()     # 关联的所有书籍
5.2 基于字段查询
  • relate_query_name

  • relate_query_name默认值为related_name

  • __字段名:常用于反向的多对多查询

# 表示跨表查找出版社name
book_obj = models.Book.objects.filter(pub__name='人民出版社')
  • 反向查询
# 指定related_name=books,查询指定书的出版社
pub_obj = models.Publisher.objects.filter(books__title='python之旅')
# 不指定related_name,查询指定书的出版社,使用类名小写
pub_obj = models.Publisher.objects.filter(book__title='python之旅')

# 指定related_name=books,related_query_name='xxx',查询指定书的出版社
pub_obj = models.Publisher.objects.filter(xxx__title='python之旅')

 

 

posted @ 2020-05-28 15:35  炜琴清  阅读(211)  评论(0编辑  收藏  举报