第六章Django

web應用程序html

server端創建socket,不斷地accept,當收到客戶端鏈接信號以後,服務端向客戶端發送數據,將html網頁打開,read出來,併發送至客戶端,這樣客戶端就能夠瀏覽到網頁的內容python

 

http協議:mysql

包頭裏面的數據用 一個「\r\n」來區分,最後使用兩個「\r\n」來區分數據git

GET協議把數據放在了包頭裏面,POST協議把數據放在包頭的最後面web

GET提交的數據以「?」區分,參數之間以「&」進行鏈接ajax

 

相應格式:正則表達式

協議版本 狀態碼 狀態碼的緣由短語 相應首部字段 主體sql

 

web框架 yuan功能總結

main.py: 啓動文件,封裝了socket

1 urls.py: 路徑與視圖函數映射關係 ---- url控制器

2 views.py 視圖函數,固定有一個形式參數:environ -----視圖函數,

3 templates文件夾: html文件 -----模板

4 models: 在項目啓動前,在數據庫中建立表結構 ----- 與數據庫相關



Django的安裝與啓動
建立應用:python manage.py startapp blog

urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/([0-9]{4})/$', views.year_archive),
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

有名分組:在組前面加上?P<組名> 便可,在傳參時的形參必須是「組名」,不然會出錯
 


命名空間:namespace
app01.urls:
須要加上
app_name = "app01"
urlpatterns=[
re_path(r'^index/',views.index,name="index"),
]

同理在ap02.urls加上相同的配置

views.py:
def index(request):
return HttpResponse(reverse("app01:index"))
須要加上反向解析


註冊自定義轉換器
先建一個類
class FourDigitYearConverter:
regex = '[0-9]{2}' #正則表達式的公式

def to_python(self,value):
return int(value)

def to_url(self,value):
return '%04d' % value

在項目中註冊轉換器
# 註冊定義的url轉換器
register_converter(FourDigitYearConverter,'mm') #FourDigitYearConverter : 爲以上類名

以後在urls裏能夠直接path使用
path('articles/<mm:month>/',views.month_archive)


模板語法 只有兩個
1.{{}}
能夠在
return render(request,'index.html',locals()) 這樣就把該函數裏的所有全局變量都傳過去了
同時在index.html能夠經過 . 來過去數據 如一個數組l=【‘123’,‘456’,‘789’】 ,在html能夠經過l.2 獲取到數據456

2{%%}
{%if%}

{%endif%}

自定義標籤與過濾器
1.在settings的INSTALLED_APPS加上當前app的名稱,否則django沒法找到自定義的simple_tag.
2.在app文件夾裏面添加templatetags模塊(模塊名只能是templatetags)
3.在templatetags裏面建立任意py文件
4.在該py文件裏面引入
from django import template
register = template.Library()  # 固定名字
@register.filter          #加上裝飾器,這個爲模板過濾器
def filter_multi(x,y):
return x*y

@register.simple_tag #標籤過濾器
def filter_tag(x,y):
return x*y
5.在html文件裏面讀取該過濾器
{%load py的文件名%}
6.使用
{{ 2 | filter_multi:5 }}

{% filter_tag 5 6 %}

繼承:extends
在一個base.html 裏面把模板寫好
在另外一個html裏面引入base.html
{% extends "base.html" %}
這時候能夠在下面繼續添加block裏面的內容
{{% block title %}
<title>第一個</title>
{% endblock title%}

模型層ORM
ORM 對象-關係-映射
經過編寫ORM層,控制pysql轉換成db語句,再去控制db數據庫。py文件裏面經過建立一個類


生成表模型
1.建立模型
from django.db import models

# Create your models here.

class Book(models.Model):
     id = models.AutoField(primary_key=True)
     title=models.CharField(max_length=32)
     state=models.BooleanField()
     pub_date=models.DateField()
     price=models.DecimalField(max_digits=8,decimal_places=2)
     publish=models.CharField(max_length=32)

建立一個app,而後在app項目文件下的models下建立類數據庫

2.配置連接數據庫settingsdjango

在項目文件下的settings文件設置下,設置數據庫信息

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'bms',                #建立數據庫名字
        'USER':'root',         #連接數據庫用戶名
        'PASSWORD':'',         #連接數據庫密碼
        "HOST":'127.0.0.1',      #目標數據庫地址
        'PORT':3306           #目標數據庫端口
    }
}

  

