本节内容
-
路由系统,视图函数,模板引擎,ORM操作
- FBV和CBV
-
ORM操作补充
-
Cookie和Session
- Ajax入门
1. Django基本内容整理
1.1 路由系统
Django中路由系统的使用主要有一下几个方面:
from django.conf.urls import url from django.contrib import admin from app import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), # 直接跳转到views的index函数进行处理 url(r'^index/(d+)/', views.index), # 加括号后表示分组,此分组为未命名分组,views的index函数参数中处理request还需要一个形参来接受分组传递过来的变量 # def index(request,id) url(r'index/(?P<uid>d)',views.index), # 命名分组,通过?P<>可以给传到views的index指定一个关键字参数,他的使用和未命名分组相似 url(r'index/',views.index,name='INDEX'), # url设置别名:通过name可以设置url的别名,别名可以供视图函数和模板使用 # 视图函数(views)使用别名反生成url: # from django.urls import reverse # reverse(viewname='helei') # 模板语言使用别名反生成url: # {% url 'INDEX' %} ]
1.2 视图函数 views
视图下有三个函数来处理用户请求 HttpResponse 简单的返回字符串 render render(request, template_name, context=None, content_type=None, status=None, using=None) 结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。 参数: request: 用于生成响应的请求对象。 template_name:要使用的模板的完整名称,可选的参数 context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。 content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值。 status:响应的状态码。默认为200。 redirect 重定向方法:可以传递参数、locals()或者键值对 2.views的配置 在视图函数date需要接收两个参数,第一个为request(这个参数是必须的),其他参数为url分组传过来的对应参数。 def date(request,year):
1.3 模板引擎
在视图函数中使用render方法可以给模板传递参数,模板通过渲染后,把渲染生成的字符串传递给web客户端,在模板中也有一些模板语言
简单说下常用的模板语言:
如果views函数通过render方法,给模板函数传递了一下几个参数(给模板传递一个用户对象列表,每个对象有username,password,age)
{'user_obj_list':user_obj_list,'title':'用户信息','status':True}
模板语言如下:
- {{ title }} # 取数据
- {% for obj in user_obj_list %} {{ obj.username }}{{ obj.password }} {% endfor %} # 模板语言中的for循环
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> #在标签里添加reversed来反序循环列表: {% for obj in list reversed %} ... {% endfor %} #{% for %}标签可以嵌套: {% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %} #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量, #这个变量含有一些属性可以提供给你一些关于循环的信息 1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first当第一次循环时值为True,在特别情况下很有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了 # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它 # Django会在for标签的块中覆盖你定义的forloop变量的值 # 在其他非循环的地方,你的forloop变量仍然可用 #{% empty %} {{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %} <li>this is empty!</li> {% endfor %} # [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55
- {% if status %} <h1>状态正常</h1> {% else %} {% endif %}
- ########模板的继承
- 母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %} - 变量的过滤器的使用(filter)
语法格式: {{obj|filter:param}} # 1 add : 给变量加上相应的值 # # 2 addslashes : 给变量中的引号前加上斜线 # # 3 capfirst : 首字母大写 # # 4 cut : 从字符串中移除指定的字符 # # 5 date : 格式化日期字符串 # # 6 default : 如果值是False,就替换成设置的默认值,否则就是用本来的值 # # 7 default_if_none: 如果值是None,就替换成设置的默认值,否则就使用本来的值 #实例: #value1="aBcDe" {{ value1|upper }} #value2=5 {{ value2|add:3 }} #value3='he llo wo r ld' {{ value3|cut:' ' }} #import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }} #value5=[] {{ value5|default:'空的' }} #value6='<a href="#">跳转</a>' {{ value6 }} {% autoescape off %} {{ value6 }} {% endautoescape %} {{ value6|safe }} {{ value6|striptags }} #value7='1234' {{ value7|filesizeformat }} {{ value7|first }} {{ value7|length }} {{ value7|slice:":-1" }} #value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }} value9='hello I am yuan'
- {% url 'bieming' %} # 反向生成路由配置的url
- {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %} # 用更简单的变量名替代复杂的变量名
详细的参考:http://www.cnblogs.com/yuanchenqi/articles/6811632.html
1.3.1 自定义filter和simple_tag
a、在app中创建templatetags模块(必须的)
b、创建任意 .py 文件,如:my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改变 @register.filter def filter_multi(v1,v2): return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}
d、使用simple_tag和filter(如何调用)
{% load xxx %} #首行 # num=12 {{ num|filter_multi:2 }} #24 {{ num|filter_multi:"[22,333,4444]" }} {% simple_tag_multi 2 5 %} 参数不限,但不能放在if for语句中 {% simple_tag_multi num 5 %}
e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
注意:
filter可以用在if等语句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
1.4 ORM操作:
数据库的配置。
在Django中默认在settings配置了sqlite数据库的信息,如果需要使用mysql数据库需要进行一下的配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'books', #你的数据库名称 'USER': 'root', #你的数据库用户名 'PASSWORD': '', #你的数据库密码 'HOST': '', #你的数据库主机,留空默认为localhost 'PORT': '3306', #你的数据库端口 } }
注意
NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 USER和PASSWORD分别是数据库的用户名和密码。 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。 然后,启动项目,会报错:no module named MySQLdb 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的__init__,在里面写入: import pymysql pymysql.install_as_MySQLdb() 问题解决!
ORM操作
http://www.cnblogs.com/yuanchenqi/articles/6811632.html
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
2.1 FBV和CBV
在views.py中处理request方法的定义有两种,FBV和CBV 分别如下:
在CBV的方式中,类需要继承View这个类,在这个类中可以重写父类的dispatch函数,因为处理request的GET或POST请求之前会先执行这个方法,重写dispatch方法可以实现某些功能(认证)
FBV: url(r'^index/', views.index), def index(request): print('.....') if request.method == 'GET': pass elif request.method == 'POST': pass return HttpResponse('....') CBV: url(r'^user/', views.User.as_view()), class User(View): def dispatch(self, request, *args, **kwargs): print('before') obj = super(User,self).dispatch(request, *args, **kwargs) print('after') return obj def get(self,request): print("get...") return HttpResponse('...') def post(self,request): print("post...") return HttpResponse('...')
1.3 ORM操作
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
dp = models.ForeignKey(to='DePart',to_field='id')
# depart = models.ForeignKey('DePart')
class DePart(models.Model):
title = models.CharField(max_length=16)
# ForeignKey查询
# 正向跨表查询
# 1.对象
# q = models.UserInfo.objects.all()
# for row in q:
# print(row.username,row.password,row.dp_id,row.dp.id,row.db.title)
# 2.字典
# q = models.UserInfo.objects.values('username','password','dp_id','dp__title')
# for row in q:
# print(row['username'],row['dp__title'])
# 3.元祖
# q = models.UserInfo.objects.values_list('username','password','dp_id','dp__title')
# for row in q:
# print(row[0],row[3])
# 反向跨表查询
# 1.对象
# v = models.DePart.objects.all()
# for row in v:
# print(row.id,row.title,row.userinfo_set.all())
# 2.字典
# v = models.DePart.objects.values('id','title','userinfo__username','userinfo__password')
# for row in v:
# print(row)
# 3.元祖
# v = models.DePart.objects.values('id','title','userinfo__username','userinfo__password')
# for row in v:
# print(row)
# 自己写第三张表
def U2G(models.Model):
ui = models.ForeignKey('UserInfo')
ug = models.ForeignKey('UserGroup')
# 添加数据
models.U2G.objects.create(ui=1,ug=1)
models.U2G.objects.create(ui=1,ug=2)
models.U2G.objects.create(ui=2,ug=1)
models.U2G.objects.create(ui=2,ug=2)
# 查询
q = models.U2G.objects.all()
for row in q:
print(row.ui.username)
print(row.ug.caption)
# django 自动生成
m = models.ManyToManyField('UserInfo')
增加:
obj = models.UserGroup.objects.filter(id=2).first()
obj.m.add(1)
obj.m.add(1,2,3)
obj.m.add(*[1,2]) #一次多加一个
删除:
obj = models.UserGroup.objects.filter(id=2).first()
obj.m.remove(1)
obj.m.remove(2,3,4)
obj.m.remove(*[2,3,4])
清空:
obj.m.clear() # 没有参数
更新:设置为什么, 最后就只有什么
obj.m.set([3,])
查询:
q = obj.m.all()
print(q)
q = obj.m.filter()
models.Book.objects.get_or_create
# 如果没有就创建,需要提供足够的参数
(<Book: Java>,True)
查询条件:
__contains 包含某个元素
__icontains 忽略大小写
__startswith 以什么开头
__istartswith 不区分大小写
__endswith
__iendswith
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__rang 范围
start_date = datetime.date(2005,1,1)
end_date = datetime.date(2006,1,1)
Book.objects.filter(pub_date__rang = (start_date,end_date))
__year
__month 每年的这个月份的都查出来
__day 每年这一天的
__week_day
__hour
文件的自定义上传
def upload_file(request):
if request.method == "POST":
obj = request.FILES.get('fafafa')
f = open(obj.name, 'wb')
for chunk in obj.chunks():
f.write(chunk)
f.close()
return render(request, 'file.html')
1.4 session和cookie
cookie:
放在客户端上的键值对。
1.设置cookie
obj = render(request,'index.html')
obj.set_cookie('key','value')
return obj
2.提取cookie
request.COOKIES.get()
session:
保存到服务器上的键值对
1.设置session
request.session['user'] = u
request.session['pwd'] = p
2.获取session
request.session.get('user')
3.注销
request.session.clear()
1.5 Ajax
ajax最基本的使用
$.ajax({ url: '/aj/', # 提交地址 type: "POST", # 提交方式 data: {uuu: u, ppp:p}, # 提交数据 dataType: "JSON", success:function (data) { # 回调函数,登录成功后自动执行 # 将字典形式的字符串,发序列化成为字典对象(json对象) # var data_dict = JSON.parse(data); if(data_dict.status){ location.href = "/home/" }else{ alert(data_dict.error); } } })
asdf