Django:ORM单表操作

  ORM,实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖特定的数据库,通过简单的配置,就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变动而导致的无效劳动

ORM是 对象-关系-映射 的简称:object relational mapping

类对象--->sql---->pymysql---->mysql服务端---->磁盘,ORM就是将类对象的语法翻译成sql语句的一个引擎

原生sql和python的orm代码对比

#sql中创建表
create table empluyee(
    id int primary key auto_increment,
    name varchar(20),
    gender bit default 1,
    birthday data,
    department varchar(10),
    salary decimal(8,2) unsigned,
)
# 添加表记录
insert employee (name,gender,birthday,salary,department) values ('alex',1,'1977-12-12',4000,'cleaning');

#查询表记录
select * from employee where name='alex';

#更新表记录
update employee set birthday='1966-01-01' where name='alex';

#删除表记录
delete from employee where name='alex';

#Django中models.py
class Employee(models.Model):
    id = models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    gender=models.BooleanField()
    birthday=models.DateField()
    department=models.CharField(max_length=32)
    salary=models.DecimalField(max_digits=8,decimal_places=2)
#python的类对象
emp=Employee(name='alex',gender=True,birthday='1981-01-01',department='cleaning')
emp.save()
#查询一条表记录
Employee.objects.filter(age=24)
#更新一条表记录
Employee.objects.filter(id=1).update(birthday='1982-02-02')
#删除一条表记录
Employee.objects.filter(id=1).delete()

在pycharm用连接mysql

1.在项目settings.py中修改DATABASES
    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST':'127.0.0.1',            
        'PORT':3306,
        'NAME':'ormtest',    # 要连接的mysql库名
        'USER':'root',
        'PASSWORD':'123456',
        }
    }
2.在项目__init__.py中
    import pymysql
    # MySQLdb()是Django用来连接mysql数据的工具,这里用pymysql代替MySQLdb
    pymysql.install_as_MySQLdb()

3.在应用文件夹中models.py中写入创建数据的类
    class UserInfo(models.Model):
    #create table userinfo(id int primary key auto_increment,
    # name varchar(16),age int,current_date date)
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=16)
        age = models.IntegerField()
        current_date = models.DateField()

4.在命令行(Terminal)中输入命令
    python manage.py makemigrations    # 创建一条记录,数据库操作的记录
    python manage.py migrate        # 连接数据库,并按model.py中写类来生成表,以及生成django自带的表

外部文件使用models.py

在Django中可以用外部的py文件操作models.py,来操作数据库
1.在项目下创建 xx.py文件,写入代码
# 外部文件使用jdango的models,需要配置jdango环境

import os

if __name__ == '__main__':
    os.enveron.setdefault("DJANGO_SETTINGS_MODULE","ormhw.settings")
    import django                                #  项目名称  settings.py
    django.setup()
    from app01 import models
    
    obj_lst = []
    
    for i in range(1,10):
        obj = models.Books(
            title = 'python%s'%i,
            price = 120+i,
            pub_date = '101%s-10-10'%i,
            publish = 'beida' if i<5 else 'tsinghua'
        )
        obj_lst.append(obj)
    models.Books.objects.bulk_create(obj_lst)
2.直接运行xx.py 文件,就可以执行代码,对数据库做操作

Django项目通过浏览器admin后台管理数据库

# 在app 中的admin.py中添加需要管理的类,即创建的表
from django.contrib import admin
from app01 import models
# Register your models here.

admin.site.register(models.Book)

#在pycharm terminal中输入命令
python manage.py createsuperuser

#接着输入username/password,email可以不用输入,直接回车

#运行项目,在浏览器上输入127.0.0.1:8000/admin
#输入用户名密码即可管理添加的数据库表了

数据库相关字段

