Django 之 ORM 基础

来源:互联网 发布:双机热备 数据库 编辑:程序博客网 时间:2024/06/05 10:23

转载自:bobo0609

ORM 即 关系对象映射 ( Object Relational Mapping)


两种方式:
1、DB first
2、Code first(主流)


基本步骤

创建类  app01/models.py

from django.db import models    class UserInfo(models.Model):        username = models.CharField(max_length=32)    password = models.CharField(max_length=64)

注册APP  proj/settings.py

INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'app01',]
修改数据库引擎 settings.py 
django默认使用sqlite 数据库,如需修改为其他数据库存储数据需修改数据库引擎,如 MySQL :

DATABASES = {    'default': {    'ENGINE': 'django.db.backends.mysql',    'NAME':'dbname',    'USER': 'root',    'PASSWORD': 'xxx',    'HOST': '',    'PORT': '',    }}    

PS: Django默认使用MySQLdb模块链接MySQL,但python3中还无此模块,所以需要使用pymysql来代替,在project同名文件夹下的__init__文件中添加如下代码:
  import pymysql 
  pymysql.install_as_MySQLdb()

执行命令
python manage.py makemigrations    # 找到所有的models.py, 在相应的migrations下生成 000x_initial.py 文件,记录数据库变化
python manage.py migrate    # 根据000x_initial.py 文件,生成数据库表.

# 如果在model.py中修改了类,重新执行以上命令from django.db import models    class UserInfo(models.Model):        username = models.CharField(max_length=32)    password = models.CharField(max_length=64)            email = models.CharField(max_length=60,null=True)  # 增加列时不允许为空,需添加null=True,否则报错 

根据类自动创建数据库表 -- models.py


字段类型

字符串类型
CharField() # 字符类型 
  -参数:  必须提供max_length参数, 表示字符长度 如 CharField(max_length=10)
TextField() 文本类型
EmailField()   # Django Admin以及ModelForm中提供验证机制
IPAddressField()    # Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)    # Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 (推荐)
URLField()   # Django Admin以及ModelForm中提供验证 URL
SlugField()   # Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
FilePathField()    # Django Admin以及ModelForm中提供读取文件夹下文件的功能
  - 参数:
    path, 文件夹路径
    match=None, 正则匹配
    recursive=False, 递归下面的文件夹
    allow_files=True, 允许文件
    allow_folders=False, 允许文件夹
  PS: EmailField、GenericIPAddressField、URLField等仅给django-admin使用时才有特殊功能,如果不用admin,和CharField一样都表示普通字符串

数字类型
整型
  IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647
  PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647
  SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 
  BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

浮点型
  FloatField(Field)
  DecimalField(Field) # 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)  # 二进制类型

布尔值
BooleanField(Field)  - 布尔值类型
NullBooleanField(Field)  - 可以为空的布尔值
* 自定义自增列 (当model中如果没有自增列,则自动会创建一个列名为id的列)
  AutoField(primary_key=True) 必须填入参数  primary_key=True

时间类型
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) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

字段属性
null    -> db是否可以为空
default    -> 默认值
primary_key   -> 主键
db_column='xxx'   -> 列名
db_index=True   -> 索引
unique    -> 唯一索引
unique_for_date    ->  数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month  ->  数据库中字段【月】部分是否可以建立唯一索引
unique_for_year    ->  数据库中字段【年】部分是否可以建立唯一索引
auto_now_add   ->  创建时,自动生成时间
auto_now   ->  更新时,自动更新为当前时间
choices   ->  django admin中显示下拉框,避免连表查询(连表查询效率低)
blank   -> django admin是否可以为空
verbose_name    -> django admin显示字段中文
editable   -> django admin是否可以被编辑
error_messages    -> django admin 错误信息(欠)
help_text   -> django admin 提示

validators   -> django form 自定义错误信息(欠)

示例:

