day17-Django進階及orm

day17 2018-08-12 

Django框架02

1. 今日內容:
    1. 新建Django項目梳理
        1. 模板文件路徑配置
        2. 數據庫配置
        3. 靜態文件配置
        4. 註釋掉csrf中間件那一行
    2. Django默認sqlite3數據庫的簡單用法
    
    3. 路由系統進階:https://www.cnblogs.com/liwenzhou/articles/8271147.html
        - 動態路由
        urls.py中經過正則表達式的分組匹配,捕獲用戶訪問的url中的值,傳遞給視圖函數
        分組匹配:
            至關於給視圖函數傳遞 位置參數
        分組命名匹配:
            至關於給視圖函數傳遞 關鍵字參數
        
        - name
            防止將url硬編碼到咱們的業務邏輯代碼中,給url起別名
            經過別名,反向找到 url
            在views.py中:
                from django.urls import reverse
                具體的url = reverse('url別名')
                    
    4. 視圖函數進階:https://www.cnblogs.com/liwenzhou/articles/8305104.html
        1. views.py
            1. 基礎必會三件套
                1. HttpResponse('字符串')
                2. render(request, "xx.html", {"key": value})
                3. redirect("/其它的url/")
            2. FBV(Function Base View) 基於函數的視圖
                經過request.method == "POST" 去判斷
                
            3. CBV(Class Base View)    基於類的視圖
                1. 必須繼承views.View     --> from django import views
                2. 寫一個本身的視圖類
                3. 經過定義不一樣的方法,來處理用戶不一樣的請求
                4. 在urls.py中註冊視圖的時候要寫 views.類名.as_view()
        2. request對象的經常使用屬性和方法
            request表示的是和用戶請求相關的全部數據
            1. request.method       --> 用戶當前請求的請求方法
            2. request.GET          --> 用戶請求中url中的參數
            3. request.POST         --> 用戶POST請求的數據
            4. request.path_info    --> 用戶訪問的url路徑是什麼
            
        3. Django上傳文件
            1. 前端頁面
                1. form表單必定要有action,method必須是post
                2. 必定要配置enctype="multipart/form-data
            2. 後端:
                 def post(self, request):
                    # 拿到用戶發送的文件數據
                    file_obj = request.FILES.get("code")
                    # 保存下來
                    # 1. 拿到用戶上傳的文件名
                    filename = file_obj.name
                    # 2. 在服務端建立一個同名的文件
                    with open(filename, "wb") as f:
                        # 3. 從用戶上傳的文件對象中一點一點讀數據,往我本地建立的文件句柄裏一點一點寫
                        for i in file_obj.chunks():
                            f.write(i)
                    return HttpResponse("上傳成功!")
        
        4. JsonResponse
            專門用來返回JSON格式數據的響應對象
            from django.http import JsonResponse
            
     5. 模板引擎進階:https://www.cnblogs.com/liwenzhou/p/7931828.html
        1. 已經學過的Django模板語言的語法
            1. 兩個語法:
                1. {{ }}    --> 跟變量相關的操做
                2. {% %}    --> 跟邏輯相關的操做
            2. 變量相關
                1. 傳字典或對象類型的數據     obj.name/obj.age
                2. 傳數組類型的數據           obj.索引值
            3. 日期格式化
                <p>{{ today|date:"Y-m-d H:i:s"}}</p>
            4. 顯示真正的html代碼
                <p>{{ link|safe }}</p>
        2. 母板
            1. 爲何要用母版?
                不一樣的頁面有大量重複的代碼,咱們能夠把公用的部分提取出來放在單獨一個文件
            2. 怎麼使用?
                1. 在子頁面 經過使用 {% extends ‘模板名’ %}   --> 放在子頁面的最上面
                2. {% block xx %}{% endblock %}
        3. 組件
            把單獨的一段html代碼放在一個文件
            使用 {% include '組件名' %}導入
            
    6. CSRF
        1. 爲何要有csrf_token?
        2. Django中如何使用?
            在render的頁面上寫上{% csrf_token %}
        3. 若是是form表單形式提交,必須放在form表單中    
            
            
    7. ORM單表查詢13條+外鍵操做(一對多):
        1. ORM上週知識點:
            1. 查詢
                1. 查全部
                    models.Publisher.objects.all()
                2. 查某個具體的記錄
                    models.Publisher.objects.get(id=1)   --> 注意查詢條件不成立就報錯
            2. 刪除一條記錄
                models.Publisher.objects.get(id=1).delete()
            3. 建立一條記錄
                models.Publisher.objects.create(name="新出版社名字", addr="出版社地址") 
            4. 修改一條記錄
                obj = models.Publisher.objects.get(id=1)
                obj.name = "新名字"
                obj.save()
            

        2. 字段和參數:  https://www.cnblogs.com/liwenzhou/p/8688919.html
            1. 上週字段和參數:
                1. models.AutoField(primary_key=True)
                2. models.CharField(max_length=32)
                
            2.     經常使用字段和參數
                1. 字段
                    1. CharField
                    2. AutoField
                    3. DateField
                    
                    4. DateTimeField()
                    5. IntergeField()
                2. 參數
                    1. null=True
                    2. default=默認值
                    3. unique=True
                    4. 時間字段
                        1. auto_now_add=True    第一次建立時
                        2. auto_add=True        每次更新時
            
            3. ORM必知必會單表查詢13條
                1. all()                             --> 查詢全部結果
                2. filter()                          --> 根據查詢條件查詢數據庫的
                3. get()                             --> 獲取一個惟一的值
                4. exclude()                         --> 將符合條件的都剔除掉,留下不符合條件的
                5. values('字段名', ...)             --> 返回一個QuerySet,裏面是字典
                6. values_list(字段名', ...)         --> 返回一個QuerySet,裏面是元祖
                7. order_by()                        --> 對查詢結果排序
                8. reverse()                         --> 對一個有序的查詢結果集作反轉
                9. distinct()                        --> 去重,跨表查詢時去掉重複的記錄,MySQL不支持按字段去重
                10. count()                          --> 返回數據條數
                11. first()                          --> 取第一個數據
                12. last()                           --> 取最後一條數據
                13. exists()                         --> 判斷表裏有沒有數據
                
                
                分類:
                    1. 返回QuerySet列表的有哪一些?
                        1. all()
                        2. filter()
                        3. exclude()
                        4. order_by()
                        5. reverse()
                        6. distinct()
                        
                        7. values('字段名', ...)     --> 查詢結果的列表裏,都是字典
                        8. values_list(字段名', ...) --> 查詢結果的列表裏,都是元祖
                        
                    2. 返回具體對象的
                        1. first()
                        2. last()
                        3. get()
                        
                    3. 返回數字的
                        1. count()
                    4. 返回布爾值
                        1. exists()
                
            4. 單表查詢神奇的雙下劃線
                查詢操做:https://www.cnblogs.com/liwenzhou/p/8660826.html
                
                1. 外鍵 ForeignKey 
                    經過Foreignkey字段 ,可以獲得和我關聯的那個對象
                    數據庫中保存的字段名是 外鍵字段_id
                2. 外鍵增刪改查
                3. 跨表查詢
                    1. 基於對象的查詢
                        1. 正向查
                        2. 反向查
                    2. 基於QuerySet的查詢
                        1. 正向查
                        2. 反向查
                    
                    
    8. cookie&session:https://www.cnblogs.com/liwenzhou/p/8343243.html
        1. Cookie
            1. 是什麼?
                保存在瀏覽器端的鍵值對!
                服務端在返回響應的時候,告訴瀏覽器保存的鍵值對!瀏覽器能夠拒絕保存Cookie.
                
            2. 爲何要有cookie?
                HTTP請求是無狀態的,咱們須要保存狀態  --> cookie 
                
            3. Django中cookie的使用
                1. 設置cookie
                    rep = HttpResponse("ok")
                    rep.set_cookie("key", "value", max_age=xx秒)
                    rep.set_signed_cookie("key", "value", salt="ooxx", max_age=xx秒)
                2. 獲取cookie
                    request.COOKIES.get("key")
                    request.get_signed_cookie("key", default="", salt="ooxx")
                3. cookie有失效時間
                    1. Django中不設置,關閉瀏覽器就失效了
                    2. 經過max_age設置超時時間
                    
            4. 補充3點:
                1. 如何登錄後再跳轉回以前訪問的頁面    --> next參數實現
                2. 如何將FBV的裝飾器應用到CBV上        --> from django.utils.decorators import method_decorator
                3. 裝飾器修復技術                      --> from functools import wraps
        
        
        2. session
            1. 保存在服務端的鍵值對!
            下週講!
            

2. 練習題:
    1. django請求生命週期
    2. values和values_list的區別?
    3. session和cookie是什麼?以及區別?
    4. django路由系統中name的做用?
    5. filter和exclude的區別?
    6. ORM查詢示例:
        表結構:
            出版社表:
                ID   名稱
            圖書表:
                ID   書名稱    價格     出版社ID
        題目:
            1. 查詢老男孩出版社出版過的價格大於200的書籍
            2. 查詢全部以py開頭的書籍名稱
            3. 查詢價格爲50,100或者150的全部書籍名稱及其出版社名稱
            4. 查詢價格在100到200之間的全部書籍名稱及其價格
            5. 查詢全部人民出版社出版的書籍的價格(從高到低排序,去重)
            6. 查詢價格大於200的書籍的個數
            7. 查詢價格不等於100的全部書籍


3. 做業:主機管理【02】:主機管理
    1. 基於django建立表:
        用戶表:ID、用戶名、密碼
        
        業務線表:ID、名稱
        
        主機表:ID、主機名、密碼、業務線ID
        
    2. 主機管理:增刪改查(一對多,不須要作業務線管理,只要在數據庫錄入業務線數據便可)
    
    3. 使用母板和動態路由
    4. 套用BootStrap樣式

    採分點:
        練習題:20
        實現全部功能:70
        代碼寫的清晰、健壯、可擴展:10
課上筆記
sqlite3文件數據庫,點開便可使用
sqlite3數據庫添加時間類型 可能有問題。

urls---views(寫函數)----html

1、路由系統
1.Django的路由系統;用戶請求與url'內容中是否匹配

2.正則表達式

動態匹配路由的方式傳參數
分組匹配------------^edit_publisher/(\d+)/$
url(r'^admin/', admin.site.urls),
url(r'^publisher_list/$', views.publisher_list, name="alex"),
url(r'^edit_publisher/(?P<edit_id>\d+)/$', views.EditPublisher.as_view(), name="alex"),
url.py
def edit_publisher(request):
    if request.method == "POST":
        # 接收用戶提交過來的數據
        edit_id = request.POST.get("id")
        new_name = request.POST.get("name888")
        # 去數據庫修改出版社名字
        obj = models.Publisher.objects.get(id=edit_id)
        obj.name = new_name
        obj.save()
        return redirect("/publisher_list/")
    # 取url攜帶的參數
    print(request.GET.get("id"))
    edit_id = request.GET.get("id")
    # 去數據庫找編輯的出版社
    publisher_obj = models.Publisher.objects.get(id=edit_id)

    return render(request, "edit_publisher.html", {"obj": publisher_obj})
不使用動態路由views
def edit_publisher(request, edit_id):
    print(reverse('alex'))
    print("=" * 120)
    if request.method == "POST":
        new_name = request.POST.get("name888")
        # 去數據庫修改出版社名字
        obj = models.Publisher.objects.get(id=edit_id)
        obj.name = new_name
        obj.save()
        return redirect(reverse('alex'))
    print(edit_id)
    publisher_obj = models.Publisher.objects.get(id=edit_id)
    return render(request, "edit_publisher.html", {"obj": publisher_obj})
分組命名匹配views-FBV
分組命名匹配---^edit_publisher/(?P<edit_id>\d+)/$

分組匹配:
至關於給視圖函數傳遞 位置參數
分組命名匹配:
至關於給視圖函數傳遞 關鍵字參數css


?P<pk>給分組取一個名字 將捕獲的值當成關鍵字參數傳入
修改list html中a標籤編輯、刪除取值路徑
reverse
# CBV
class EditPublisher(views.View):
    def get(self, request, edit_id):
        publisher_obj = models.Publisher.objects.get(id=edit_id)
        return render(request, "edit_publisher.html", {"obj": publisher_obj})

    def post(self, request, edit_id):
        new_name = request.POST.get("name888")
        # 去數據庫修改出版社名字
        obj = models.Publisher.objects.get(id=edit_id)
        obj.name = new_name
        obj.save()
        return redirect(reverse('alex'))
分組匹配的views-CBV


2、視圖函數
1.import views 是dj中自帶的函數
cbv views.類名.as_view()

2,dj上傳文件 ,

1. 前端頁面
1. form表單必定要有action,method必須是post
2. 必定要配置enctype="multipart/form-datahtml

2.後端:chunks()不寫也可實現功能,此功能是django提供的方法,通常寫上。前端

# Django上傳文件示例
class Upload(views.View):
    def get(self, request):
        return render(request, "upload.html")

    def post(self, request):
        # 拿到用戶發送的文件數據
        file_obj = request.FILES.get("code")
        # 保存下來
        # 1. 拿到用戶上傳的文件名
        filename = file_obj.name
        # 2. 在服務端建立一個同名的文件
        with open(filename, "wb") as f:
            # 3. 從用戶上傳的文件對象中一點一點讀數據,往我本地建立的文件句柄裏一點一點寫
            for i in file_obj.chunks():
                f.write(i)
        return HttpResponse("上傳成功!")
上傳文件views
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上傳文件</title>
</head>
<body>

<form action="/upload/" method="post" enctype="multipart/form-data">
    <input type="file" name="code">
    <input type="submit" value="提交">
</form>
</body>
</html>
upload.html

json格式的數據---相似於{‘code’:0,'data':'alex'}
from django.http import JsonResponse
# 返回JSON格式數據
class JsonTest(views.View):
    def get(self, request):
        res = {"code": 0, "data": "alex"}
        res2 = ["alex", "污Sir", "金老闆", "小姨媽", "MJJ"]
        # 1. 先將字典序列化成json格式的字符串
        # import json
        # s = json.dumps(res2, ensure_ascii=False) #ensure_ascii=False確保輸出漢字
        # return HttpResponse(s)
        return JsonResponse(res2, safe=False)  # 列表類型要寫safe=False
返回JSON格式數據

xss攻擊(跨站腳本攻擊) : js代碼--死循環

3、模板引擎

1. {{ }} --> 跟變量相關的操做
2. {% %} --> 跟邏輯相關的操做mysql

{% for teacher in data %}
        {% if forloop.last %}
            {{ teacher }}
        {% else %}
            {{ teacher }},
        {% endif %}
    {% endfor %}
例子

 

4. 顯示真正的html代碼
<p>{{ link|safe }}</p>jquery

import datetime

now = datetime.datetime.now()
print(now, type(now))
ret = now.strftime("%Y-%m-%d %H:%M:%S")  # 日期類型轉換爲字符串類型
print(ret, type(ret))
日期格式化

模板語言不支持連續判斷
不支持:{#<p>{% if 3 > 2 > 1 %}{% endif %}</p>#}

須要這樣寫:{#<p>{% if 3 > 2 and 2 > 1 %}{% endif %}</p>#}
默認找屬性,屬性優先級大於方法
# 測試模板語法
def template_test(request):
    data = ["金老闆", "景女神", "MJJ"]
    # data = ""
    filesize = 1234567890
    import datetime
    today = datetime.datetime.today()
    link = "<script>for(;;){alert(123)}</script>"

    class Person(object):
        def __init__(self, name, dream):
            self.name = name
            self.dream = dream

        def dream(self):
            return "個人夢想是學好Python!"

    pw = Person("彭瑋", "不去下一期!")

    return render(request, "t.html", {
        "data": data,
        "file_size": filesize,
        "today": today,
        "link": link,
        "person": pw
    })
測試模板語法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


{#<p>{{ data.1 }}</p>#}
<p>{{ data|default:"暫無數據" }}</p>
{##管道符先後及冒號先後不要加空格#}
<p>{{ file_size|filesizeformat }}</p>
<p>{{ today }}</p>
{#年月日時分秒#}
<p>{{ today|date:"Y-m-d H:i:s"}}</p>

<p>{{ link }}</p>
{#加safe容許顯示html及頻繁彈出框#}
{#<p>{{ link|safe }}</p>#}

<hr>

<p>
    {% for teacher in data %}
    {#        最後一次循環,不加,#}
        {% if forloop.last %}
            {{ teacher }}
        {% else %}
            {{ teacher }},
        {% endif %}
    {% endfor %}
</p>
{#<p>{% if 3 > 2 > 1 %}{% endif %}</p>#}
{##}
{#<p>{% if 3 > 2 and 2 > 1  %}{% endif %}</p>#}

<hr>

{{ person.name }}
{{ person.dream }}


</body>
</html>
t.html

4、母版
bt--css jquery--js

怎麼使用?
1. 在子頁面 經過使用 {% extends ‘模板名’ %} --> 放在子頁面的最上面
2. {% block xx %}{% endblock %}git

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ html_title }}</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    {% block page-css %}
    
    {% endblock %}
</head>
<body>
{% include 'nav.html' %}
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">

            {% block page-main %}

            {% endblock %}

        </div>
    </div>
</div>
<script src="/static/jquery.js"></script>
{% block page-js %}

{% endblock %}
</body>
</html>
mama.html
{% extends 'mama.html' %}

{% block page-main %}
<table class="table table-bordered">
    <thead>
    <tr>
        <th>#</th>
        <th>id</th>
        <th>出版社名稱</th>
        <th>操做</th>
    </tr>
    </thead>
    <tbody>
    {% for publisher in publisher_list %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ publisher.id }}</td>
            <td>{{ publisher.name }}</td>
            <td>
                <a href="/edit_publisher/{{ publisher.id }}/" class="btn btn-info">編輯</a>
                <a href="/delete_publisher/" class="btn btn-danger">刪除</a>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>

{% endblock %}

{#我這個頁面纔用到的一個js文件#}
{% block page-js %}
    <script src="/static/1.js"></script>
{% endblock %}
使用母版.html

3. 組件
把單獨的一段html代碼放在一個文件
使用 {% include '組件名' %}導入web

 
五.跨站請求僞造 CSRF
網站沒法限制誰給他發請求,例如:本身寫的頁面也可跳轉到sougouweb。
釣魚網站 往銀行發請求,獲取你的用戶名、密碼等信息。

value="隨機的字符串"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="銀行轉帳的api" method="post">
    <input type="text" name="key" value="adadaaljqoiqwkqkwqqqrdadq" style="display: none">
    <input type="text" name="query">
    <input type="submit" value="提交">
</form>

<hr>

</body>
</html>
csrf.html
def csrf_test(request):
    if request.method == "POST":
        print(request.POST)
        return HttpResponse("OK")
    return render(request, "csrf_test.html")
csrf_test的view
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="" method="post">
{#    生成隨機字符串的input框,必須在form表單裏 #}
    {% csrf_token %}
    <input type="text" name="name">
    <input type="submit" value="提交">
</form>
</body>
</html>
csrf_test.html

6、ORM單表查詢13條+外鍵操做(一對多)

1.字段和參數
1. 字段
                    1. CharField
                    2. AutoField
                    3. DateField
                    
                    4. DateTimeField()
                    5. IntergeField()
                2. 參數
                    1. null=True
                    2. default=默認值
                    3. unique=True
                    4. 時間字段
                        1. auto_now_add=True    第一次建立時
                        2. auto_add=True        每次更新時
AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -3276832767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 032767
    IntegerField(Field)
        - 整數列(有符號的) -21474836482147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 02147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -92233720368547758089223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須爲逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          容許文件
                allow_folders=False,       容許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型

字段合集
字段合集
如下內容參考博客地址:https://www.cnblogs.com/liwenzhou/p/8660826.html
2.ORM必知必會單表查詢13條
1. all()                             --> 查詢全部結果
                2. filter()                          --> 根據查詢條件查詢數據庫的
                3. get()                             --> 獲取一個惟一的值
                4. exclude()                         --> 將符合條件的都剔除掉,留下不符合條件的
                5. values('字段名', ...)             --> 返回一個QuerySet,裏面是字典
                6. values_list(字段名', ...)         --> 返回一個QuerySet,裏面是元祖
                7. order_by()                        --> 對查詢結果排序
                8. reverse()                         --> 對一個有序的查詢結果集作反轉
                9. distinct()                        --> 去重,跨表查詢時去掉重複的記錄,MySQL不支持按字段去重
                10. count()                          --> 返回數據條數
                11. first()                          --> 取第一個數據
                12. last()                           --> 取最後一條數據
                13. exists()                         --> 判斷表裏有沒有數據
# 如何在一個py文件中 使用Django項目的相關配置或內容
import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")  # manage.py中第6行
    import django

    django.setup()

    from app01 import models

    # 查詢age=18的第一我的
    # ret = models.Person.objects.get(age=18)  # pk(主鍵) unique
    # print(ret)
    # 查詢age=18的全部人
    # ret = models.Person.objects.filter(age=18) #獲取的是對象的列表,多個值
    # print(ret[0])  # ret[0]取一個值

    # ret = models.Person.objects.filter(age=18).values("age", "phone")
    # print(ret)  # 打印指定的兩個字段,字典內容

    # ret = models.Person.objects.filter(age=18).values_list("age", "phone")
    # print(ret) # 打印指定的兩個字段,小元組內容,只有值,無key了

    # 排序
    # ret = models.Person.objects.all().order_by("age")
    # print(ret)


 # 神奇的雙下劃線
    # 查詢年齡大於18歲的
    # ret = models.Person.objects.filter(age__gt=18, id__gt=1)
    # print(ret)

    # 查詢id值在 [1, 2]的人
    # ret = models.Person.objects.filter(id__in=[1, 2, 20000])
    # print(ret)  # 取1,2的人,不會報錯
    #
    # 查詢id值不在[1,2]的人
    # ret = models.Person.objects.exclude(id__in=[1,2])
    # print(ret)

    # 查詢名字中包含 JJ 的那我的
    # ret = models.Person.objects.filter(name__contains="JJ")
    # print(ret)
    # 不區分大小寫查詢
    # ret = models.Person.objects.filter(name__icontains="jj")
    # print(ret)

    # 查詢id在1-3區間內的數據
    # ret = models.Person.objects.filter(id__range=[1, 3])
    # print(ret)

    # 查詢以JJ結尾的人
    # ret = models.Person.objects.filter(name__endswith='JJ')
    # print(ret)
    # print(models.Person.objects.first().birthday) #sqlite3中顯示None,日期的格式有問題,mysql能夠顯示
    # 查詢 生日 是 2018年的全部人
    # ret = models.Person.objects.filter(birthday__year=2018)
    # print(ret)


#外鍵
    # 查詢第一本書關聯的出版社的名字
    # 1. 基於對象的查詢
    # book_obj = models.Book.objects.first()
    # ret = book_obj.publisher.name
    # print(ret)
    # 2. 基於queryset的雙下劃線查詢,雙下劃線表示跨表
    # ret = models.Book.objects.all().values_list("publisher__name").distinct()
    # print(ret)

    # 反向查詢
    # 1. 由出版社反向查詢書籍(基於對象的查詢)
    # publisher_obj = models.Publisher.objects.get(id=2)  # 找到張江出版社
    # 張江出版社出版的全部書籍
    # ret = publisher_obj.book_set.all()
    # print(ret)

    # 2. 基於queryset的雙下劃線
    # 江出版社出版的全部書籍的書名
    ret = models.Publisher.objects.filter(id=2).values_list("book__title")
    print(ret)
orm_test.py

注:
查詢:
1.根據惟一值查詢:用get
2.通常會用filter

1256789 11 12 經常使用
id__gt=1 #id大於1的數據
分類:
                    1. 返回QuerySet列表的有哪一些?
                        1. all()
                        2. filter()
                        3. exclude()
                        4. order_by()
                        5. reverse()
                        6. distinct()
                        
                        7. values('字段名', ...)     --> 查詢結果的列表裏,都是字典
                        8. values_list(字段名', ...) --> 查詢結果的列表裏,都是元祖
                        
                    2. 返回具體對象的
                        1. first()
                        2. last()
                        3. get()
                        
                    3. 返回數字的
                        1. count()
                    4. 返回布爾值
                        1. exists()
分類
不一樣的對象有不一樣的方法,能夠根據對象調用方法。返回QuerySet的使用加[0]

3. 單表查詢神奇的雙下劃線
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值
 
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、22、33的數據
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 
models.Tb1.objects.filter(name__contains="ven")  # 獲取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
 
models.Tb1.objects.filter(id__range=[1, 3])      # id範圍是1到3的,等價於SQL的bettwen and
 
相似的還有:startswith,istartswith, endswith, iendswith 

date字段還能夠:
models.Class.objects.filter(first_day__year=2017)

    4.外鍵操做--重點!正則表達式

經過Foreignkey字段 ,可以獲得和我關聯的那個對象,例如: book.publisher.name
一對多--外鍵操做
外鍵關聯--查、增刪、改
關聯字段__被查名稱 能夠跨表查詢

基於例子練習跨表查詢(正向、反向),例子見上 orm_test.py或以下
#外鍵
    # 查詢第一本書關聯的出版社的名字
    # 1. 基於對象的查詢
    # book_obj = models.Book.objects.first()
    # ret = book_obj.publisher.name
    # print(ret)
    # 2. 基於queryset的雙下劃線查詢,雙下劃線表示跨表
    # ret = models.Book.objects.all().values_list("publisher__name").distinct() #全部書籍出版社的名字
    # ret = models.Book.objects.filter(id=1).values_list("publisher__name")#id爲1的書籍出版社的名字
    # print(ret)

    # 反向查詢
    # 1. 由出版社反向查詢書籍(基於對象的查詢)
    # publisher_obj = models.Publisher.objects.get(id=2)  # 找到張江出版社
    # 張江出版社出版的全部書籍
    # ret = publisher_obj.book_set.all()
    # print(ret)

    # 2. 基於queryset的雙下劃線
    # 江出版社出版的全部書籍的書名
    ret = models.Publisher.objects.filter(id=2).values_list("book__title")
    print(ret)

 

from django.db import models

# Create your models here.


class Publisher(models.Model):
    name = models.CharField(max_length=12)


# 書籍表
class Book(models.Model):
    title = models.CharField(max_length=32)
    publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE) #on_delete級聯刪除


class Person(models.Model):
    name = models.CharField(max_length=12, default="alex")
    age = models.IntegerField(default=18)
    birthday = models.DateField()
    birthday2 = models.DateTimeField(null=True)
    phone = models.CharField(max_length=11, unique=True)
    # 建立該記錄時自動把當前時間保存到該字段
    join_date = models.DateField(auto_now_add=True)
    # 更新該記錄的值時 自動把當前時間保存到該字段
    last_date = models.DateField(auto_now=True)

    def __str__(self):
        return "{}-{}".format(self.age, self.phone)
models.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

# from django.urls import path

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publisher_list/$', views.publisher_list, name="alex"),
    url(r'^edit_publisher/(?P<edit_id>\d+)/$', views.EditPublisher.as_view(), name="alex"),
    # 測試上傳你文件
    url(r'^upload/$', views.Upload.as_view()),
    # 測試返回Json格式數據
    url(r'^json_test/$', views.JsonTest.as_view()),
    # 測試模板語法
    url(r'^template_test/$', views.template_test),
    # 測試跨站請求僞造 (CSRF)
    url(r'^csrf_test/$', views.csrf_test),

    url(r'^book_list/$', views.book_list),
    url(r'^add_book/$', views.AddBook.as_view()),
    url(r'^delete_book/(?P<pk>\d+)/$', views.DeleteBook.as_view()),
    url(r'^edit_book/(?P<pk>\d+)/$', views.EditBook.as_view()),
    url(r'^login/$', views.login),


]
urls.py--all
@login_check
def book_list(request):
    # 去數據庫查詢全部的書籍
    data = models.Book.objects.all()
    return render(request, "book_list.html", {"book_list": data})


class AddBook(views.View):

    @method_decorator(login_check)
    def get(self, request):
        data = models.Publisher.objects.all()
        return render(request, "add_book.html", {"publisher_list": data})

    def post(self, request):
        book_name = request.POST.get("title")
        publisher_id = request.POST.get("publisher")
        # publisher_obj = models.Publisher.objects.get(id=publisher_id)
        # 建立書籍
        models.Book.objects.create(
            title=book_name,
            publisher_id=publisher_id
            # publisher=publisher_obj #麻煩,不推薦
        )
        return redirect("/book_list/")


class DeleteBook(views.View):
    def get(self, request, pk):
        models.Book.objects.filter(id=pk).delete()
        return redirect("/book_list/")


class EditBook(views.View):
    def get(self, request, pk):
        book_obj = models.Book.objects.get(id=pk)
        publisher_list = models.Publisher.objects.all()
        return render(request, "edit_book.html", {"book": book_obj, "publisher_list": publisher_list})

    def post(self, request, pk):
        book_obj = models.Book.objects.get(id=pk)
        new_title = request.POST.get("title")
        new_publisher_id = request.POST.get("publisher")
        # 更新
        book_obj.title = new_title
        book_obj.publisher_id = new_publisher_id
        # 同步到數據庫
        book_obj.save()
        return redirect("/book_list/")
書籍相關的views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>編輯書籍</title>
</head>
<body>

<form action="" method="post">
{% csrf_token %}
    <input type="text" name="title" value="{{ book.title }}">
    <select name="publisher">
        {% for publisher in publisher_list %}

            {% if book.publisher == publisher %}
                <option selected value="{{ publisher.id }}">{{ publisher.name }}</option>
            {% else %}
                <option value="{{ publisher.id }}">{{ publisher.name }}</option>
            {% endif %}
        {% endfor %}
    </select>
    <input type="submit" value="提交">
</form>
</body>
</html>
edit_book.html

 

# 登陸
def login(request):
    if request.method == "POST":
        next = request.GET.get("next")
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")

        if username == "alex" and pwd == "alexdsb":
            if next:
                rep = redirect(next)
            else:
                rep = redirect("/publisher_list/")
            # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie)
            # rep.set_cookie("s21", "hao", max_age=7)  # 7秒鐘有效的Cookie
            rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7)  # 設置加鹽的cookie
            return rep
        else:
            return HttpResponse("滾~")

    return render(request, "login.html")



# 裝飾器版本登陸認證
def login_check(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next = request.path_info
        # 登陸驗證
        # v = request.COOKIES.get("s21")  # 取正常的cookie
        v = request.get_signed_cookie("s21", default="", salt="ooxx")  # 獲取加鹽的cookie
        if v == "hao":
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next))

    return inner
登陸的view


7、cookie和session

瀏覽器能夠拒絕保存Cookie.在瀏覽器的settings中搜索cookie,禁用便可!
補充3點:
1. 如何登錄後再跳轉回以前訪問的頁面 --> next參數實現
2. 如何將FBV的裝飾器應用到CBV上 --> from django.utils.decorators import method_decorator
3. 裝飾器修復技術 --> from functools import wraps

form表單中的action不要寫死 ,應是<form action="" method="post">

函數的裝飾器可否 直接給類使用??--不能夠
須要用method_decorator 裝飾一下

# 登陸
def login(request):
    if request.method == "POST":
        next = request.GET.get("next")
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")

        if username == "alex" and pwd == "alexdsb":
            if next:
                rep = redirect(next)
            else:
                rep = redirect("/publisher_list/")
            # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie)
            # rep.set_cookie("s21", "hao", max_age=7)  # 7秒鐘有效的Cookie
            rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7)  # 設置加鹽的cookie
            return rep
        else:
            return HttpResponse("滾~")

    return render(request, "login.html")


#使用
def publisher_list(request):
    # 從請求中找有沒有我以前登陸時候保存的特殊的鍵值對
    print(request.COOKIES)
    v = request.COOKIES.get("s21")
    # 若是你請求攜帶的值 和我以前讓你保存的是同一個,就表示你是已經登錄過的用戶,默認放行
    if v == "hao":
        print(request.path_info)
        data = models.Publisher.objects.all()
        return render(request, "publisher_list.html", {"publisher_list": data})
    else:
        return redirect("/login/")
cookie的簡單應用
 
# 裝飾器版本登陸認證
def login_check(func):
    @wraps(func) #裝飾器修復技術
    def inner(request, *args, **kwargs):
        next = request.path_info  # 獲取當前路徑
        # 登陸驗證
        # v = request.COOKIES.get("s21")  # 取正常的cookie
        v = request.get_signed_cookie("s21", default="", salt="ooxx")  # 獲取加鹽的cookie
        if v == "hao":
            return func(request, *args, **kwargs)  # 你要執行的視圖函數
        else:
            return redirect("/login/?next={}".format(next))

    return inner






# 登陸
def login(request):
    if request.method == "POST":
        next = request.GET.get("next")
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")

        if username == "alex" and pwd == "alexdsb":
            if next:
                rep = redirect(next)
            else:
                rep = redirect("/publisher_list/")
            # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie)
            # rep.set_cookie("s21", "hao", max_age=7)  # 7秒鐘有效的Cookie
            rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7)  # 設置加鹽的cookie
            return rep
        else:
            return HttpResponse("滾~")

    return render(request, "login.html")
裝飾器版登陸
@login_check
def book_list(request):
    # 去數據庫查詢全部的書籍
    data = models.Book.objects.all()
    return render(request, "book_list.html", {"book_list": data})


from django.utils.decorators import method_decorator

class AddBook(views.View):

    @method_decorator(login_check)
    def get(self, request):
        data = models.Publisher.objects.all()
        return render(request, "add_book.html", {"publisher_list": data})

    def post(self, request):
        book_name = request.POST.get("title")
        publisher_id = request.POST.get("publisher")
        # publisher_obj = models.Publisher.objects.get(id=publisher_id)
        # 建立書籍
        models.Book.objects.create(
            title=book_name,
            publisher_id=publisher_id
            # publisher=publisher_obj #麻煩,不推薦
        )
        return redirect("/book_list/")
裝飾器版登陸應用

裝飾器修復技術---@warppers
--動態添加功能+顯示被裝飾函數信息
from functools import wraps


def wrapper(func):
    @wraps(func)  # 藉助內置的工具修復被裝飾的函數
    def inner(*args, **kwargs):
        print("呵呵")
        func(*args, **kwargs)
    return inner


@wrapper
def foo(arg):
    """
    這是一個測試裝飾器的函數
    :param arg: int 必須是int類型
    :return: None
    """
    print("嘿嘿嘿" * arg)


foo(10)
print(foo.__doc__)
代碼
相關文章
相關標籤/搜索