'''
1.CharField    
    字符串字段,必须要有一个参数:max_length
2.IntergerField  
    保存一个整数
3.DecimalField   
    一个浮点数,必须提供两个参数:max_digits 总位数,decimal_places 小数位数
4.AutoField     
    表示一个自增字段
5.BooleanField  
    A true/false field.admin 用 checkbox 来表示此类字段
6.TextField
    一个容量很大的文本字段
    admin用一个<textarea>表示该字段数据
7.EmailField
    一个带有检查Email合法性的 CharField,不接受  max_length参数
8.DateField
    日期字段,有下列额外的可选参数
    Argument    描述
    auto_now    对象被保存时,自动将该字段的值设置为当前时间,通常用于表现通常用于表示 "last-modified" 时间戳.
    auto_now_add  当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        (仅仅在admin中有意义...)
9.DateTimeField
    时间字段,类似DateField支持同样的附加选项
10.ImageField
    类似FileField,不过要校验上传对象是否是一个合法图片,它有两个可选参数:height_field和width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存. 
11.FileField
    文件上传字段
    必须要有的参数:upload_to,用于保存上传文件的本地文件系统路径。这个路径必须包含 strftime #formatting,该格式将被上载文件的 date/time
     替换(so that uploaded files don't fill up the given directory).
     admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件)
12.URLField
    用于保存URL,若verify_exists参数为True,给定的URL会预先检查是否存在( 即URL是否被有效装入且
      没有返回404响应).
    admin用一个<input type='text'>文本框表示该字段保存的数据
13.NullBooleanField
    类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
    admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.
14.SlugField
15.XMLField
    一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
16.FilePathField
17.IPAaddressField
    一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
'''

更多的参数

'''
1.null
    如果为True ,Django将用NULL来在数据库存储空值,默认值是false
2.blank
    如果为True,该字段允许不添,默认为false
    这与null不同,null纯粹是数据库范畴的,blank是数据验证范畴的
    如果一个字段blank=True,表单的验证将允许该字段为空值,如果blank=false,该字段就必须有值
3.default
    字段的默认值,可以是一个值或者可调用对象。如果可调用,每有新对象被创建它都会被调用,如果你的字段没有设置为可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
    
4.primary_key
    如果为True,那么这个字段就是模型的主键。如果没有指定任何一个字段的primary_key=True,Django就会自动添加一个IntegerField字段作为主键,所以除非你想覆盖默认的主键行为,否则抹油必要设置一个字段的primary_key=True

5.unique
    如果设置值为True,这个数据字段的值在整张表中必须是唯一的

6.choices
    由二元组组成一个可迭代对象,用来给字段提供选择项。如果设置choices,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices中的选项
    
7.db_index
    如果db_index=True,则代表将此字段设置为数据库索引
    
8.DatetimeField  DateField  TimeField 这三个时间段,都可以设置如下属性
    auto_now_add
        配置auto_now_add=True,创建数据记录的时候,会把当前时间添加到数据库
    auto_now
        配置auto_now=True,每次更新数据记录都会跟新该字段,标识这条记录的最后一次的修改时间
    
    
'''

ORM字段与mysql数据库实际字段的对应关系

'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',

添加表记录

python中 orm 的对应关系有三种

类 ----------------->表

类对象------------->行(表记录)

类属性------------->表字段

首先想要操作表的增删改查,需要先导入这个表

# views.py中导入需要操作的表
from app01 import models

def index(request):
    '''
    添加表记录,等数据库操作
    '''
    obj=models.Book(title='python',price='120',pubdate='2019-10-10',publish='人民出版社')
    obj.save()
    
    
# create 方法插入数据,返回的是object对象
    obj=models.Book。objects.create(title='python',price='120',pubdate='2019-10-10',publish='人民出版社')
    print(obj.title)

    
# 批量创建
    objs = []
    for i in range(20):
        obj = models.UserInfo(
            name='alex%s'%i,
            age = 20 + i,
            current_date='1990-01-01'
        )
         objs.append(obj)
    models.UserInfo.objects.bulk_create(objs)
    

# 创建方法:updata_or_create,有就更新,没有就创建
    models.UserInfo.objects.update_or_create(
        name='wusir111',
        defaults={
            'age':35,
            'current_date':'1982-03-03'
        }
    )

查询表记录

# 简单查询,获取所有对象,即表记录以对象的形式返回,queryset
all_objs = models.UserInfo.objects.all()
print(all_objs) #<QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
    for obj in all_objs:
        print(obj.name)
        
# filter(**kwargs) 条件查询,查询不到内容,不会报错,返回空 queryest
    objs = models.UserInfo.objects.filter(id=1)
    print(objs) # <QuerySet [<UserInfo: aliex>]>

    objs1 = models.UserInfo.objects.filter(name = 'wusir')
    print(objs1)    # <QuerySet [<UserInfo: wusir>]>
    