from django.db import models# Create your models here.class UserInfo(models.Model):     #  生成的表名称为app01_userinfo    #  会自动创建id列(自增,主键)       username = models.CharField(max_length=32,blank=True,verbose_name='用户名')        # 用户名列,字符串类型,指定长度    password = models.CharField(max_length=60, help_text='pwd')     email = models.EmailField(max_length=19,null=True,error_messages={'invalid': '请输入邮箱'}    caption = models.CharField(max_length=32,unique=True)    user_type_choices = ((1, '超级用户'), (2, '普通用户'),(3, '临时用户'),)   # 保存在内存中    user_type_id = models.IntegerField(choices=user_type_choices,default=1)    ctime = models.DateTimeField(auto_now_add=True, null=True)    mtime = models.DateTimeField(auto_now=True, null=True)     '''     方式一: mtime 时间不会更新     obj=UserInfo.objects.filter(id=1).update(caption='CEO')     方式二: mtime 时间会更新     obj=UserInfo.objects.filter(id=1).first()     obj.caption = 'CEO'     obj.save()     '''

根据类对数据库表中的数据进行各种操作   -- views.py

from app01 import modelsdef orm(request):    # 增    models.UserInfo.objects.create(username='root',password='123')    dic = {'username': 'xxx', 'password': '666'}    models.UserInfo.objects.create(**dic)    obj = models.UserInfo(username='alex',password='123')    obj.save()    # 查    result = models.UserInfo.objects.all()    result = models.UserInfo.objects.filter(username='root',password='123')    print(result)  #结果为Django的QuerySet类型 <QuerySet [<UserInfo: UserInfo object>,<UserInfo: UserInfo object>,<UserInfo: UserInfo object>]>    for row in result:        print(row.id,row.username,row.password)    dic = {'name': 'xxx', 'age_gt': '19'}    models.User.objects.filter(**dic)    # 删    models.UserInfo.objects.filter(id=4).delete()    # 改    models.UserInfo.objects.filter(id=3).update(password="69")

# models.tb.objects.filter(id__gt=1) => select * from tb where id > 1 
# models.tb.objects.filter(id__gte=1) => select * from tb where id >= 1 
# models.tb.objects.filter(id=1) => select * from tb where id = 1 
# models.tb.objects.filter(id__lt=1) => select * from tb where id < 1 
# models.tb.objects.filter(id__lte=1) => select * from tb where id <= 1 


外键约束 .

ForeignKey("PrimaryTable",to_filed='xxx')

