Python Django

本章內容:css

 

 

參考文檔

  環境搭建及基礎配置html

  URL設置前端

  Django快速Web開發——模型(基礎)python

  Django快速Web開發——模型(高級)mysql

  Django快速Web開發——管理後臺jquery

  Django中文文檔nginx

  Django 1.11.6 文檔c++

  

 

Django 安裝

參考文檔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 實例

django-admin startproject opsweb        #生成opswed項目

  項目目錄結構

    

  

 

  運行第一個小實例:

  須要提早在settings.py裏修改這一行: ALLOWED_HOSTS = ["*"]  

python manage.py runserver 0.0.0.0:33333

  

  這裏運行的時候遇到一個報錯:

  ImportError: No module named security

  這個是因爲我在virtualenv環境下建立的這個項目,執行的時候卻退出了,須要進入後再執行。

 

django app 實例 

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函數。

 

django HttpRequest 對象

  視圖函數中的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()

 

django HttpResponse對象

  傳遞一個字符串做爲頁面的內容到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這個是不能用的!

 

 

django JsonResponse對象

  支持傳遞list,dict

  return JsonResponse([1,2,3], safe = False)

 

 

django QueryDict對象

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較不適用,建議使用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!')
views 函數
 <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>
Ajax 異步登陸

 

 

project 添加一個目錄而且可識別

  又名靜態文件配置

  

  添加static目錄,須要添加setting裏面的

STATIC_URL = '/static/' 
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
 )

  這樣,就能夠在templates目錄下的html文件中引用這個url了

  

 

django 路由系統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')
url.py
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
view.py
action = {% url "i1" %}
{% url "i3"  1 2 %}
{% url  'i3' pid=1  nid = 9%}
html

 

 

 django Views

  視圖獲取用戶相關請求信息,以及請求頭。

  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)
View中三元運算寫法

 

 

django Template

  模板繼承:有時候許多頁面有許多類似之處,爲了書寫簡單就能夠用到末班繼承,

  被繼承文件  layer.html  ,寫好公共的內容, {% block content %}   {% endblock %}   這個裏面是繼承的頁面中須要本身書寫的東西

  繼承的文件  a.html     {% extends 'layer.hmlt' %}    #說明下這個內容是從哪裏繼承的

            {%  block  content  %}   書寫本身的代碼   {%   endblock  %}  ,固然能夠寫多塊內容

 

  模板導入:別人寫好的代碼塊,咱這個頁面上面須要導入,好比淘寶上面的每一個產品的塊

         a.html b.html  這些都是一個個小的產品,這時候須要在主頁面導入

          {%   include  「a.html」 %}

        {% include "b.html" %}

 

 

django Simple_tag/filter

      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:「第二個參數」  %}     //注意中間不能有空格

 

django cookie

  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,分頁

  cookie 加salt

  obj = HttpResponse('s')

  obj.set_signed_cookie('username', "kangbazi", salt='abcdefg')             #加鹽加密

  request.get_signed_cookie('username', salt='abcdefg')            #用鹽解密      

 

 

django session

  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,默認修改以後才保存(默認)

 

 

django 連接數據庫

  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')

 

session 與 cookie的區別

 

  1,session 在服務器端,cookie 在客戶端(瀏覽器)
  2,session 默認被存在在服務器的一個文件裏(不是內存)
  3,session 的運行依賴 session id,而 session id 是存在 cookie 中的,也就是說,若是瀏覽器禁用了 cookie ,同時 session 也會失效(可是能夠經過其它方式 實現,好比在 url 中傳遞 session_id)
  4,session 能夠放在 文件、數據庫、或內存中均可以。
  5,用戶驗證這種場合通常會用 session

django流程介紹

   

  兩種架構:

  MVC

    即將程序分爲三個組成部分, model(模型)、view(視圖)、controller(控制器)

    M  管理應用程序的狀態,

    C  接受外部用戶的操做,根據操做訪問模型獲取數據

    V  負責把數據格式化後呈獻給用戶

 

  django 也是MVC的框架,可是在Django中,控制器接受用戶輸入的部分由框架自行處理,因此Django裏更關注的是模型(Model),模塊(Template)和視圖(Views),成爲MTV模式:

    M  表明模型(Model) ,即數據存取層,該層處理與數據相關的全部事物:如何存取、如何驗證有效性、包含哪些行爲以及數據之間的關係等。

    T  表明模板(Template), 即表現層,該層處理與表現相關的決定:如何在頁面或者其餘類型文檔中進行顯示

    V  表明視圖(View), 即業務邏輯層,蓋層包含存取模型及調取恰當模塊的相關邏輯,你能夠把它看作模型與模塊之間的橋樑。 

 

 

Djiango 數據庫 ORM

  小例,經過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>
    至關於mysql的
    

    篩選到數據並修改:

    

    刪除對象

    

 

 

django shell  操做/自帶方法

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

 

 

 

django分頁功能

  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})
分頁

 

 

 django csrf

  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>
csrf_token

  二、若是是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

  若是你的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(){

                    }
                })

            })
        })
many_ajax

 

   另外想一個問題,若是有100個views,只有其中 兩個須要加這個需求,另外的都不加,再若是有兩個加,其餘的都不加呢?這裏就涉及到全局和局部使之生效的問題

  全局:

    中間件 django.middleware.csrfViewMiddleware

  局部:

  • @csrf_protect, 爲當前的幻術強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件
  • @csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件    

   

 

 

django + uwsgi + nginx 啓動 

  使用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
nginx_restat.sh

 

  下面配置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)
models.py
#!/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} ) 
views.py
 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>
前端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)
views.py
<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>
html
相關文章
相關標籤/搜索