到目前为止,当程序涉及到数据库相关操做时,咱们通常都会这么操做:
(1)建立数据库,设计表结构和字段
(2)使用MySQLdb来链接数据库,并编写数据访问层代码
(3)业务逻辑层去调用数据访问层,执行数据库操做html
import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='mydb', passwd='123', 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='123', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return data
Django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。Django遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。Django是经过Model类来操做数据库的,程序员不须要关注SQL语句和数据库的类型(不管数据库是MySql、Sqlite,仍是其它类型),Django自动生成相应数据库类型的SQL语句,来完成对数据库数据的操做。python
当咱们在已经建立的Django工程中建立app时(假设app的名称为app01),那么在app01模块下默认会生成models.py文件,这个就是Django工程中操做数据库的文件。 git
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中设置了不少种数据类型。 sql
一、models.AutoField 自增列=int(11) 若是没有的话,默认会生成一个名称为id的列,若是要显示的定义一个自增列,必须把该列设置为主键(primary_key=True) 二、models.CharField 字符串类型字段 必须加max_length参数 三、models.BooleanField 布尔类型字段=tinyint(1) 不能为空,Blank=True 四、models.ComaSeparatedIntegerField 用逗号分割的数字类型=varchar 继承CharField,因此必须加max_lenght参数 五、models.DateField 日期字段类型date 参数auto_now=True表示每次更新都会更新这个时间;参数auto_now_add表示只是第一次建立时添加,以后的更新再也不改变 六、models.DateTimeField 日期字段类型datetime 同DateField的参数 七、models.Decimal 十进制小数类型=decimal 必须指定整数位max_digits和小数位decimal_places 八、models.EmailField 字符串类型(正则表达式邮箱)=varchar 对字符串进行正则表达式验证 九、models.FloatField 浮点类型=double 十、models.IntegerField 整形 十一、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 十二、models.IPAddressField 字符串类型(ip4正则表达式) 1三、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol能够是:both、ipv四、ipv6 验证时,会根据设置进行报错 1四、models.NullBooleanField 容许为空的布尔类型 1五、models.PositiveIntegerFiel 正Integer 1六、models.PositiveSmallIntegerField 正smallInteger 1七、models.SlugField 减号、下划线、字母、数字 1八、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 1九、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 2一、models.URLField 字符串类型,地址正则表达式 2二、models.BinaryField 二进制 2三、models.ImageField 图片 2四、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)更多参数类型django
一、null=True 数据库中字段是否能够为空 二、blank=True django的Admin中添加数据时是否可容许空值 三、primary_key=False 主键,对AutoField设置主键后,就会代替原来默认的自增id列 四、auto_now和auto_now_add auto_now 自动建立---不管添加或修改,都是当前操做的时间 auto_now_add 自动建立---永远是建立时的时间 五、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices=GENDER_CHOICE) 六、max_length 最大长度 七、default 默认值 八、verbose_name Admin中字段的显示名称 九、name|db_column 数据库中的字段名称 十、unique=True 不容许重复 十一、db_index = True 数据库索引 十二、editable=True 在Admin里是否可编辑 1三、error_messages=None 错误提示 1四、auto_created=False 自动建立 1五、help_text 在Admin中提示帮助信息 1六、validators=[] 验证 1七、upload-to 文件上传路径 |
(3)Model类的扩展编程
输出Model对象默认返回值json
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
<!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>
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')
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'123'} --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) # 一、从文件中获取数据,而后赋值给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 # 二、直接从数据库中获取self.fields['admin'].widget.choices self.fields['admin'].widget.choices = models.SimpleModel.objects.all().values_list('id','username')
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})
class SimpleModel(models.Model): username = models.CharField(max_length=64) password = models.CharField(max_length=64)
<!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>
值得注意的地方: #获取指定列的值,能够传多个参数,它的结果为字典形式 |
2 进阶操做(了不得的双下划线)
利用双下划线将字段和对应的操做链接起来
# 获取个数 |
参考资料:
http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html