from django.db import models# Create your models here.class UserGroup(model s.Model):    uid = models.AutoField(primary_key=True)  #自定义自增列,必须声明primary_key=True    caption = models.CharField(max_length=32,unique=True)class UserInfo(models.Model):     username = models.CharField(max_length=32,blank=True,verbose_name='用户名')         password = models.CharField(max_length=60, help_text='pwd')      email = models.CharField(max_length=60)    user_group = models.ForeignKey("UserGroup",to_field='uid',default=1)     # default=1 表示默认属于哪个部门,django在数据库中将user_group存取字段为user_group_id,实际上user_group为UserGroup的对象封装了(uid,caption,ctime,uptime)
from app01 import modelsdef orm(request):    models.UserInfo.objects.create(    username='root1',    password='123',    email="xxx.@qq.com",    user_group = models.UserGroup.objects.filter(id=1).first() # 或 user_group_id = 1 (推荐)     )    user_list = Userinfo.objects.all()    for row in user_list:         print(row.user_group) #这里 user_group代指 UserGroup 对象        print(row.user_group.id)  # 等同于 print(row.user_group_uid)        print(row.user_group.caption)  

示例:用户管理

urls.py

from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [    url(r'^login/', views.login),    url(r'^index/', views.index),    url(r'^user_info/', views.user_info),    url(r'^userdetail-(?P<nid>\d+)/', views.user_detail),    url(r'^userdel-(?P<nid>\d+)/', views.user_del),    url(r'^useredit-(?P<nid>\d+)/', views.user_edit),]

view.py

from django.shortcuts import render,HttpResponse,redirectdef login(request):    models.UserGroup.objects.create(caption='DBA')    if request.method == "GET":        return render(request, 'login.html')    elif request.method == "POST":        # 数据库中执行 select * from user where usernam='x' and password='x'        u = request.POST.get('user')        p = request.POST.get('pwd')        # count = models.UserInfo.objects.filter(username=u, password=p).count()        obj = models.UserInfo.objects.filter(username=u, password=p).first()           if obj:                return redirect('/cmdb/index/')        else:            return render(request, 'login.html')    else:         # PUT,DELETE,HEAD,OPTION...        return redirect('/index/')def index(request):     return render(request, 'index.html')def user_info(request):    if request.method == "GET":        user_list = models.UserInfo.objects.all()  # print(user_list.query)        group_list = models.UserGroup.objects.all()        return render(request, 'user_info.html', {'user_list': user_list, "group_list": group_list})    elif request.method == 'POST':        u = request.POST.get('user')        p = request.POST.get('pwd')        models.UserInfo.objects.create(username=u,password=p)        return redirect('/cmdb/user_info/')def user_detail(request, nid):    obj = models.UserInfo.objects.filter(id=nid).first()    # models.UserInfo.objects.get(id=nid)  # 取单条数据,但如果不存在则报错    return render(request, 'user_detail.html', {'obj': obj})def user_del(request, nid):    models.UserInfo.objects.filter(id=nid).delete()    return redirect('/cmdb/user_info/')def user_edit(request, nid):    if request.method == "GET":        obj = models.UserInfo.objects.filter(id=nid).first()        return render(request, 'user_edit.html',{'obj': obj})    elif request.method == "POST":        nid = request.POST.get('id')        u = request.POST.get('username')        p = request.POST.get('password')        models.UserInfo.objects.filter(id=nid).update(username=u,password=p)        return redirect('/cmdb/user_info/')

index.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        body{            margin: 0;        }        .menu{            display: block;            padding: 5px;        }    </style></head><body>    <div style="height: 48px;background-color: black;color: white">        Deployment    </div>    <div>        <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;">            <a class="menu" href="/cmdb/user_info/">用户管理</a>            <a class="menu" href="/cmdb/user_group/">用户组管理</a>        </div>        <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">        </div>    </div></body></html>

user_info.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        body{            margin: 0;        }        .menu{            display: block;            padding: 5px;        }    </style></head><body>    <div style="height: 48px;background-color: black;color: white">        Deployment    </div>    <div>        <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;">            <a class="menu" href="/cmdb/user_info/">用户管理</a>            <a class="menu" href="/cmdb/user_group/">用户组管理</a>        </div>        <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">            <h3>添加用户</h3>            <form method="POST" action="/cmdb/user_info/">                <input type="text" name="user" />                <input type="text" name="pwd" />                <select name="group_id">                    {% for item in group_list %}                        <option value="{{ item.uid }}">{{ item.caption }}</option>                    {% endfor %}                </select>                  <input type="submit" value="添加"/>            </form>            <h3>用户列表</h3>            <ul>                {% for row in user_list %}                    <li>                        <a href="/cmdb/userdetail-{{ row.id }}/">{{ row.username }}</a>                         <span> {{ row.user_group.caption }} </span>                        <a href="/cmdb/userdel-{{ row.id }}/">删除</a> |                        <a href="/cmdb/useredit-{{ row.id }}/">编辑</a>                    </li>                {% endfor %}            </ul>        </div>    </div></body></html>

user_detail.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        body{            margin: 0;        }        .menu{            display: block;            padding: 5px;        }    </style></head><body>    <div style="height: 48px;background-color: black;color: white">        Deployment    </div>    <div>        <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;">            <a class="menu" href="/cmdb/user_info/">用户管理</a>            <a class="menu" href="/cmdb/user_group/">用户组管理</a>        </div>        <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">            <h1>用户详细信息</h1>            <h5>{{ obj.id }}</h5>            <h5>{{ obj.name }}</h5>            <h5>{{ obj.password }}</h5>        </div>    </div></body></html>

user_edit.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        body{            margin: 0;        }        .menu{            display: block;            padding: 5px;        }    </style></head><body>    <div style="height: 48px;background-color: black;color: white">        Deployment    </div>    <div>        <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;">            <a class="menu" href="/cmdb/user_info/">用户管理</a>            <a class="menu" href="/cmdb/user_group/">用户组管理</a>        </div>        <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">            <h1>编辑用户</h1>            <form method="post" action="/cmdb/useredit-{{ obj.id }}/">                <input style="display: none" type="text" name="id" value="{{ obj.id }}" />                <input type="text" name="username" value="{{ obj.username }}" />                <input type="text" name="password" value="{{ obj.password }}"/>                <input type="submit" value="提交" />            </form>        </div>    </div></body></html>