Django基础——Model篇(一)
到目前为止,当程序涉及到数据库相关操作时,我们一般都会这么操作:
(1)创建数据库,设计表结构和字段
(2)使用MySQLdb来连接数据库,并编写数据访问层代码
(3)业务逻辑层去调用数据访问层,执行数据库操作
import MySQLdb def GetList(sql):
db = MySQLdb.connect(user='root', db='mydb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchall()
db.close()
return data def GetSingle(sql):
db = MySQLdb.connect(user='root', db='mydb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchone()
db.close()
return data
python操作数据库
Django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。Django遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。Django是通过Model类来操作数据库的,程序员不需要关注SQL语句和数据库的类型(无论数据库是MySql、Sqlite,还是其它类型),Django自动生成相应数据库类型的SQL语句,来完成对数据库数据的操作。
一 创建数据库
当我们在已经创建的Django工程中创建app时(假设app的名称为app01),那么在app01模块下默认会生成models.py文件,这个就是Django工程中操作数据库的文件。
1 创建数据库Model类(models.py文件)
#/usr/bin/env python
#-*- coding:utf-8 -*- from __future__ import unicode_literals
from django.db import models # Create your models here. # ORM模型
# 类 -> 数据库表
# 对象 -> 表中的每一行数据
# 对象.id,对象.value -> 每行中的数据
#这个类是用来生成数据库表的,这个类必须继承models.Model类 class UserInfo(models.Model):
#创建表的字段
username = models.CharField(max_length=16) #创建一个字段,类型为字符串类型,最大长度为16
password = models.CharField(max_length=32) #创建一个字段,类型为字符串类型,最大长度为32 #注:对于ORM框架,可以简单的认为自定义类UserInfo表示数据库的表;根据UserInfo创建的对象表示数据库表
#里的一行数据;而对象.username和对象.password表示每一行数据里具体的字段(username/password)的数据。
(1)更多字段类型
一般数据库中字段类型大概5种(字符串/数字/浮点型/时间类型/布尔类型),但Django为了在后台admin中可以操作数据库,同时为了限制在admin中对数据库的无效操作,Model中设置了很多种数据类型。
1、models.AutoField 自增列=int(11) 如果没有的话,默认会生成一个名称为id的列,如果要显示的定义一个自增列,必须把该列设置为主键(primary_key=True) 2、models.CharField 字符串类型字段 必须加max_length参数 3、models.BooleanField 布尔类型字段=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字类型=varchar 继承CharField,所以必须加max_lenght参数 5、models.DateField 日期字段类型date 参数auto_now=True表示每次更新都会更新这个时间;参数auto_now_add表示只是第一次创建时添加,之后的更新不再改变 6、models.DateTimeField 日期字段类型datetime 同DateField的参数 7、models.Decimal 十进制小数类型=decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱)=varchar 对字符串进行正则表达式验证 9、models.FloatField 浮点类型=double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置进行报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串类型,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField 图片 24、models.FilePathField 文件 |
models.DateTimeField/models.GenericIPAddressField/models.ImageField使用字段说明
class UserInfo(models.Model):
name = models.CharField(max_length=32)
ctime = models.DateTimeField(auto_now=True) #每当你创建一行数据时,Django就会在该行数据中增加一个ctime字段
uptime = models.DateTimeField(auto_now_add=True) #当前表任何一行数据有更新时,Django就会自动更新该字段.
#下面两项是新增的字段,注意新增时参数的设置,否则在命令行创建数据库时报错,null=True表示在数据库中该字段可以为空,default='xxx'表示默认值
email_1 = models.EmailField(max_length=32,null=True)
email_2 = models.EmailField(max_length=32,default='aaa@qq.com')
#新增字段,blank=True表示admin后台可以为空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True)
#upload_to='upload'表示用户上传数据存储的位置,这里需要注意:在数据库中实际保存的并不是文件,而是文件存放的路径
img = models.ImageField(null=True,blank=True,upload_to='upload')
(2)更多参数类型
1、null=True 数据库中字段是否可以为空 2、blank=True django的Admin中添加数据时是否可允许空值 3、primary_key=False 主键,对AutoField设置主键后,就会代替原来默认的自增id列 4、auto_now和auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices=GENDER_CHOICE) 6、max_length 最大长度 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 验证 17、upload-to 文件上传路径 |
(3)Model类的扩展
输出Model对象默认返回值
class UserInfo(models.Model):
name = models.CharField(max_length=32)
ctime = models.DateTimeField(auto_now=True) #每当你创建一行数据时,Django就会在该行数据中增加一个ctime字段
uptime = models.DateTimeField(auto_now_add=True) #当前表任何一行数据有更新时,Django就会自动更新该字段.
#下面两项是新增的字段,注意新增时参数的设置,否则在命令行创建数据库时报错,null=True表示在数据库中该字段可以为空,default='xxx'表示默认值
email_1 = models.EmailField(max_length=32,null=True)
email_2 = models.EmailField(max_length=32,default='aaa@qq.com')
#新增字段,blank=True表示admin后台可以为空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True)
#upload_to='upload'表示用户上传数据存储的位置,这里需要注意:在数据库中实际保存的并不是文件,而是文件存放的路径
img = models.ImageField(null=True,blank=True,upload_to='upload')
#下面的__unicode__(self)方法,表示当输出这个类创建的对象时,默认会输出这个对象的name字段
def __unicode__(self):
return self.name
def model(request):
#创建两条数据
models.UserInfo.objects.create(name='alex')
models.UserInfo.objects.create(name='eric')
obj_1 = models.UserInfo.objects.all()
obj_2 = models.UserInfo.objects.filter(name='alex')
#输出obj及其类型
print obj_1,type(obj_1)
print obj_2,type(obj_2)
return HttpResponse('ok')
如果不加上述__unicode__(self)方法,则输出结果为
[<UserInfo: UserInfo object>, <UserInfo: UserInfo object>] <class 'django.db.models.query.QuerySet'>
[<UserInfo: UserInfo object>,] <class 'django.db.models.query.QuerySet'>
如果加上上述__unicode__(self)方法,则输出结果为
[<UserInfo: alex>, <UserInfo: eric>] <class 'django.db.models.query.QuerySet'>
[<UserInfo: alex>,] <class 'django.db.models.query.QuerySet'>
在数据库表已经生成的情况下,添加新的字段报错,错误信息如下:
localhost:Django_lastday luotim$ python manage.py makemigrations
You are trying to add a non-nullable field 'email' to userinfo without a default; we can't do that (the database needs something to
populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
Select an option:
当你在已有的数据库表中添加一个非空的字段的时,由于原表中已有的行没有这个字段,那么就会导致报错。解决办法就是:允许为空、或者设置默认值。假设在已有的表中添加如下两个字段,那么可以设置字段为空,或者给字段设置默认值
email_1 = models.EmailField(max_length=32,null=True)
email_2 = models.EmailField(max_length=32,default='aaa@qq.com')
上传图片实例
class UserInfo(models.Model):
name = models.CharField(max_length=32)
ctime = models.DateTimeField(auto_now=True) #每当你创建一行数据时,Django就会在该行数据中增加一个ctime字段
uptime = models.DateTimeField(auto_now_add=True) #当前表任何一行数据有更新时,Django就会自动更新该字段.
#下面两项是新增的字段,注意新增时参数的设置,否则在命令行创建数据库时报错,null=True表示在数据库中该字段可以为空,default='xxx'表示默认值
email_1 = models.EmailField(max_length=32,null=True)
email_2 = models.EmailField(max_length=32,default='aaa@qq.com')
#新增字段,blank=True表示admin后台可以为空
ip = models.GenericIPAddressField(protocol='ipv4',null=True,blank=True)
#upload_to='upload'表示用户上传数据存储的位置,这里需要注意:在数据库中实际保存的并不是文件,而是文件存放的路径
img = models.ImageField(null=True,blank=True,upload_to='upload')
def __unicode__(self):
return self.name
Model类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head> <body>
{#注意form表单提交文件时,form中的enctype="multipart/form-data"参数表示分片上传#}
<form action="/upload/" method="post" enctype="multipart/form-data">
<p><input type="file" name="f1"/></p>
<p><input type="file" name="f2"/></p>
<p><input type="text" name="hostname"/></p>
<input type="submit" value="upload"/>
</form>
</body>
</html>
HTML页面
def upload(request):
if request.method == 'POST':
# 这里只会获取type='text'的内容
inp_post = request.POST
# 这里获取提交文件的文件名,字典形式
inp_files = request.FILES
# 获取name='f1'对应的文件对象
file_obj1 = inp_files.get('f1')
print file_obj1,type(file_obj1)
# from django.core.files.uploadedfile import InMemoryUploadedFile
# 获取对应的文件名
print file_obj1.name
# 注意在windows下,打开模式为'wb',否则出错
f = open(file_obj1.name,'wb')
# 分片传输,每64k写一次,chunks方法中利用了yield,生成器
print file_obj1.chunks()
for line in file_obj1.chunks():
f.write(line)
f.close()
return render(request,'home/upload.html')
Views中的upload方法
2 注册APP(settings.py文件)
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]
3 执行命令(Django 1.9)
python manage.py makemigrations
python manage.py migrate
当执行python manage.py makemigrations命令时,在Django工程中会生成如图所示的文件(其中migrations为新生成的模块,红框中为新生成的文件)
其中0001_initial.py文件的内容如下(相当于生成一个数据库源,后面生成数据库表会按照这个数据库源来生成)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-11 12:46 from __future__ import unicode_literals
from django.db import migrations, models class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name='UserInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(max_length=16)),
('password', models.CharField(max_length=32)),
],
),
]
然后执行python manage.py migrate命令,它会读取0001_initial.py这个数据库结构文件从而生成数据库表。
4 通过admin来查看数据库
先创建超级用户,然后在admin.py文件中按照如下进行配置
#/usr/bin/env python
#-*- coding:utf-8 -*- from django.contrib import admin
# Register your models here.
from app01 import models #注册models.py文件中创建的类
admin.site.register(models.UserInfo)
然后可以通过页面访问到如下信息
二 操作数据库表
1 基本操作
# 增--3种方法 |
数据库创建数据实例
#hmtl文件
<form action="/add_user/" method="post">
<p>用户名:{{ obj.username }}</p>
<p>密码:{{ obj.password }}</p>
<input type="submit" value="submit"/>
</form> #forms模块中的account.py文件
class AddUser(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput()) #views模块中的login.py文件
def add_user(request):
obj = AccountForm.AddUser(request.POST)
if request.method == 'POST':
if obj.is_valid():
user_input = obj.clean()
print user_input
#用户输入的就是字典类型,所以参数为**user_input
models.UserInfo.objects.create(**user_input)
print models.UserInfo.objects.all()
return render(request,'account/add_user.html',{'obj':obj})
return render(request,'account/add_user.html',{'obj':obj}) #结果
--print user_input
{'username': u'xxx', 'password': u''}
--print models.UserInfo.objects.all() 返回值
[<UserInfo: xxx>, <UserInfo: alex>,] #Model类中添加了__unicode__方法
数据库创建数据实例
数据库查找数据实例
from django import forms
from app01 import models class ImportForm(forms.Form):
# 优化后的写法,设置select的数据为空
admin = forms.IntegerField(
widget=forms.Select()
)
# 为了实时的获取文件中的数据,重新写了构造方法,这样当修改了文件数据,重新请求时(不需要重启)
# 实时的获取文件中的数据,因为每次请求时都会把类实例化,那么就会执行类的构造方法,这里利用了
# 面向对象编程的思想(静态字段属于类),好好体会这里面的思想
def __init__(self,*args,**kwargs):
super(ImportForm,self).__init__(*args,**kwargs)
# 1、从文件中获取数据,然后赋值给self.fields['admin'].widget.choices
# import json
# f = open('db_admin')
# data = f.read()
# data_tuple = json.loads(data)
# self.fields是深拷贝的结果self.fields = copy.deepcopy(self.base_fields)
# self.fields['admin'].widget.choices = data_tuple # 2、直接从数据库中获取self.fields['admin'].widget.choices
self.fields['admin'].widget.choices = models.SimpleModel.objects.all().values_list('id','username')
forms模块中的ImportForm类
from django.shortcuts import render,HttpResponse
from app01.forms import home as HomeForm
from app01 import models def index(request):
# 创建一行数据
# dic = {'username':'alex','password':'123'}
# models.SimpleModel.objects.create(**dic) res = models.SimpleModel.objects.all()
#对应的sql语句"SELECT "app01_simplemodel"."id", "app01_simplemodel"."username", "app01_simplemodel"."password" FROM "app01_simplemodel""
print res.query
#[<SimpleModel: SimpleModel object>] 列表
print res
# <class 'django.db.models.query.QuerySet'> 类
print type(res)
# 取某个字段值,字典
ret = models.SimpleModel.objects.all().values('username')
# [{'username': u'alex'}] 字典
print ret
# <class 'django.db.models.query.QuerySet'>
print type(ret)
# 取某个字段值,列表
ref1 = models.SimpleModel.objects.all().values_list('username')
# [(u'alex',)] 元组组成的列表
print ref1
# <class 'django.db.models.query.QuerySet'>
print type(ref1)
# [(1, u'alex')] 获取(id,username)元组组成的列表
ref2 = models.SimpleModel.objects.all().values_list('id','username')
print ref2 obj = HomeForm.ImportForm()
return render(request,'home/index.html',{'obj':obj})
Views模块中的index函数
class SimpleModel(models.Model):
username = models.CharField(max_length=64)
password = models.CharField(max_length=64)
models模块中的SimpleModel类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>录入数据</h1>
<form action="/index/">
<p>{{ obj.host_type }} </p>
<p>{{ obj.hostname }}</p>
<p>{{ obj.admin }}</p>
</form>
<h1>数据列表</h1>
</body>
</html>
index.html文件
值得注意的地方: #获取指定列的值,可以传多个参数,它的结果为字典形式 #获取指定列的值,可以传多个参数,它的结果为指定列的值先组成元组,然后再由这些元组组成列表 #在form中生成select标签时,可以通过它来获取值然后给choices |
2 进阶操作(了不起的双下划线)
利用双下划线将字段和对应的操作连接起来
# 获取个数 |
参考资料:
http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html
Django基础——Model篇(一)的更多相关文章
- Django基础——Model篇(三)
一 Django ORM中的概念 ORM —— 关系对象映射,是Object Relational Mapping的简写,是用来简化数据库操作的框架 Django ORM遵循Code Frist原则, ...
- Django基础——Model篇(二)
一 Model连表关系 一对多:models.ForeignKey(其他表) 多对多:models.ManyToManyField(其他表) 一对一:models.OneToOneFiel ...
- Django基础第一篇
目录 1.Django MTV框架简介 2.基础命令创建项目的配置说明 3.前后端交互案例 4.基于数据库实现数据交互增删改查 Django简介 Django框架的设计模式借鉴了MVC的思想,和MVC ...
- Django进阶Model篇—数据库操作(ORM)
一.数据库配置 django 默认支持sqlite.mysql.oracle.postgresql数据库,像db2和sqlserver之类的数据库需要第三方的支持,具体详见https://docs.d ...
- Django进阶Model篇008 - 使用原生sql
注意:使用原生sql的方式主要目的是解决一些很复杂的sql不能用ORM的方式写出的问题. 一.extra:结果集修改器-一种提供额外查询参数的机制 二.执行原始sql并返回模型实例 三.直接执行自定义 ...
- Django进阶Model篇007 - 聚集查询和分组查询
接着前面的例子,举例聚集查询和分组查询例子如下: 1.查询人民邮电出版社出了多少本书 >>> Book.objects.filter(publisher__name='人民邮电出版社 ...
- Django进阶Model篇005 - QuerySet常用的API
django.db.models.query.QuerySet QuerySet特点: 1.可迭代 2.可切片 查询相关API 1.get(**kwargs):返回与所给的筛选条件相匹配的对象,返回结 ...
- Django进阶Model篇004 - ORM常用操作
一.增加 create和save方法 实例: 1.增加一条作者记录 >>> from hello.models import * >>> Author.object ...
- Django进阶Model篇002 - 模型类的定义
一.创建数据模型. 实例: 作者模型:一个作者有姓名. 作者详情模型:把作者的详情放到详情表,包含性别.email 地址和出生日期,作者详情模型与作者模型之间是一对一的关系(OneToOneField ...
随机推荐
- java异常与处理
1:Java中的所有不正常类都继承于Throwable类.Throwable主要包括两个大类,一个是Error类,另一个是Exception类: 2:其中Error类中包括虚拟机错误和线程死锁,一旦E ...
- SQLServer语句 汇总
SQL Server语句 序号 功能 语句 1 创建数据库(创建之前判断该数据库是否存在) if exists (select * from sysdatabases where name='data ...
- mac操作快捷键
- dede列表页分页地址优化(不同url相同内容问题解决)<转自http://www.966266.com>
<注明,完全转自http://www.966266.com/seoblog/?p=75> 存在问题 DEDE默认分类分页地址存在不同URL相同内容问题,导致内容重复,对SEO非常不利.情况 ...
- 再详细的介绍一下Unity5的AssetBundle
之前曾经写了一篇博客介绍Unity5的AssetBundle,结果似乎很受关注.不过似乎很多人看了之后都不懂,主要是因为不太明白AssetBundle是什么,它的依赖关系和结构是什么的,就直接想拿代码 ...
- 有关eclipse连接SQL Server 2008的问题
1.首先,提供一个链接http://blog.163.com/jackie_howe/blog/static/19949134720122261121214/ 这个链接有详细更改SQL Server ...
- c# 中定时器的用法
来源于:http://blog.sina.com.cn/s/blog_62c501440100fog1.html System.Threading.Timer 是一个非常常用的定时器类,关于这个类的使 ...
- Quartz任务调度快速入门(转)
转自http://www.blogjava.net/baoyaer/articles/155645.html 概述 了解Quartz体系结构 Quartz对任务调度的领域问题进行了高度的抽象,提出了调 ...
- 2014年IT界最具“钱”景的10类岗位
来自人力资源公司罗致恒富(Robert Half)的一组2014年薪资指导显示,在工程.软件开发和程序领域有一技之长的职工的薪资可能出现何种程度的增长.罗致恒富预计2014年薪资将平均上调3.7%,而 ...
- SP_APPROVALSET_OVERTIME 插入單據
CREATE OR REPLACE PROCEDURE SP_APPROVALSET_OVERTIME(VAPPLY_NO varchar2,VAPPLYKIND_NO varchar2,VFAC_N ...