3.確認信息

①在項目app文件下的__init__插入代碼:
import pymysql

pymysql.install_as_MySQLdb()
 

 

②確保配置文件中的INSTALLED_APPS中寫入咱們建立的app名稱

如在installed_apps 下添加app文件名


最後,能夠進行數據遷移
python manage.py makemigrations
python manage.py migrate

  


數據庫的創建create:
方式一:
book_obj = Book.objects.create(title='第一個數據庫',state=True,price=500,pub_date="2012-12-12",publish='人民出版社')    #裏面的數據格式須要與創建時的數據格式一致

方式二:
book_obj = Book(title='方式二',publish='機械出版社',state=True,pub_date="2010-12-11",price=10.12)
book_obj.save()                    #須要多一個save
 
查詢表:
Django 本身生成的一個數據對象:QuerySet: [obj1,obj2,obj3....]
能夠經過語句Book.object ---> 生成QuerySet數據
Book.object.all() 能夠讀取全部的數據

values方法: 返回和調用都是QuerySet
book_obj = Book.objects.values('price')
至關於
list = []
for obj in QuerySet:
  list.append{'price':obj['price']}
  .... #若是在values後面加值,就繼續append

values_list方法:  
返回和調用都是QuerySet
book_obj = Book.objects.values_list('price')


distinct:去重 從返回結果中剔除重複紀錄


表的查詢

一對多的查詢:
A---B
若是關聯表在A表中:
A----->B :正向查詢
反過來經過B去查A 則是反向查詢,主要看關聯表在哪張表裏面
正向查詢:看字段
反向查詢:看錶名:表名小寫__set.all()


聚合與分組查詢
關鍵字:
annotate

總結 跨表的分組查詢的模型:
# 每個後表模型.objects.values("pk").annotate(聚合函數(關聯表__統計字段))
 

AJAX
特色:
1.使用JavaScript向服務器發送異步請求
2.局部刷新

$(".Ajax").click(function () {
$.ajax({
url:"/test_ajax/", //請求地址
type:"get", //請求的類型poet或者是get
success:function (data) {
$(".haha").html(data)
console.log(data)
}
})
})


數據之間的傳輸 經過使用json序列化
在py裏面使用json.dump序列化
在Ajax裏面使用JSON.parse 反序列化進行解析


利用Form表單進行文件上傳

def file_put(request):
    if request.method=="POST":
        print('123')
        print(request.POST)
        print(request.FILES)

        file_obj = request.FILES.get("tou")

        with open(file_obj.name,'wb') as f:
            for i in file_obj:
                f.write(i)

        return HttpResponse('OK')

    return render(request, "file_put.html")

 

批量導入數據庫的數據:
'''
    批量導入數據:

    Booklist=[]
    for i in range(100):
        book = Book(user="book_%s"%i,pwd=i*i)
        Booklist.append(book)
    Book.objects.bulk_create(Booklist)
    '''

 

 

分頁器:

book_list = Book.objects.all()

    paginator = Paginator(book_list,10)

    print("count:", paginator.count)  # 數據總數
    print("num_pages", paginator.num_pages)  # 總頁數
    print("page_range", paginator.page_range)  # 頁碼的列表

    page1=paginator.page(4)     #第4頁的page對象數據
    for i in page1:             #遍歷
        print(i)

    print(page1.object_list)    #直接拿出該page的全部對象

  
  #捕捉EmptyPage錯誤信息時作的處理
  try:
  current_page = int(request.GET.get("page",1))
  page1 = paginator.page(current_page)
  except EmptyPage as e:
  page1 = paginator.page(1)
 

 

 

 print(page2.has_next())            #是否有下一頁
    print(page2.next_page_number())    #下一頁的頁碼
    print(page2.has_previous())        #是否有上一頁
    print(page2.previous_page_number()) #上一頁的頁碼

 

 

 

form組件

 

form.is_valid()   #:返回布爾值
form.cleaned_data #:{"name":"yuan","email":"123@qq.com"} 返回匹配成功的字典
form.errors      #返回對應類字段的錯誤信息 :{"name":[".........."]}

 

 

 
 