# get(**kwargs),返回的是model对象,有且只有一个结果。如果没有会报错,有多条记录也会报错
    obj = models.UserInfo.objects.get(id = 3)
    print(obj)  # aliex
     
    # obj = models.UserInfo.objects.get(name='jackma')
    # print(obj)  # 查询记录有多条或者没有的时候报错 get() returned more than one UserInfo -- it returned 2!
    
# order_by(*field) queryset类型的数据来调用,对查询的结果排序,默认按照id来升序的,返回值还是queryset类型
    query = models.UserInfo.objects.all().order_by('age','-id')
    print(query)  # 按照age从小到大排序,age相同的记录按照id 从大到小排序

# reverse()   queryset类型的数据调用,对返回结果进行反向排序,返回值还是queryset类型
    query = models.UserInfo.objects.all().order_by('id').reverse()
    print(query)  # 返回queryset类型
    
# count()     queryset类型的数据调用,返回数据库中匹配查询到的数量
    num = models.UserInfo.objects.all().count()
    print(num)
    
# first()     queryset类型的数据调用,返回第一条记录,得到的是model对象
# first()     queryset类型的数据调用,返回最后一条记录,得到的是model对象
    fobj = models.UserInfo.objects.all().first()
    lobj = models.UserInfo.objects.all().last()
    
# exists()    queryset类型的数据调用,如果queryset包含数据,则返回True,否则返回False
    obj = models.UserInfo.objects.filter(id=50).exists()
    print(obj)
    
 # values 返回queryset类型数据,元素是dick类型
    query = models.UserInfo.objects.filter(id__gt=25).values()   # 查询id>25的结果
    print(query)  #<QuerySet [{'id': 26, 'name': 'wusir111', 'age': 35, 'current_date': datetime.date(1982, 3, 3)}]>
    
# value_list  返回queryset类型数据,元素列表里面套元祖
    query = models.UserInfo.objects.filter(id__gt=25).values_list()   # 查询id>25的结果
    print(query)    # <QuerySet [(26, 'wusir111', 35, datetime.date(1982, 3, 3))]>
    
#distinct 去重,values 和 values_list 得到的queryset类型的数据来调用

基于双下划线的模糊查询

Book.objects.filter(price_in=[110,220,210]) # 查询price值等于这三个里面任意一个的对象,返回所有符合条件的对象
Book.objects.filter(price_gt=100)    # price大于100的对象。大于等于price_gte
Book.objects.filter(price_lt=100)    # price小于100的对象。小于等于price_lte
Book.objects.filter(price_range=[100,200])#相当于sql 的between and,大于等于100,小于等于200
Book.objects.filter(title_contains='python')# title中包含python的
Book.objects.filter(title_icontains='python')# 不区分大小写
Book.objects.filter(title_startswith='py')# 以什么开头,不区分大小写
Book.objects.filter(pub_date__year=2012)

all_books=models.Book.objects.filter(pub_date__year=2012)# 找2012年所有的书
all_books=models.Book.objecs.filter(pub_date__year__gt=2012)#找大于2012年所有的书籍

删除表记录

# delete()方法的调用者可以是一个model对象,也可以是一个queryset集合。它立即执行删除对象,没有返回值

obj.delete()

# 也可以一次删除多个对象,每个Queryset都有一个delete方法,它一次性删除queryset中的所有对象
models.Book.objects.filter(pub_date__year=2012).delete()#删除2015年的所有书籍

    models.UserInfo.objects.get(id=3).delete()  # 删除id=3 的记录
    models.UserInfo.objects.filter(name='jackma').delete()  # 删除 name='jackma'的所有记录
    models.UserInfo.objects.all().delete()  # 删除所有

修改表记录

# 更新 update()方法,model对象不能调用更新方法,只能queryset调用
   models.UserInfo.objects.filter(name='wusir').update(age=3)

update()方法对于任何结果集(queryset)均有效,这意味着你可以同时更新多条记录,update()方法会返回一个整形数值,表示受影响的记录条数

原文地址:https://www.cnblogs.com/jmuchen/p/13434022.html