内容简介:Django模型(数据库)及Django Query常用方法
###目录:
- Django教程(一)- Django视图与网址
- Django教程(二)- Django视图与网址进阶
- Django教程(三)- Django表单Form
- Django教程(四)- Django模板及进阶
- Django模型(数据库)及Django Query常用方法
- Django教程(五)- 上传及显示
- Django实战(一)- 搭建简单的博客系统
- Django实战(二)- 创建一个课程选择系统
Django模型(数据库)及Django Query常用方法
Django 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite 3, MySQL, PostgreSQL等数据库,只需要在 settings.py 中配置即可,不用更改 models.py 中的代码,丰富的API极大的方便了使用。 新建项目和应用
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有这么一个应用。
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 文件,修改其中的代码如下:
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 提供的 QuerySet API Django提供了丰富的API, 下面演示如何使用它。
$ python manage.py shell >>> from people.models import Person >>> Person.objects.create(name="Tom", age=24) <Person: Person object> >>>
我们新建了一个用户WeizhongTu 那么如何从数据库是查询到它呢?
>>> 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()
##实例代码操作 需求一:编写登录和注册
编写注册功能,用户名不能已经存在,如果存在需要提示重新输入 注册后可以登录,成功后可以跳转到成功登录界面
代码操作:
- register.html
<!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>
- login.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>
- loginsuc.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>
- weekForm.py
# -*- 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)
- models.py
# -*- 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)
- views.py
# -*- 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/')
- urls.py
from django.conf.urls import url
from . import views
urlpatterns=[
url(r'^register/$',views.register,name='register'),
url(r'^login/$',views.login,name='login')
]
效果展示:
需求二:编写宠物管理系统
- petForm.py
# -*- 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)
- html
- petlist.html
<!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>
- html
- addpet.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>
- html
- editpet.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>
- models.py
# -*- 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)
- views.py
# -*- 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})
- urls.py
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'),
]
效果展示:
####功能完善中,未完待续...
以上所述就是小编给大家介绍的《Django模型(数据库)及Django Query常用方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 常用的模型集成方法介绍:bagging、boosting 、stacking
- 常用的模型集成方法介绍:bagging、boosting 、stacking
- 50种常用的matplotlib可视化,再也不用担心模型背着我乱跑了
- Redis常用命令与常用配置速查手册
- Linux常用命令使用
- 常用推荐算法介绍
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design for Hackers
David Kadavy / Wiley / 2011-10-18 / USD 39.99
Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!