本章内容:css
环境搭建及基础配置html
URL设置前端
Django快速Web开发——模型(基础)python
Django快速Web开发——管理后台jquery
Django中文文档nginx
参考文档git
Django的安装会涉及一下多个软件,部署的参考文档会有不少,遇到的报错也会不少,百度、goole 可解决github
系统字符集:
#echo $LANG en_us.UTF-8
yum源设置:
mirrors.aliyun.com/help/centos or wget -O /etc/yum.repos.d/CentOs-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
时区设置:
ntpdate time.windows.com
python 相关包安装:
依赖的包: yum -y install openssl-devel readline-devel gcc gcc-c++ pypi setuptools 包,注意回退一个版本比较稳定
Wget -S https://pypi.python.org/packages/dc/8c/7c9869454bdc53e72fb87ace63eac39336879eef6f2bf96e946edbf03e90/setuptools-33.1.1.zip#md5=7963d41d97b94e450e3f8a217be06ffe unzip setuptools-33.1.1.zip cd setuptools-33.1.1 /usr/local/python27/bin/python setup.py install python-2.7.13 版本
wget -S https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz ./configure --prefix=/usr/locl/python27 make && make intall pip 安装 /usr/local/python27/bin/easy_install pip vim /etc/pip.conf [global] trusted-host = pypi.douban.com index-url = http://pypi.douban.com/simple [list] format=colums
virtualenv 环境安装
/usr/local/python27/bin/pip install virtualenv cd data/ /usr/local/python27/bin/virtualenv ./python27env source /data/python27/env/bin/activate pip install ipython pip install mysql-python #deactiveate ,退出虚拟环境
django 安装:
pip install "django>=1.8,<1.9" #安装1.8版本 ipython 中 django.get_version() #查看版本
mysql 安装
5.6版本比较稳定 rpm -ivh https://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm sudo yum -y install mysql mysql-server mysql-devel zlib-devel
django-admin startproject opsweb #生成opswed项目
项目目录结构:
运行第一个小实例:
须要提早在settings.py里修改这一行: ALLOWED_HOSTS = ["*"]
python manage.py runserver 0.0.0.0:33333
这里运行的时候遇到一个报错:
ImportError: No module named security
这个是因为我在virtualenv环境下建立的这个项目,执行的时候却退出了,须要进入后再执行。
python manage.py startapp dashboard
生成的目录结构:
目录文件说明:
配置app
把app的名字写入:
opsweb/settings.py
再对url进行配置:
添加到opsweb/urls.py中
能够理解为处理dashboard目录,交给后面的函数来处理
配置视图:
配置dashboard中的url:
梳理下流程:
如:发起url请求:http://59.110.12.72:33333/dashboard/hello/
首先匹配到dashboard 这个app,而后又在python27env/reboot/opsweb/opsweb/urls.py中匹配到了 url(r'^dashboard/', include("dashboard.urls")),而后就会去dashboard中查找urls.py. 在其中发现url(r'hello/$',views.hello), 而后就会执行views视图中的hello函数。
视图函数中的request是由Django建立的
def index(request): pass
request属性
HttpRequest.scheme
HttpRequest.body
HttpRequest.path
HttpRequest.path_info
HttpRequest.method
HttpRequest.encoding
HttpRequest.GET
HttpRequest.POST
HttpRequest.META
HttpRequest.user
request方法
HttpRequest.get_host()
HttpRequest.get_full_path()
HttpRequest.build_absoulute_uri(location)
HttpRequest.get_signed_cookie()
HttpRequest.is_secure()
HttpRequest.is_ajax()
传递一个字符串做为页面的内容到HttpResponse构造函数
from django.http import HttpResponse return HttpResponse('Here is the text of hte web page')
return HttpResponse('Test',content_type="text/plain")
reponse属性
HttpResponse.content
HttpResponse.charset
HttpResponse.status_code
HttpResponse.reason_phrase
reponse方法
HttpResponse.__init__(content=”, content_type=None, status=200, reason=None, charset=None)
如何用呢?待了解
django 中 return HttpResponse('内容'),这个内容只能是string格式的,因此须要 json.dumps(res) 下这个res结果
加入这个res是字典,后端已经序列化了,传递给前端后,须要把这个字符串转化为对象, var obj = JSON.parse(data)
前端对象转换为字符串 :
那为题来了,ajax 请求中只能 return HttpResponse 吗?最好是这样,但能够用 render,不过这个返回的是一个渲染好的html页面,处理是个问题,redirect这个是不能用的!
支持传递list,dict
return JsonResponse([1,2,3], safe = False)
In [1]: from django.http import QueryDict In [2]: Get = QueryDict('a=1&b=2&c=3')
QueryDict的方法:
QueryDict.get(key, default=None)
QueryDict.setdefault(key, default=None)[source]
QueryDict.update(other_dict) QueryDict.items() QueryDict.values() QueryDict.copy() QueryDict.getlist(key, default=None)
QueryDict.setlist(key, list_)[source]
QueryDict.appendlist(key, item)
QueryDict.setlistdefault(key, default_list=None)
QueryDict.lists() QueryDict.pop(key) QueryDict.popitem() QueryDict.dict() QueryDict.urlencode(safe=None)
这种方法相比render较不适用,建议使用render,学习一下
与flask类似,须要创建一个templates文件夹,把html文件放到这里,而后再渲染
视图中添加:
urls中添加:
html文件:
后端验证登陆
request.GET
request.POST
request.FILES #上传文件
request.getlist() #checkbox 等多选的内容
1 def login(request): 2 print request 3 if request.method == "GET": 4 print 'username from get -->',request.GET.get('username') 5 print 'password from get-->',request.GET.get('password') 6 template = loader.get_template('login.html') 7 context = Context({"title":"reboot 运维平台"}) 8 return HttpResponse(template.render(context)) 9 10 elif request.method == 'POST': 11 print 'username from get -->',request.POST.get('username') 12 print 'password from get-->',request.POST.get('password') 13 username = request.POST.get('username') 14 password = request.POST.get('password') 15 return HttpResponse('login ok!')
<html> <head> <title> {{title}} </title> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> </head> <body> <h1>用户登陆</h1> <ul> <form action="/dashboard/login/" method="post"> <li><input type="text" name="username" id="username" /></li> <li><input type="text" name="password" id="password" /></li> <li><input type="submit" value="login" id="form_submit" /></li> </form> </ul> <script> $(function(){ $('#form_submit').click(function(){ var username = $('#username').val(); var password = $('#password').val(); $.post("/dashboard/login/",{username:username,password:password},function(res){ alert(res) }) return false; #若是不return false的话,就会按照默认的请求走了 }) }) </script> </body> </html>
又名静态文件配置
添加static目录,须要添加setting里面的
STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )
这样,就能够在templates目录下的html文件中引用这个url了
项目下的urls.py的配置
一、/index/
二、/index/(\d+)
三、/index/(?P<nid>\d+)
正则(?P<year>[0-9]{4})用法
至关于定义了一个year变量,在后边匹配到条件,就把取到值复制给year
四、/index/(?P<nid>\d+) name='root'
reverse()
{% url 'root' 1 %}
五、include
当有N个app时,url的编写都在项目的usls.py下就会有点乱,能够把这个文件转移到各个app下的urls.py下,须要在项目urls.py下作以下操做
from django.conf.urls import url, include
urlpatterns = [
url(r'^cmdb/', include('app01.urls'))
url(r'^monitor/', include('app02.urls'))
]
六、默认值(传递参数)
/index/ {'web':'root'}
def func(request, web):
return ......
例子:
url(r'^index/', views.index, {'name':'root'})
def index(request, name):
print(name)
return HttpResponse('ok')
这时候回多传递后面的字典给后端,而浏览器的格式不变。这个字典的变量能够是动态的,如,动态获取了客户的信息,而后传递给后端。这是后再view中定义的函数,也须要传递这个字典的key,否则会报确实参数的错。
七、name
对URL路由关系进行命名, ==> 之后能够根据此名称生成本身想要的URL
url(r'abcdefg', views.index, name='i1') url(r'bbbbbb/(\d+)/(\d+)', views.index, name='i2') url(r'dddddd/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3')
def func(request, *args, **kwargs): from django.urls import reverse url1 = reverse('i1') #生成的url abcdefg url2 = reverse('i2', args = (1,2,)) #bbbbbb/1/2/ url3 = reverse('i3' , kwargs = {'pid':1, "nid":9}) #dddddd/1/9
action = {% url "i1" %}
{% url "i3" 1 2 %}
{% url 'i3' pid=1 nid = 9%}
视图获取用户相关请求信息,以及请求头。
print(tpye(request)) #查看类类型
from django.core.handlers.wsgi import WAGIRequest #能够查看到全部的请求头都是包含在environ 方法中的
print(request.environ)
for k,v in request.environ.items(): #去查看请求头过来的全部信息
def login_view(request): if request.method == "GET": return render(request, "public/login.html") else: username = request.POST.get("username", "") userpass = request.POST.get("password", "") user = authenticate(username=username, password=userpass) ret = {"status":0, "errmsg":""} if user: login(request, user) ret['next_url'] = request.GET.get("next") if request.GET.get("next", None) else "/" else: ret['status'] = 1 ret['errmsg'] = "用户名或密码错误,请联系管理员" return JsonResponse(ret)
模板继承:有时候许多页面有许多类似之处,为了书写简单就能够用到末班继承,
被继承文件 layer.html ,写好公共的内容, {% block content %} {% endblock %} 这个里面是继承的页面中须要本身书写的东西
继承的文件 a.html {% extends 'layer.hmlt' %} #说明下这个内容是从哪里继承的
{% block content %} 书写本身的代码 {% endblock %} ,固然能够写多块内容
模板导入:别人写好的代码块,咱这个页面上面须要导入,好比淘宝上面的每一个产品的块
a.html b.html 这些都是一个个小的产品,这时候须要在主页面导入
{% include “a.html” %}
{% include "b.html" %}
Simple_tag写法
一、首先要在app的目录下建立一个templatetags(名字不能变)目录,app须要添加到setting里面就没必要多说了
二、穿件一个任意名称的python文件,如xxoo.py
三、xxoo.py 代码
from django import template register = template.Library() #register名字不能变 @register.simplt_tag def zidingyi(a,b): #能够添加参数 return a + b
四、配置html文件
{% load xxoo %} //首先须要在html文件的顶部load这个python文件
{% zidingyi 2 5 %} //而后下面能够引用这个函数了
优势:能够传递多个参数
缺点:不能做为if条件
Filter
用法基本相同
from django import template register = template.Library() #register名字不能变 @register.filter def zidingyi(a,b): #能够添加参数,最多只容许两个参数 return a + b
html文件
{% load xxoo %} //首先须要在html文件的顶部load这个python文件
{% ‘第一个参数’|zidingyi:“第二个参数” %} //注意中间不能有空格
cookie:以键对的方式存储在客户端
django设置cookie: rep.set_cookie(key,value,参数)
def login(request): user_info = { 'dachengzi':{'pwd':'123'}, 'kangbazi':{'pwd':'123'} } if request.method == 'GET': print('I am here') return render(request, 'login.html') elif request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') print(username,password) res = user_info.get(username) if not res: return render(request, 'login.html') if res['pwd'] == password: print('I am coming to denglu') res = redirect('/denglu/') #能够这种写法 res.set_cookie('username111',username) return res else: return render(request,'login.html') def denglu(request): v = request.COOKIES.get('username111') #提取登陆的username if not v: return redirect('/login/') return render(request, 'denglu.html', {'current_user':v}) #在前端显示登陆的user
参数:
key, 键
value
=
'', 值
max_age
=
None
, 超时时间
expires
=
None
, 超时时间(IE requires expires, so
set
it
if
hasn't been already.)
path
=
'/'
, Cookie生效的路径,
/
表示根路径,特殊的:跟路径的cookie能够被任何url的页面访问
domain
=
None
, Cookie生效的域名
secure
=
False
, https传输
httponly
=
False
只能http协议传输,没法被JavaScript获取(不是绝对,底层抓包能够获取到也能够被覆盖)
例:
current_date = datetime.datetime.utcnow()
current_date = current_date + datetime.timedelta(seconds=5)
response.set_cookie('username111', u, expires=current_data)
httponly=False 这只后只有http能获取到cookie,js获取不到
<select onchange="changePageSize()"> <option value="10">10</option> <option value="30">30</option> <option value="50">50</option> <option value="100">100</option> </select> <script src="jquery.js"></script> <script src="jquery.cookie.js"></script> //cookie是基于juery的,对cookie进行操做 <script> function changePageSize(ths){ var v = $(ths).val() $.cookie('per_page_count', v) } </script>
cookie 加salt
obj = HttpResponse('s')
obj.set_signed_cookie('username', "kangbazi", salt='abcdefg') #加盐加密
request.get_signed_cookie('username', salt='abcdefg') #用盐解密
django实现session功能十分简单,在视图函数中添加以下,
request.session['username'] = username
看似简单,其实django帮咱们作了许多事情
一、生成随机字符串
二、写到浏览器的cookie中,(sessionid的形式)
三、保存在服务器端的session中,(保存在了数据库中django_session表中)
四、固然这个服务器端存session的字典中也能够保存一些其余的客户的信息,来更好的识别客户
待session设置完毕后须要
python manage.py makemigrations
python manage.py migrate
来使之生效
django的session的缓存时间默认是2周,能够人为设置
request.session.set_expiry(10s) 设置10s过时
还能够在setting里添加一些默认的设置
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过时(默认) SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改以后才保存(默认)
setting的配置中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'wang.....',
'USER':'#####',
'PASSWORD':'123456',
'HOST':'59.110.12.72',
'PORT':3306
}
}
测试连接数据是否成功:
python manage.py syncdb
须要注意的是,Django默认使用的是MySQLdb模块连接MYSQL,python3中须要修改成pymysql,在project 同名文件夹下的__init__文件中添加以下代码便可:
import pymysql
pymysql.install_as_MYSQLdb()
连接数据库建立普通用户:
python manage.py shell
from django.contrib.auth.models import User
user = User.objects.create_user('rock','rock@51reboot.com','123456')
建立管理员用户,命令行模式下:
python manage.py createsuperuser --username=reboot --email=reboot@51reboot.com
修改密码:
python manage.py shell
from django.contrib.auth.models import User
user = User.objects.get(username='rock')
user.set_password('rock')
user.save()
用户登陆和退出验证:
from django.contrib.auth import authenticate,login,logout def login_view(request): print request if request.method == "GET": template = loader.get_template('login.html') context = Context({"title":"reboot 运维平台"}) return HttpResponse(template.render(context)) elif request.method == 'POST': print 'username from get -->',request.POST.get('username') print 'password from get-->',request.POST.get('password') username = request.POST.get('username') password = request.POST.get('password') user = authenticate(username=username,password=password) if user: login(request,user) return HttpResponse('login ok!') else: return HttpResponse('login fail') def logout_view(request): logout(request) return HttpResponse('logout success!!')
from django.views import view
class Home(view): #继承view方法 ''' 执行get、post方法以前都会先执行dispatch方法 ''' def dispatch(self, request, *args, **kwargs): #代用父类中的dispatch print('before') result = super(Home, self).dispatch(request, *args, **kwargs) print('after') def get(self, request): print(request.method) return render(request, 'home.html') def post(self, request): print(request.method, 'POST') return render(request, 'home.html')
两种架构:
MVC
即将程序分为三个组成部分, model(模型)、view(视图)、controller(控制器)
M 管理应用程序的状态,
C 接受外部用户的操做,根据操做访问模型获取数据
V 负责把数据格式化后呈献给用户
django 也是MVC的框架,可是在Django中,控制器接受用户输入的部分由框架自行处理,因此Django里更关注的是模型(Model),模块(Template)和视图(Views),成为MTV模式:
M 表明模型(Model) ,即数据存取层,该层处理与数据相关的全部事物:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
T 表明模板(Template), 即表现层,该层处理与表现相关的决定:如何在页面或者其余类型文档中进行显示
V 表明视图(View), 即业务逻辑层,盖层包含存取模型及调取恰当模块的相关逻辑,你能够把它看作模型与模块之间的桥梁。
小例,经过django orm 添加表,而后admin展现:
首先在dashboard这个app下的models.py添加表
from django.db import models # Create your models here. class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() def __unicode__(self): #这两行是为了在后台中以名字展示,否则不会显示建立的名称 return "<%s>"%(self.name) class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() def __unicode__(self): return "<%s,%s>"%(self.first_name,self.last_name) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return "<%s>"%(self.title)
表格建立完毕后须要在数据苦衷生成了
python manage.py makemigrations
python manage.py migrate
这样数据库中就会生成对应的表:
表建立完毕了,就须要在app下的admin.py中导入表的信息
from django.contrib import admin # Register your models here. import models admin.site.register(models.Author) admin.site.register(models.Book) admin.site.register(models.Publisher)
python manay.py createsuperuser ,建立可登陆admin后台的超级管理员用户
这样在访问http://59.110.12.72:33333/admin/ ,就能够在里面作一些对标的增、删、改、查 了
Django 数据库支持的字段类型:
详见:https://docs.djangoproject.com/en/1.9/ref/models/fields/
Django 中若是想要表格能够输入为空:
null = True 控制的是数据库能够为空
blank = True 告诉Django表格能够为空
而后再发布配置:
使标题显示中文
ORM对数据库进行操做
表中插入数据
python manage.py shell
>>> from dashboard.models import Publisher
>>> p1 = Publisher(name='Apress',address='USA',city='MHD',state_province='..',country='USA',website='www.baidu.com')
>>> p1.save() #这种方法,须要save()后才会添加到数据库
#下面这种方法,能够直接在添加到数据库
>>> p1 = Publisher.objects.create(name='laoboy',address='USA',city='MHD',state_province='..',country='USA',website='www.baidu.com')
这套命令对应这数据库操做的 insert
若是要改变其中某个字段的值,须要怎么操做呢?
p1.name = 'balabala'
p1.save()
这里保存的时候,是又从新把整个表保存了一遍。
查找对象
>>> Publisher.objects.all()
[<Publisher: <快网出版社>>, <Publisher: <Apress>>, <Publisher: <oldboy>>]
注意到Django在选择全部数据时并无使用 SELECT* ,而是显式列出了全部字段。 设计的时候就是这样:SELECT* 会更慢
>>> Publisher.objects.filter(name='oldboy')
[<Publisher: <oldboy>>]
一样,也支持,多条件过滤
>>> Publisher.objects.filter(name='oldboy',country='USA')
[<Publisher: <oldboy>>]
模糊查询
>>> Publisher.objects.filter(name__contains="boy") #中间是双横杠
[<Publisher: <oldboy>>]
获取单个对象并对齐修改
>>> Publisher.objects.get(name='oldboy')
<Publisher: <oldboy>>
>>> a = Publisher.objects.get(name='oldboy')
>>> a.name = 'oldboy2'
>>> a.save()
获取对象后进行排序
>>> Publisher.objects.order_by(
"name"
) #按照name来排序
>>> Publisher.objects.order_by(
"state_province"
,
"address"
) #第一项同样的,按照第二项来排序
>>> Publisher.objects.order_by(
"-name"
) #倒叙
排来排去有点麻烦,能够用meta来进行全局的排序
连锁查询
>>> Publisher.objects.
filter
(country
=
"U.S.A."
).order_by(
"-name"
)
[<Publisher: O'Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by(
'name'
)[
0
] #指向要帅选出来的第一条数据
<Publisher: Apress>
筛选到数据并修改:
删除对象
shell 中修改密码:
from django.contrib.auth.models import User u = User.objects.get(username='admin') #获得admin用户的对象 u.set_password('123') #设置密码 u.password #查看的密码就是加密后的 #添加新用户 u2 = User() u2.username = 'u2' u2.set_password('123') u2.save() #设置is_staff后即可以登陆后台系统了 u2.is_staff = True #django user登陆鉴权 from django.contrib.auth import authenticate test = authenticate(username='u2', password='123') #若是有值则存在,None则不存在
用户验证登陆的时候若是没有验证成功,django会有一个本身的rewritelogin的地址若是想要更改这个login的得知的话,则须要在settings配置文件中添加以下一行
LOGIN_URL = ‘/login’
django自带方法
一、login
from django.contrib.auth import login, authenticate user = authenticate(username='u2', password='123') login(request, user) #登陆
二、login_required
from django.contrib.auth.decorators import login_required @login_required def index(request): #装饰到函数前面 pass
xss: django为了安全机制,默认传递的都是字符串,好比来自浏览客户的评论,若是给写了个js脚本,抱歉那是不会执行的,只是按照字符串来对待
肯定安全的状况下,那如何让其对这字符串作解释呢?
方法:
一、前端 {{ page_str |safe}} //对后端传递过来的字符串做解释
二、后端 from django.utils.safestring import mark_safe
page_str = mark_safe(page) #对html的字符串作mark_safe后,再传递
手写一个分页:
def user_list(request): current_page = request.GET.get('p',1) #获取参数p,没有就默认为1 start = (current_page-1) * 10 end = current_page * 10 data = LIST[start:end] #LIST 想象为数据库获取的数据 all_count = len(LIST) count, yushu = divmod(all_count, 10) if y: count += 1 page_list = [] for i in range(1, count+1): temp = '<a href="/user_list/?p=%s>%s</a>"' %(i,i) page_list.append(temp) page_str = "".join(page_list) page_str = mark_safe(page_str) return render(request, 'user_list.html' , {'li': data, 'page_str': page_str})
CSRF, Cross Site Request Forgery, 跨站点伪造请求。举例来说,某个恶意的网站上有一个指向你的网站的连接,若是某个用户已经登陆到你的网站上了,那么当这个用户点击这个恶意网站上的那个连接时,就会向你的网站发来一个请求,你的网站会觉得这个请求是用户本身发来的,其实呢,这个请求是那个恶意网站伪造的。具体的细节及其危害见 wikipedia
机制:django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。而后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。
setting中开启csrf功能后,在没有作特殊处理的状况下会遇到下面的报错:
那如何解决这个问题呢?
一、form 表单提交的的时候须要添加上{% csrf_token %}
<form action="/cref/" method="post"> {% csrf_token %} <div> 用户名:<input type="text" name="username"> </div> <div> 密码:<input type="text" name="password"> </div> <div> <input type="submit" value="提交"> </div> </form>
二、若是是ajax请求呢?那就须要在请求的时候,在header中添加这么一行,headers:{'X-CSRFtoken':csrf_token},
<script> $(function () { $('#btn').click(function () { var csrf_token = $.cookie('csrftoken') $.ajax({ url:'/cref/', type:"POST", headers:{'X-CSRFtoken':csrf_token}, data : {'username':'admin','password':'123'}, success:function(){ } }) }) }) </script>
若是你的ajax不少,总是添加这么一行,那岂不是很麻烦呢?那只须要在开头添加一个ajaxSetup便可
$(function () {
$.ajaxSetup({
beforeSend:function (xhr,settings) {
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'))
}
});
$('#btn').click(function () {
var csrf_token = $.cookie('csrftoken')
$.ajax({
url:'/cref/',
type:"POST",
//headers:{'X-CSRFtoken':csrf_token},
data : {'username':'admin','password':'123'},
success:function(){
}
})
})
})
另外想一个问题,若是有100个views,只有其中 两个须要加这个需求,另外的都不加,再若是有两个加,其余的都不加呢?这里就涉及到全局和局部使之生效的问题
全局:
中间件 django.middleware.csrfViewMiddleware
局部:
使用runserver可使咱们的django项目很便捷的在本地运行起来,但这只能在局域网内访问,若是在生产环境部署django,就要多考虑一些问题了。好比静态文件处理,安全,效率等等,本篇文章总结概括了一下基于uwsgi+Nginx下django项目生产环境的部署
准备知识:
Django:一个基于python的开源web框架
uwsgi:一个基于自由uwagi协议、wsgi协议和http服务协议的web网关
nginx:经常使用的高性能代理服务器
wsgi.py : django项目携带的一个wsgi接口文件
项目流程
一、首先客户端请求服务资源,
二、nginx做为直接对外的服务接口,接收到客户端发送过来的http请求,会解包、分析,
三、若是是静态文件请求就根据nginx配置的静态文件目录,返回请求的资源,
四、若是是动态的请求,nginx就经过配置文件,将请求传递给uWSGI;uWSGI 将接收到的包进行处理,并转发给wsgi,
五、wsgi根据请求调用django工程的某个文件或函数,处理完后django将返回值交给wsgi,
六、wsgi将返回值进行打包,转发给uWSGI, uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端(如浏览器)。 *
注:不一样的组件之间传递信息涉及到数据格式和协议的转换
软件安装:
1.yum -y install gcc openssl openssl-devel
2.install python3
./configure --prefix=/usr/local --with-ssl
make && make install
3. istall pip3
url:https://github.com/pypa/pip/archive/1.5.5.tar.gz
python3 setup.py install
/usr/local/python3/bin pip 安装的命令都放到这个目录下
4.pip3 install uwsgi
5. install nginx
tar 包安装的ngin,须要本身添加快速启动脚本到 /etc/init.d/下
#!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # config: /etc/sysconfig/nginx # pidfile: /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/nginx/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval killall -9 nginx } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac
下面配置uwsgi.ini 文件
# hello_uwsgi.ini file [uwsgi] # Django-related settings socket = :9999 #这里须要配置的socket,若是是http的话,会有错误 #http = :9999 # the base directory (full path) chdir = /home/right/cache_check # Django s wsgi file module = cache_check.wsgi # process-related settings # master master = true # maximum number of worker processes processes = 4 #logto = /var/log/uwsgi/%n.log daemonize = /var/log/uwsgi/dango_uwsgi.log # ... with appropriate permissions - may be needed # chmod-socket = 664 # clear environment on exit vacuum = true plugin = python #harakiri = 12
添加uwsgi快速启动脚本
#!/bin/sh NAME="dango" if [ ! -n "$NAME" ];then echo "no arguments" exit; fi echo $NAME ID=`ps -ef | grep "$NAME" | grep -v "$0" | grep -v "grep" | awk '{print $2}'` echo $ID echo "################################################" for id in $ID do kill -9 $id echo "kill $id" done echo "################################################" uwsgi --ini /home/right/cache_check/dango_uwsgi.ini
添加nginx的配置
location / { include uwsgi_params; uwsgi_pass 127.0.0.1:9999; uwsgi_send_timeout 1600; # 指定链接到后端uWSGI的超时时间。 uwsgi_connect_timeout 1600; # 指定向uWSGI传送请求的超时时间,完成握手后向uWSGI传送请求的超时时间。 uwsgi_read_timeout 1600; # 指定接收uWSGI应答的超时时间,完成握手后接收uWSGI应答的超时时间。 #root html; #index index.html index.htm; #uwsgi_param SCRIPT_NAME; }
到这里配置完毕,能够运行了
能够添加新书,并显示
1 from django.db import models 2 3 # Create your models here. 4 5 class Publisher(models.Model): 6 name = models.CharField(max_length=30) 7 address = models.CharField(max_length=50) 8 city = models.CharField(max_length=60) 9 state_province = models.CharField(max_length=30) 10 country = models.CharField(max_length=50,null=True) 11 website = models.URLField() 12 def __unicode__(self): 13 return "<%s>"%(self.name) 14 15 class Author(models.Model): 16 first_name = models.CharField(max_length=30) 17 last_name = models.CharField(max_length=40) 18 email = models.EmailField() 19 def __unicode__(self): 20 return "<%s,%s>"%(self.first_name,self.last_name) 21 22 class Book(models.Model): 23 title = models.CharField(max_length=100) 24 authors = models.ManyToManyField(Author) 25 publisher = models.ForeignKey(Publisher) 26 publication_date = models.DateField() 27 def __unicode__(self): 28 return "<%s>"%(self.title)
#!/usr/bin/python #coding:utf-8 from django.shortcuts import render from django.http import HttpResponse from django.template import Context,loader from django.contrib.auth import authenticate,login,logout import models # Create your views here. def booklist(request): if request.method == 'POST': book_name = request.POST.get('name') publisher_id = request.POST.get('publisher_id') author_ids = request.POST.get('author_ids') print 'books`s name from post -->',request.POST.get('name') print 'publisher_id from post-->',request.POST.get('publisher_id') print 'author_ids from post-->',request.POST.get('author_ids') new_book = models.Book( title = book_name, publisher_id = publisher_id, publication_date = '2016-05-22' ) new_book.save() new_book.authors.add(*author_ids) #表中多对多,须要另外插入 books = models.Book.objects.all() publisherlist = models.Publisher.objects.all() authorlist = models.Author.objects.all() return render(request, 'books.html',{'books':books,'publisher':publisherlist,'authorlist':authorlist} )
1 <!DOCTYPE html> 2 <html lang="en" xmlns="http://www.w3.org/1999/html"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>booklist</title> 6 <style books_name></style> 7 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" > 8 <style> 9 .book_form{margin-top:10px;} 10 </style> 11 </head> 12 <body> 13 <div class="container"> 14 </br> 15 <ul> 16 {% for book in books %} 17 <li>{{book.title}}</li> 18 19 {% endfor%} 20 </ul> 21 22 </br> 23 <form method='post' action='/dashboard/books/'> 24 <div class="col-xs-4"> 25 输入书名<input type="text" class=" input-sm form-control" name='name' > 26 </div> 27 </br> 28 <div class="col-xs-2"> 29 <select class="input-sm form-control" name="publisher_id"> 30 <option >请选择出版社</option> 31 {% for banshe in publisher%} 32 <option value='{{banshe.id}}'>{{banshe.name}}</option> 33 {% endfor%} 34 35 </select> 36 37 </div> 38 <div class="col-xs-4"> 39 <select multiple class="form-control" name='author_ids'> 40 {% for auth in authorlist%} 41 <option value='{{auth.id}}'>{{auth.first_name}}</option> 42 {% endfor %} 43 </select> 44 </div> 45 46 <input type="submit" value="建立新书"> 47 </form> 48 </div> 49 </body> 50 </html>
总结一
用户登陆,前端用户ajax请求登陆,后端验证,翻过json给前端,前端经过状态码来判断作什么操做
涉及的内容:django login, authenticate, login_required , ajax请求, from表单
from django.http import HttpResponse, JsonResponse from django.http.response import JsonResponse from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib.auth.decorators import login_required @login_required def index(request): return render(request, 'index.html') def mylogin(request): user_info = { 'dachengzi':{'pwd':'123'}, 'kangbazi':{'pwd':'123'} } if request.method == 'GET': print('I am here') return render(request, 'pages/examples/login.html') elif request.method == 'POST': print('I am post request!') username = request.POST.get('username') password = request.POST.get('password') print(username,password) res = authenticate(username=username, password=password) res_json = {} if res is not None: login(request,res) res_json['status'] = 0 else: res_json['status'] = 1 return JsonResponse(res_json)
<form action="#" > //防止from自动get请求,这里填入# <div class="form-group has-feedback"> <input id="username" class="form-control" placeholder="Email"> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> </div> <div class="form-group has-feedback"> <input id="password" type="password" class="form-control" placeholder="Password"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <div class="row"> <div class="col-xs-8"> <div class="checkbox icheck"> <label> <input type="checkbox"> Remember Me </label> </div> </div> <!-- /.col --> <div class="col-xs-4"> <button id="submit" type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button> </div> <!-- /.col --> </div> </form> <script> $('#submit').click(function () { username = $('#username').val() password = $('#password').val() $.ajax({ type:"POST", url:"/login/", data:{username:username, password:password}, dataTpye:"json", success:function (data1) { status = data1.status if(status ==0){ location.href='/' }else{ console.log('error') } } }) }) </script>