from django.forms import widgets
class UserForm(forms.Form):                              #用於認證用
    name = forms.CharField(max_length=32,label="用戶名", widget=widgets.TextInput(attrs={"class":"form-control"}),error_messages={「required」:「該字段不能爲空」})   #attr即爲修改樣式,error_message修改默認的錯誤信息,必須爲required這個鍵名
    pwd = forms.CharField(min_length=4)
    r_pwd = forms.CharField(min_length=4)
    email = forms.CharField()
    tel = forms.CharField(min_length=4,max_length=32)


def form_test(request):
    if request.method == 'POST':
        form = UserForm(request.POST)
        if form.is_valid():             #校驗是否驗證經過,同時會把錯誤、正確的信息放在兩個字典裏面
            print(form.cleaned_data)
        else:
            print(form.cleaned_data)
            print(form.errors)  # ErrorDict : {"校驗錯誤的字段":["錯誤信息",]}
            print(form.errors.get("name"))  # ErrorList ["錯誤信息",]
        return HttpResponse("OK")
        form = UserForm()
        return render(request, "form_test.html", locals())

    form = UserForm()

    return render(request,"form_test.html")

 

在html裏面想打印錯誤信息,能夠{{form.name.errors}}  這樣能夠獲取name裏的錯誤信息

 

利用form表單組件 進行文件上傳,使用FormData

$(".login_btn").click(function () {
        var form_data = new FormData();         //首先實例化一個FormData
        form_data.append("user",$("#id_user").val())    //再往裏面添加數據
        form_data.append("pwd",$("#id_pwd").val())
        form_data.append("r_pwd",$("#id_r_pwd").val())
        form_data.append("email",$("#id_email").val())
        form_data.append("img",($("#avater")[0].files[0]))     //該爲文件,主要是傳它才使用FormData,否則不用這麼麻煩
        form_data.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val())

        $.ajax({
            url:"",
            type:"post",
            contentType:false,     //必須設置這兩個值
            processData:false,
            data:form_data,         //最後把這個對象傳給data
            success:function (data) {
                console.log(data)
            }
        })
    })

 

 

局部鉤子

在規則裏面class 添加一個方法"clean_%s"name

 def clean_tel(self):
        val = self.cleaned_data.get('tel')

        if len(val) == 11:
            return val
        else:
            raise ValidationError("手機號格式錯誤")

form.is_valid--》self.errors-->self.full_clean--》self._clean_fields()
依次校驗每一個字段,以後再走鉤子去判斷裏面有沒有clean_%s 用戶自定義的方法

if hasattr(self, 'clean_%s' % name):
    value = getattr(self, 'clean_%s' % name)()
    self.cleaned_data[name] = value

 

 

全局鉤子

    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        r_pwd = self.cleaned_data.get('r_pwd')

        if pwd and r_pwd:
            if pwd == r_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('兩次密碼不一致!')
        else:
            return self.cleaned_data

 

 

視圖函數 form_test.html

<div class="container">
    <form action="" method="post">
        {% csrf_token %}
        <div class="row">
            <div>
                <p>
                {{ form.name.label }}{{ form.name }}<span>{{ form.name.errors }}</span><span class="has-error pull-right">{{ errors.0 }}</span>  #errors類 本身寫
                </p>
            </div>
            <div>
                <p>
                {{ form.pwd.label }}{{ form.pwd }}<span>{{ form.pwd.errors }}</span>
                </p>
            </div>
            <div>
                <p>
                {{ form.r_pwd.label }}{{ form.r_pwd }}<span>{{ form.r_pwd.errors }}</span><span class="pull-right error">{{ errors.0 }}</span>
                </p>
            </div>
            <div>
               <p>
                {{ form.email.label }}{{ form.email }}<span>{{ form.email.errors }}</span>
                </p>
            </div>
            <div>
                <p>
                {{ form.tel.label }}{{ form.tel }}<span>{{ form.tel.errors }}</span>
                </p>
            </div>
            <input type="submit" value="提交">

 

 

cookie:具體一個瀏覽器針對一個服務器存儲key-value({})

獲取cookie:

cookie 信息儲存在request.COOKIE

相關文章
相關標籤/搜索