###目录:html
Django模型(数据库)及Django Query经常使用方法python
Django 模型是与数据库相关的,与数据库相关的代码通常写在 models.py
中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库,只须要在settings.py
中配置便可,不用更改models.py
中的代码,丰富的API极大的方便了使用。 新建项目和应用react
django-admin.py startproject learn_models # 新建一个项目
cd learn_models # 进入到该项目的文件夹
django-admin.py startapp people # 新建一个 people 应用(app)
复制代码
补充:新建app也能够用 python manage.py startapp people
, 须要指出的是,django-admin.py
是安装Django后多出的一个命令,并非运行的当前目录下的django-admin.py
(当前目录下也没有),但建立项目会生成一个 manage.py
文件。 那project和app什么关系呢? 一个项目通常包含多个应用,一个应用也能够用在多个项目中。正则表达式
添加应用 将咱们新建的应用(people)添加到 settings.py 中的 INSTALLED_APPS中,也就是告诉Django有这么一个应用。sql
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'people',
)
复制代码
修改models.py 咱们打开 people/models.py 文件,修改其中的代码以下:shell
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
复制代码
咱们新建了一个Person类,继承自models.Model, 一我的有姓名和年龄。 这里用到了两种Field,更多Field类型能够参考教程最后的连接。 建立数据表 咱们来同步一下数据库(咱们使用默认的数据库 SQLite3,无需配置)数据库
先 cd 进入 manage.py 所在的那个文件夹下,输入下面的命令
# Django 1.6.x 及如下
python manage.py syncdb
# Django 1.7 及以上的版本须要用如下命令
python manage.py makemigrations
python manage.py migrate
复制代码
咱们会看到,Django生成了一系列的表,也生成了咱们新建的people_person这个表,那么如何使用这个表呢?django
使用 Django 提供的 QuerySet API Django提供了丰富的API, 下面演示如何使用它。bash
$ python manage.py shell
>>> from people.models import Person
>>> Person.objects.create(name="Tom", age=24)
<Person: Person object>
>>>
复制代码
咱们新建了一个用户WeizhongTu 那么如何从数据库是查询到它呢?session
>>> Person.objects.get(name="Tom")
<Person: Person object>
>>>
复制代码
咱们用了一个 .objects.get() 方法查询出来符合条件的对象,可是你们注意到了没有,查询结果中显示<Person: Person object>,这里并无显示出与Tom的相关信息,若是用户多了就没法知道查询出来的究竟是谁,查询结果是否正确,咱们从新修改一下 people/models.py name 和 age 等字段中不能有 __(双下划线,由于在Django QuerySet API中有特殊含义(用于关系,包含,不区分大小写,以什么开头或结尾,日期的大于小于,正则等) 也不能有Python中的关键字,name 是合法的,student_name 也合法,可是student__name不合法,try, class, continue 也不合法,由于它是Python的关键字( import keyword; print(keyword.kwlist) 能够打出全部的关键字)
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
def __unicode__(self):
# 在Python3中使用 def __str__(self):
return self.name
复制代码
按 CTRL + C 退出当前的 Python shell, 重复上面的操做,再来看看效果
新建一个对象的方法有如下几种:
1. Person.objects.create(name=name,age=age)
2. p = Person(name="Tim", age=23)
p.save()
3. p = Person(name="Tony")
p.age = 23
p.save()
4. Person.objects.get_or_create(name="Rose", age=23)
复制代码
这种方法是防止重复很好的方法,可是速度要相对慢些,返回一个元组,第一个为Person对象,第二个为True或False, 新建时返回的是True, 已经存在时返回False. 获取对象有如下方法:
Person.objects.all()
Person.objects.all()[:10] 切片操做,获取10我的,不支持负索引,切片能够节约内存
Person.objects.get(name=name)
复制代码
get是用来获取一个对象的,若是须要获取知足条件的一些人,就要用到filter
Person.objects.filter(name="abc")
# 等于Person.objects.filter(name__exact="abc") 名称严格等于 "abc" 的人
Person.objects.filter(name__iexact="abc")
# 名称为 abc 可是不区分大小写,能够找到 ABC, Abc, aBC,这些都符合条件
Person.objects.filter(name__contains="abc") # 名称中包含 "abc"的人
Person.objects.filter(name__icontains="abc") #名称中包含 "abc",且abc不区分大小写
Person.objects.filter(name__regex="^abc") # 正则表达式查询
Person.objects.filter(name__iregex="^abc") # 正则表达式不区分大小写
复制代码
filter是找出知足条件的,固然也有排除符合某条件的
Person.objects.exclude(name__contains="WZ")
# 排除包含 WZ 的Person对象
Person.objects.filter(name__contains="abc").exclude(age=23)
# 找出名称含有abc, 可是排除年龄是23岁的
复制代码
从数据库中查询出来的结果通常是一个集合,这个集合叫作 QuerySet。
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self): # __str__ on Python 3
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self): # __str__ on Python 3
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __unicode__(self): # __str__ on Python 3
return self.headline
复制代码
QuerySet 建立对象的方法
>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
总之,一共有四种方法
# 方法 1
Author.objects.create(name="Tom", email="tom@163.com")
# 方法 2
twz = Author(name="Tom", email="tom@163.com")
twz.save()
# 方法 3
twz = Author()
twz.name="Tom"
twz.email="tom@163.com"
twz.save()
# 方法 4,首先尝试获取,不存在就建立,能够防止重复
Author.objects.get_or_create(name="Tom", email="tom@163.com")
# 返回值(object, True/False)
复制代码
备注:前三种方法返回的都是对应的 object,最后一种方法返回的是一个元组,(object, True/False),建立时返回 True, 已经存在时返回 False 当有一对多,多对一,或者多对多的关系的时候,先把相关的对象查询出来
>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
复制代码
删除符合条件的结果 和上面相似,获得知足条件的结果,而后 delete 就能够(危险操做,正式场合操做务必谨慎),好比:
Person.objects.filter(name__contains="abc").delete() # 删除 名称中包含 "abc"的人
若是写成
people = Person.objects.filter(name__contains="abc")
people.delete()
效果也是同样的,Django实际只执行一条 SQL 语句。
复制代码
更新某个内容 批量更新,适用于 .all() .filter() .exclude() 等后面 (危险操做,正式场合操做务必谨慎)
Person.objects.filter(name__contains="abc").update(name='xxx') # 名称中包含 "abc"的人 都改为 xxx
Person.objects.all().delete() # 删除全部 Person 记录
复制代码
单个 object 更新,适合于 .get(), get_or_create(), update_or_create() 等获得的 obj,和新建很相似。
aut = Author.objects.get(name="Sara")
aut.name="LiMing"
aut.email="Liming@163.com"
aut.save() # 最后不要忘了保存!!!
复制代码
QuerySet 是可迭代的,好比:
es = Entry.objects.all()
for e in es:
print(e.headline)
复制代码
Entry.objects.all() 或者 es 就是 QuerySet 是查询全部的 Entry 条目。 注意事项: (1). 若是只是检查 Entry 中是否有对象,应该用 Entry.objects.all().exists() (2). QuerySet 支持切片 Entry.objects.all()[:10] 取出10条,能够节省内存 (3). 用 len(es) 能够获得Entry的数量,可是推荐用 Entry.objects.count()来查询数量,后者用的是SQL:SELECT COUNT(*) (4). list(es) 能够强行将 QuerySet 变成 列表 QuerySet 查询结果排序 做者按照名称排序
Author.objects.all().order_by('name')
Author.objects.all().order_by('-name') # 在 column name 前加一个负号,能够实现倒序
复制代码
QuerySet 支持链式查询
Author.objects.filter(name__contains="Tom").filter(email="tom@163.com")
Author.objects.filter(name__contains="Tom").exclude(email="tom@163.com")
# 找出名称含有abc, 可是排除年龄是23岁的
Person.objects.filter(name__contains="abc").exclude(age=23)
复制代码
QuerySet 不支持负索引
Person.objects.all()[:10] 切片操做,前10条
Person.objects.all()[-10:] 会报错!!!
# 1. 使用 reverse() 解决
Person.objects.all().reverse()[:2] # 最后两条
Person.objects.all().reverse()[0] # 最后一条
# 2. 使用 order_by,在栏目名(column name)前加一个负号
Author.objects.order_by('-id')[:20] # id最大的20条
复制代码
扩展:QuerySet 重复的问题,使用 .distinct() 去重复 通常的状况下,QuerySet 中不会出来重复的,重复是很罕见的,可是当跨越多张表进行检索后,结果并到一块儿,能够会出来重复的值
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
# 合并到一块儿
qs = qs1 | qs2 | qs3
这个时候就有可能出现重复的
# 去重方法
qs = qs.distinct()
复制代码
##实例代码操做 需求一:编写登陆和注册
编写注册功能,用户名不能已经存在,若是存在须要提示从新输入 注册后能够登陆,成功后能够跳转到成功登陆界面
代码操做:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用户名:{{form.userName}}{{error}}<br>
密 码:{{form.password}}<br>
确认密码:{{form.repassword}}<br>{{form.non_field_errors}}<br>
<input type="submit" value="注册">
<a href="{% url 'login' %}">已有帐号,去登陆</a>
</form>
</body>
</html>
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆</title>
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
<a href="{% url 'register' %}">没有帐号?去注册</a><br>
用户名:{{form.userName}}<br>
密 码:{{form.password}}<br>{{error}}<br>
<input type="submit" value="登陆">
</form>
</body>
</html>
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆成功</title>
</head>
<body>
登录成功了,开不开心,意不意外。怎么还有一个网页?哈哈哈哈哈哈~<br>
用户ID:{{ request.session.id }}<br>
用户名:{{ request.session.username }}
</body>
</html>
复制代码
# -*- coding:utf-8 -*-
from django.forms import Form,widgets,fields,ValidationError
class register(Form):
userName = fields.CharField(max_length=10)
password = fields.CharField(max_length=10,widget=widgets.PasswordInput)
repassword = fields.CharField(max_length=10,widget=widgets.PasswordInput)
def clean(self):
userName = self.cleaned_data['userName']
password = self.cleaned_data['password']
repassword = self.cleaned_data['repassword']
if not password == repassword:
myerror = '两次密码不一致,请从新输入'
raise ValidationError(myerror)
return self.cleaned_data
class login(Form):
userName = fields.CharField(max_length=10)
password = fields.CharField(max_length=10,widget=widgets.PasswordInput)
复制代码
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class UserModel(models.Model):
userName = models.CharField(max_length=10)
password = models.CharField(max_length=10)
复制代码
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render,redirect
from weekForms import weekForm
from models import UserModel
from django.http import HttpResponse
from . import models
# Create your views here.
def register(request):
if request.method == 'GET':
form = weekForm.register()
return render(request,'register.html',{'form':form})
elif request.method == 'POST':
form = weekForm.register(request.POST)
if form.is_valid():
temp = models.UserModel.objects.filter(userName=form.cleaned_data['userName']).exists()
if temp == False:
userModel = UserModel()
userModel.userName = form.cleaned_data['userName']
userModel.password = form.cleaned_data['password']
userModel.save()
return HttpResponse('数据提交成功!您能够登陆了.')
else:
error = '用户名已经存在!'
return render(request,'register.html',{'form':form,'error':error})
else:
return render(request,'register.html',{'form':form})
def login(request):
if request.method == 'GET':
loginform = weekForm.login()
return render(request,'login.html',{'form':loginform})
elif request.method == 'POST':
loginform = weekForm.login(request.POST)
if loginform.is_valid():
userName = loginform.cleaned_data['userName']
password = loginform.cleaned_data['password']
user = UserModel.objects.filter(userName=userName,password=password)
if user:
obj = UserModel.objects.get(userName = userName)
request.session['id'] = obj.id
request.session['username'] = obj.userName
return render(request,'loginsuc.html')
#若是想直接显示能够在setting中加SESSION_SERIALIZER='django.contrib.sessions.serializers.PickleSerializer'
else:
error = '用户名或者密码输入有误.'
return render(request,'login.html',{'form':loginform,'error':error})
else:
return render(request,'login.html',{'form':loginform})
else:
return redirect('https://www.zhihu.com/')
复制代码
from django.conf.urls import url
from . import views
urlpatterns=[
url(r'^register/$',views.register,name='register'),
url(r'^login/$',views.login,name='login')
]
复制代码
效果展现:
需求二:编写宠物管理系统
# -*- coding: utf-8 -*-
from django.forms import Form,widgets,fields
class petInfo(Form):
petName = fields.CharField(max_length=10,)
petId = fields.CharField(max_length=4)
gender = fields.CharField(initial = '雄性',
widget = widgets.Select(choices=(('雄性','雄性'),('雌性','雌性'))))
year = fields.IntegerField(max_value=25,min_value=0)
kind = fields.CharField(max_length=10)
class PetInfo(Form):
petName = fields.CharField(max_length=10,)
petId = fields.CharField(max_length=4)
gender = fields.CharField(initial = '雄性',widget = widgets.Select(choices=(('雄性','雄性'),('雌性','雌性'))))
year = fields.IntegerField(max_value=25,min_value=0)
kind = fields.CharField(max_length=10)
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>宠物管理系统</title>
</head>
<body>
<table>
<tr>
<td>宠物名</td>
<td>宠物编号</td>
<td>宠物性别</td>
<td>宠物年龄</td>
<td>种类</td>
</tr>
{% for pet in pets %}
<tr>
<td>{{pet.petName}}{{disable}}</td>
<td>{{pet.petId}}</td>
<td>{{pet.gender}}</td>
<td>{{pet.year}}</td>
<td>{{pet.kind}}</td>
<td><a href="">删除</a></td>
<td><a href="{% url 'editpet' %}?id={{ pet.id }}">修改</a></td>
</tr>
{% empty %}
没有宠物信息
{% endfor %}
</table>
<a href="{% url 'addPet' %}">添加新宠物</a>
</body>
</html>
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加宠物信息</title>
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ id }}">
宠物名:{{form.petName}}<br>
宠物编号:{{form.petId}}<br>
宠物性别:{{form.gender}}<br>
年 龄:{{form.year}}<br>
种类:{{form.kind}}<br>
<input type="submit" value="增长宠物">
</body>
</html>
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改宠物信息</title>
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ id }}">
宠物名:{{pet.petName}}<br>
宠物编号:{{pet.petId}}<br>
宠物性别:{{pet.gender}}<br>
年 龄:{{pet.year}}<br>
种类:{{pet.kind}}<br>
<input type="submit" value="修改">
</form>
</body>
</html>
复制代码
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class pet(models.Model):
petName = models.CharField(max_length=10)
petId = models.CharField(max_length=4)
gender = models.CharField(max_length=1)
year = models.IntegerField()
kind = models.CharField(max_length=10)
复制代码
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from models import pet
from django.http import HttpResponse
from petForms import petForm
from . import models
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
# Create your views here.
def petlist(request):
pets = models.pet.objects.all().filter(isDelete=True)
return render(request,'petlist.html',{'pets':pets})
def addPet(request):
if request.method == 'GET':
petform = petForm.PetInfo()
return render(request,'addpet.html',{'form':petform})
elif request.method == 'POST':
petform = petForm.PetInfo(request.POST)
if petform.is_valid():
data = petform.cleaned_data
newPet = pet()
newPet.petName = data['petName']
newPet.petId = data['petId']
newPet.gender = data['gender']
newPet.year = data['year']
newPet.kind = data['kind']
newPet.save()
return redirect(reverse('petlist'))
else:
return render(request,'addpet.html',{'form':petform})
def editPet(request):
if request.method == 'GET':
id = request.GET.get('id',0)
pets = models.pet.objects.get(pk=int(id))
petform = petForm.petInfo(
initial={
'petName':pets.petName,
'petId':pets.petId,
'gender':pets.gender,
'year':pets.year,
'kind':pets.kind,
} #给须要修改的宠物添加初始属性
)
return render(request,'editpet.html',{'pet':petform,'id':id})
elif request.method == 'POST':
petform = petForm.petInfo(request.POST)
id = request.POST['id']
if petform.is_valid():
data = petform.cleaned_data
oldPet = models.pet.objects.get(pk=int(id))
# oldPet.petName = models.Pet.objects.get(pk=int(id))['petName']
oldPet.petName = data['petName']
oldPet.petId = data['petId']
oldPet.gender = data['gender']
oldPet.year = data['year']
oldPet.kind = data['kind']
oldPet.save()
return redirect(reverse('petlist')) #重定向
else:
pet = models.pet.objects.get(pk=int(id))
return render(request,'editpet.html',{'pet':petform,'id':id})
def petsin(request):
Pets = pet.objects.all()
id = request.GET['id']
new = models.pet.objects.get(pk=int(id))
values = {
'petName':new.petName,
'petId':new.petId,
'gender':new.gender,
'year':new.year,
'kind':new.kind,
}
return render(request,'pet.html',{'values':values,})
def delpet(request):
if request.method == 'GET':
id = request.GET.get('id',0)
pets = models.pet.objects.get(pk=int(id))
pets.isDelete=0
pets.save()
pets = models.pet.objects.all().filter(isDelete = True)
return render(request, 'petlist.html', {'pets': pets})
复制代码
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'addPet/$',views.addPet,name='addPet'),
url(r'petlist/$',views.petlist,name='petlist'),
url(r'editpet/$',views.editPet,name='editpet'),
]
复制代码
效果展现:
####功能完善中,未完待续...