概述:主要总结Django的一些基本操作,与使用过程中出现的问题,使用的Django版本是1.11.2,开发平台是win10。本次涵盖的内容有url路由机制,orm(对象关系映射),模板语言(增加前后端的交互),基本有了这些就可以完成一个简单的webapp了。
Django路由机制
路由机制例子
路由机制是Django中十分重要的一个部分,Django将收到http请求的url解析,如果与你写的路由表项相匹配就会传递到后端的视图处理函数,如果没有匹配到的url就会丢弃。
路由注册的例子
from django.conf.urls import url
...
urlpatterns=[
...
url(r'^index/aaa',index1),
url(r'^index/',index),
url(r'^add/\d*/$',Add),
url(r'^add/(?P<name>\d*)/$',Add),
url(r'^news/', include('news.urls')),
url(r'^$',error),]
注意放置路由表的列表名必须叫做urlpatterns,url方法在django.conf.urls中。
例子解读
上面的五种情况基本涵盖了注册路由表项的所有情况.
其中第一个与第二个是一种可能会出现误解的情况,因为两个正则表达式都可以匹配/index/aaa,那么这时候,如果让2在1之前,那么就无法匹配到/index/aaa了,因为首先找到了’^index/’就可以匹配上了,没必要继续向后找,所以如果有上面情况的路由匹配需求的时候,我们一定要注意把范围更详细的写在上面,当然r’^index/
′这样的正则匹配也可以解决这样的问题,防止一个正则匹配多个。第三与第四是给视图(view)函数传参的两种形式,第一种就是匹配到了之后传参,但是对这个传入的参数的意义没有任何说明,如果写成第二种形式,我们的视图函数中的参数名字必须为(?P)中param中的参数名字,这样就算不去进入视图的文件中看,也可以看到参数的含义,我们推荐第二种方式。第五个路由项的意义是把路由转发再做一次分发,比如一个webapp有两个大的分站点的时候,比如www.mo.com/news与www.mo.com/video,在这两个下面都会有很多分支的功能,而且可能是由两个组负责完成的,那么这时候就十分有用了,需要注意的是,当路由转发过去后,在子项目中的url匹配与上面没有任何区别,而且不需要添加前面的父项目,比如news下的add项目,在news下的url只需写url(r′add/
’,add)即可。
第六种是用来匹配当你在”/”后什么都不输入的时候的跳转网页的。
二.数据库orm
orm建表
orm系统简化了我们对数据库的操作,不用在开发的过程写很多的sql语句,但是带来方便的后果就是降低了程序的执行效率,所以在实际使用中还要取舍。
1.使用ORM创建一个表
我们对这个表结构的需求是有id(主键),name,password,createtime,updatetim,type(外键))。如果使用sql语句的话。创建起来会有点复杂
sql语句例子
创建usertype表:
CREATE TABLE usertype (id int(11) not NULL AUTO_INCREMENT,
type varchar(50),
PRIMARY KEY(id)
)
创建userinfo表:
CREATE TABLE userinfo (id int(11) not NULL AUTO_INCREMENT , username VARCHAR(50),
password VARCHAR(50) ,
createtime datetime NOT NULL,
updatetime datetime NOT NULL,
type int(11) ,
primary KEY(id),
FOREIGN KEY(type) REFERENCES usertype(id));
orm例子
如果使用orm的话
from django.db import models
...
class usertype(models.Model):
type=models.CharField(max_length=50)
class userinfo(models.Model):
username=models.CharField(max_length=50)
password=models.CharField(max_length=50)
createtime=models.DateTimeField(auto_now_add=True)
updatetime=models.DateTimeField(auto_now=True)
type=models.ForeignKey(usertype,default="1")
当然在创建表之前要把数据库先创建好,只要在setings文件中配置即可。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'Django',
'USER':'django',
'PASSWORD':'*****',
'HOST':'192.168.1.101',
'PORT':'3306',
'OPTIONS':{
'init_command':"SET sql_mode='STRICT_TRANS_TABLES'",
'charset':'utf8',
}
}
}
在models文件中写完上面的语句,我们进入工程的根目录,执行
python manage.py makemigrations
python manage.py migrate
原理解释
就创建完了表,细心的朋友可能发现在migrations目录下生成了很多文件
这些可以理解成,你对数据库表修改的记录,如果你不小心删掉了这些文件,肯定会造成你在django中修改表结果时的问题。如果删掉之后,还想恢复,那就要进入django数据库。
DELETE FROM django_migrations WHERE app="webappname"
删除掉数据中对这些文件的记录才可以恢复。
使用orm首先from django.db import models,继承models.Model之后所创建的类名字就是表名。使用models.CharField创建varchar类型的列,DateTimeField是datetime类型,通过ForeignKey()就可以直接添加外键,是不是很方便。但方便归方便,这样执行后,我们根本不知道他到底做了哪些操作,我们想看下建表过程使用的sql语句,按照下面的执行即可。
PS E:\Pycharm_Project\myweb> python .\manage.py sqlmigrate web 0002
BEGIN;
--
-- Create model test
--
CREATE TABLE `web_test` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `createtime` datetime NOT NULL, `updatetime` datetime NOT NULL);
COMMIT;
命令解释:
python manage.py sqlmigrate webapp_name migrations_id
2.使用orm对数据库进行增删改查
查看orm执行了什么数据库语句
现在我们已经创建好了userinfo表
mariadb root@localhost:Django> SELECT * FROM web_userinfo\G
***************************[ 1. row ]***************************
id | 2
username | root
createtime | 0000-00-00 00:00:00
updatetime | 0000-00-00 00:00:00
type_id | 2
age | 12
***************************[ 2. row ]***************************
id | 3
username | root
createtime | 0000-00-00 00:00:00
updatetime | 0000-00-00 00:00:00
type_id | 2
age | 12
***************************[ 3. row ]***************************
id | 4
username | root
createtime | 0000-00-00 00:00:00
updatetime | 0000-00-00 00:00:00
type_id | 2
方法1
现在通过orm查询出一条数据,并显示出他所执行的sql语句是什么
当访问127.0.0.1:8000/web/index/aaa/的时候就会在终端下显示查到的数据与执行的sql语句:
<QuerySet [{'username': u'root', 'updatetime': None, u'type_id': 2L, 'age': u'12', 'createtime': None, u'id': 2L}, {'username': u'root', 'updatetime': None, u'type_id': 2L, 'age': u'12', 'createtime': None, u'id': 3L}, {'username': u'root', 'updatetime': None, u'type_id': 2L, 'age': u'12', 'createtime': None, u'id': 4L}, {'username': u'mo', 'updatetime': datetime.datetime(2017, 6, 18, 12, 5, 56, tzinfo=<UTC>), u'type_id': 1L, 'age': u'12', 'createtime': datetime.datetime(2017, 6, 18, 12, 5, 56, tzinfo=<UTC>), u'id': 5L}]>
SELECT `web_userinfo`.`id`, `web_userinfo`.`username`, `web_userinfo`.`age`, `web_userinfo`.`createtime`, `web_userinfo`.`updatetime`, `web_userinfo`.`type_id` FROM `web_userinfo`
这里是对QuerySet的query方法的应用,如果不是QuerySet对象的话,就无法生效了。
方法2
使用一个django.db中的模块
from django.db import connection
结果:
[{u'time': u'0.000', u'sql': u'SELECT @@SQL_AUTO_IS_NULL'}, {u'time': u'0.001', u'sql': u'SELECT `web_userinfo`.`username` FROM `web_userinfo` LIMIT 21'}]
切记这两种方法是对你提高Django效率有很好的帮助。
添加数据
方法1:
obj=userinfo(username="test",password="123")
obj.save()
方法2:
userinfo.objects.create(username="test",password="123")
查找数据
方法1:
查找一条数据:
obj=userinfo.objects.get(username=name)
这种方法如果没有查到数据和查到的数据大于一条都会出现异常,用于具有某些唯一性的场合使用。
方法2:
通过过滤,查找多条数据
obj=userinfo.objects.filter(username="mo")
如果不去调用这个返回的obj是不会执行查询语句的
这条语句等价的语句是
select * from userinfo where username="mo"
但是因为返回值是QuerySet类型的,不调用values()方法是不会显示出查找出的数据条目的。
所以一般后面还会跟如下语句作为输出
print obj.values("username")
values里面没有参数的时候,输出查找出来所有行的每一列。
方法3:
这种方法是最符合正常逻辑的一种查询
obj=userinfo.objects.values("username","password").filter(username="mo")
print obj
上面的语句等价于我们最常用的
select username,password from userinfo where username = 'mo';
一般经过filter方法后返回的值的类型都是QuerySet类型的,我们使用for去遍历这个返回值就会得到,相应的字典。
过滤数据
obj.objects.filter(name=name,pwd=password) #这是一个且的关系
obj.objects.filter(Q(username=username)|Q(password=password)) #这是数据库中或的关系
obj.objects.filter(id__gt=id) #这个是大于的关系
obj.objects.filter(id__contains=id) #模糊查找
obj.objects.filter(id__in=["1","2"]) #在什么范围内
删除数据
删除数据其实是建立在查找的原理上,比如我们想删除掉所有username为mo的条目
userinfo.objects.filter(username="mo").delete()
等价的sql语句
DELETE FROM userinfo WHERE username="mo";
更新数据
更新数据的原理也是基于查找
userinfo.objects.filter(username="mo").update(username="test")
数据处理操作
userinfo.objects.values().filter(id__gt=id).order_by("id") #正序
userinfo.objects.values().filter(id__gt=id).order_by("-id") #倒序
userinfo.objects.values().filter(id__gt=id).count() #计数
userinfo.objects.values().filter(id__gt=id)[0:3] #分页
注意分页操作,在以后会经常使用。
Django模板语言
之前所讲到的操作,都是对于底层操作的,我们的前端界面还十分简陋,通过模板语言我们可以给前端界面增加更多的交互。
为了不那么枯燥,我们选择一个需求,通过模板语言来实现:
通过之前的完成一个登陆注册的建议网站应用,登陆成功后显示登陆的用户名。
在配置文件中增加模板目录的路径
首先在项目的根目录下创建好templates目录,所有的html文件都将放置在这个目录下
通过模板语言显示变量
登陆界面如下:
登陆成功界面代码如下:
这里的”{{}}”里面所放置的就是view中视图函数传递过去的变量名,这样这里的值就会是根据登陆客户的不同变动的,而不是之前的纯静态页面了。
模板语言的判断与过滤器
我们想在页面中对传入的参数做一些复杂的逻辑操作,就要使用这些操作。现在需要的功能是判断用户的密码长度,如果小于6位就进行提醒
这里过滤器的作用就相当于一个函数的作用,光靠系统自带的过滤器是肯定不够的,所以下面介绍自定义的过滤器。
自定义过滤器
首先创建一个templatetags目录,并把这个目录的路径加到setings文件中的INSTALLED_APPS中
在这里所写你所想自定义的过滤器,最好每个过滤器对应一个python文件,我们想写一个过滤器,可以将用户的id乘100后显示。
现在进入logined.html文件中,在头部添加
{% load mul %}