1. 程式人生 > >web後端--Django學習筆記09

web後端--Django學習筆記09

一、第八天作業

1、在登錄檔單中包括使用者名稱、密碼、性別、愛好(可以有多個),還要完成上傳頭像,要求在伺服器完成接收資料,並儲存到伺服器。

1.1 程式碼演示

1、views

from django.http import HttpResponse
from django.shortcuts import render
import os
​
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
​
def go_register(request):
    return render(request,'homework/register.html')
​
​
def register(request):
    regname = request.POST["regname"]
    regpwd = request.POST["regpwd"]
    sex = request.POST["sex"]
    hobbies = request.POST.getlist("hobby")   # 接收一組引數
    your_figure = request.FILES.get("your_figure")
    print("註冊名是:"+regname)
    print("註冊密碼是:" + regpwd)
    print("註冊性別是:" + sex)
    print("您的愛好是:",hobbies)
    dest_path = os.path.join(BASE_DIR,'upload','images',your_figure.name)
​
    with open(dest_path,'wb') as f:
        for chunk in your_figure.chunks():
            f.write(chunk)
​
    return HttpResponse("註冊成功!")

2、templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊頁面</title>
</head>
<body>
    <form action="{% url 'home:register' %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        註冊使用者名稱:<input type="text" name="regname"/> <br/>
        註冊密碼:<input type="password" name="regpwd"/> <br/>
        性別:男:<input type="radio" name="sex" value="boy" checked="checked"/>
             女:<input type="radio" name="sex" value="girl"/> <br/>
        愛好:讀書<input type="checkbox" name="hobby" value="read"/> &nbsp;&nbsp;
            電影<input type="checkbox" name="hobby" value="movie"/> &nbsp;&nbsp;
        跑步<input type="checkbox" name="hobby" value="jogging"/> &nbsp;&nbsp;
            美食<input type="checkbox" name="hobby" value="food"/> &nbsp;&nbsp;
          音樂<input type="checkbox" name="hobby" value="music"/> &nbsp;&nbsp;
        個人頭像:<input type="file" name="your_figure"/> <br/>
        <input type="submit" value="註冊"/>
    </form>
</body>
</html>

3、urls

#子路由
from django.urls import path
​
from homework.views import *
​
app_name = 'homework'
​
urlpatterns = [
    path('goreg/',go_register),
    path('register/',register,name="register"),
]
#總路由
 path('homework/',include('homework.urls',namespace='home')),

 

二、Django資料庫快取

    第一步:建立快取表
    python manage.py createcachetable 自定義快取表名稱
例:python manage.py createcachetable mycachetable
第二步:
在settings.py中設定快取為資料庫表
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': '快取表名稱',
    }
}
​
第三步:程式操作
def get_product_byid(request,product_id):
    # 使用底層from django.core.cache import cache查詢快取
     product = cache.get("key")
if 快取中存在:
    快取命中,直接返回
else:
    product = Product.objects.get(id=product_id)   # 從資料庫中查詢
    cache.set("key",product,"可以傳入快取過期時間")  # 儲存到快取表中
    return 返回給客戶端

2.1 程式碼演示

1、setting

​
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'mycachetable',
    }
}
#更改時區
TIME_ZONE = 'Asia/Shanghai'   #亞洲上海
​
USE_I18N = True
​
USE_L10N = True
​
USE_TZ = False    #否定預設時區

2、models

from django.db import models
​
class Product(models.Model):
    name = models.CharField(max_length=20)
    price = models.FloatField()
​
    class Meta:
        db_table = 'products'

3、views

from django.core.cache import cache
from django.shortcuts import render
from django.views.decorators.cache import cache_page
​
from cacheapp.models import Product
​
def get_product_byid(request,product_id):
    product = cache.get('product:'+str(product_id))  # 使用底層API查詢快取
    if product:
        msg = "恭喜,快取命中了"
    else:
        product = Product.objects.get(id=product_id)   # 從資料庫中查詢
        msg = "快取中沒找到,只有查資料庫了!"
        cache.set('product:'+str(product.id),product,30)  # 儲存到快取表中
    return render(request, 'cacheapp/product.html', locals())
​
​
# @cache_page(30)      #裝飾器,定義快取過期時間
def get_all_products(request):   #查詢所有產品
    print("準備查詢所有產品~~~")
    products = Product.objects.all()
    print("已經查詢完畢所有產品~~~")
    return render(request,'cacheapp/all_products.html',locals())

4、templates

<!product.html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>產品模板</title>
</head>
<body>
    <h3 style="color:red">{{ msg }}</h3>
    <h3>產品編號:{{ product.id }}</h3>
    <h3>產品名稱:{{ product.name }}</h3>
    <h3>產品價格:{{ product.price }}</h3>
</body>
</html>
<!all_products.html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>所有產品資訊</title>
</head>
<body>
    <table align="center" border="1">
        <thead>
           <tr>
               <th>產品編號</th>
               <th>產品名稱</th>
               <th>產品價格</th>
           </tr>
        </thead>
        <tbody>
           {% for product in products %}
               <tr>
                  <td> {{ product.id }} </td>
                  <td> {{ product.name }} </td>
                  <td> {{ product.price }} </td>
               </tr>
           {% endfor %}
        </tbody>
    </table>
</body>
</html>

5、urls

#子路由
from django.urls import path
from cacheapp.views import *
​
urlpatterns = [
    path('product/<int:product_id>/',get_product_byid),
    path('products/',cache_page(30)(get_all_products)),
    path('allproducts/',get_all_products),
]
#總路由
 path('cacheapp/',include('cacheapp.urls')),

6、MySQL

mysql> create database mydb default character set utf8;
Query OK, 1 row affected (0.01 sec)
​
mysql> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
​
Database changed
mysql> desc mycachetable; #檢視建立的快取表
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| cache_key | varchar(255) | NO   | PRI | NULL    |       |
| value     | longtext     | NO   |     | NULL    |       |
| expires   | datetime(6)  | NO   | MUL | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
​
mysql> insert into products(name,price)values('電腦',6000),('箱子',60);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
​
mysql> select * from products;
+----+--------+-------+
| id | name   | price |
+----+--------+-------+
|  1 | 電腦   |  6000 |
|  2 | 箱子   |    60 |
+----+--------+-------+
2 rows in set (0.00 sec)
​
mysql> select * from mycachetable\G;
*************************** 1. row ***************************
cache_key: :1:product:1
    value: gASVyQAAAAAAAACMFWRqYW5nby5kYi5tb2RlbHMuYmFzZZSMDm1vZGVsX3VucGlja2xllJOUjAhjYWNoZWFwcJSMB1Byb2R1Y3SUhpSFlFKUfZQojAZfc3RhdGWUaACMCk1vZGVsU3RhdGWUk5QpgZR9lCiMBmFkZGluZ5SJjAJkYpSMB2RlZmF1bHSUdWKMAmlklEsBjARuYW1llIwG55S16ISRlIwFcHJpY2WUR0C3cAAAAAAAjA9fZGphbmdvX3ZlcnNpb26UjAUyLjEuMpR1Yi4=
  expires: 2018-11-13 21:39:14.000000
*************************** 2. row ***************************
cache_key: :1:product:2
    value: gASVyQAAAAAAAACMFWRqYW5nby5kYi5tb2RlbHMuYmFzZZSMDm1vZGVsX3VucGlja2xllJOUjAhjYWNoZWFwcJSMB1Byb2R1Y3SUhpSFlFKUfZQojAZfc3RhdGWUaACMCk1vZGVsU3RhdGWUk5QpgZR9lCiMBmFkZGluZ5SJjAJkYpSMB2RlZmF1bHSUdWKMAmlklEsCjARuYW1llIwG566x5a2QlIwFcHJpY2WUR0BOAAAAAAAAjA9fZGphbmdvX3ZlcnNpb26UjAUyLjEuMpR1Yi4=
  expires: 2018-11-13 21:39:30.000000
2 rows in set (0.00 sec)
​
ERROR: 
No query specified
​
mysql> 
​

 

三、快取頁面(檢視函式的執行結果)

​ 第一種使用方法: 在檢視函式上新增@cache_page(快取秒數)裝飾器,則會對檢視結果快取 指定的秒數。快取到CACHES指定的快取地址。

第二種使用方法:
    path("url/",cache_page(快取秒數)(檢視函式名稱))
​
注意:cache_page是針對於具體的URL來進行快取的。

3.1 程式碼演示 (同2.1)

四、自定義表單類

  1.繼承Form類(django.forms.Form),編寫表單類
      class RegForm(forms.Form):  # 自定義表單類,繼承Form類
          regname = forms.CharField(label="註冊使用者名稱",max_length=10)
          regpwd = forms.CharField(label="註冊密碼",widget=forms.PasswordInput())
          reghome = forms.ChoiceField(label="籍貫",choices=(("1","陝西"),("2","北京"),("3","山東")))
          sex = forms.ChoiceField(label="性別",choices=(("0","男"),("1","女")),widget=forms.RadioSelect())
2. 在檢視函式中判斷提交方式,對錶單做出不同處理
  def register(request):
      if request.method == "POST":
          regform = RegForm(request.POST)  # 將POST資料傳入表單物件的構造方法中
          if regform.is_valid():  # 驗證表單資料是否有效
              regname = regform.cleaned_data["regname"] # 接收指定表單域的資料
              print("家鄉:"+reghome+";性別:",regsex)
              return redirect(reverse("formapp:success",args=(regname,regpwd)))
      else:
          regform = RegForm()   # 例項化一個空的表單物件
          return render(request,'formapp/register.html',{"regform":regform})
​
3. 在模板上渲染表單
   <form action="" method="post">
    {% csrf_token %}
       {{ regform.as_p }}   顯示錶單物件封裝的表單控制元件
    <input type="submit" value="註冊"/>
   </form>

4.1 程式碼演示

1、forms.py

from django import forms
​
class RegForm(forms.Form):  # 自定義表單類,繼承Form類
    regname = forms.CharField(label="註冊使用者名稱",max_length=10)
    regpwd = forms.CharField(label="註冊密碼",widget=forms.PasswordInput())
    reghome = forms.ChoiceField(label="籍貫",choices=(("1","陝西"),("2","北京"),("3","山東")))
    sex = forms.ChoiceField(label="性別",choices=(("0","男"),("1","女")),widget=forms.RadioSelect())

2、views

from django.shortcuts import render, redirect
from django.urls import reverse
​
from formapp.forms import RegForm
​
def go_success(request,regname,regpwd):
    return render(request,'formapp/success.html',locals())
​
​
def register(request):
    if request.method == "POST":
        regform = RegForm(request.POST)  # 將POST資料傳入表單物件的構造方法中
        if regform.is_valid():  # 驗證表單資料是否有效
            regname = regform.cleaned_data["regname"] # 接收指定表單域的資料
            regpwd = regform.cleaned_data["regpwd"]
            reghome = regform.cleaned_data["reghome"]
            regsex = regform.cleaned_data["sex"]
            print("家鄉:"+reghome+";性別:",regsex)
            return redirect(reverse("formapp:success",args=(regname,regpwd)))
    else:
        regform = RegForm()   # 例項化一個空的表單物件
        return render(request,'formapp/register.html',{"regform":regform})

3、templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊頁面</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
           {{ regform.as_p }} <!以p標籤展示>
​
        <input type="submit" value="註冊"/>
    </form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>成功頁面</title>
</head>
<body>
    <h3> 註冊成功,註冊的使用者名稱是:{{ regname }},密碼是:{{ regpwd }} </h3>
</body>
</html>

4、urls

from django.urls import path,include
from formapp.views import *
​
app_name = "formapp"
​
urlpatterns = [
    path('register/',register,name="register"),
    path('gosuccess/<regname>/<regpwd>/',go_success,name="success"),
]

 

五、自定義錯誤頁面

    在專案的總路由配置檔案中將預設的錯誤處理程式設定為自定義的檢視函式
    eg: 
    from django.conf.urls import handler500
    handler500 = 自定義檢視函式名稱

 

​
]注意:兩個設定
      在settings.py中,要將除錯狀態關閉,並設定ALLOWED_HOSTS:
      DEBUG = False
      ALLOWED_HOSTS = ["*"]
​
如果使用的是Django自帶的開發伺服器,則不能直接在自定義的錯誤頁面中
載入靜態資源;如果要載入靜態資源,需要使用
"python manage.py runserver --insecure"命令啟動開發伺服器。

5.1 程式碼演示

1、urls

#子路由
from django.urls import path
​
from errorapp.views import *
​
urlpatterns = [
    path('error/',error_view),
    path('miss/',error_404),
]
#總路由
from django.conf.urls import handler500, handler404
from django.contrib import admin
from django.urls import path,include
from errorapp.views import myhandler500,myhandler404
​
handler500 = myhandler500
handler404 = myhandler404
​
urlpatterns = [
    path('admin/', admin.site.urls),
   
    path('errorapp/',include('errorapp.urls')),
]

2、views

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
​
​
def error_view(request):
    5 / 0
    return HttpResponse("Hello")
​
def error_404(request):
    return HttpResponseRedirect("/abc/")
​
def myhandler500(request):
    return render(request,'errorapp/my500.html')
​
def myhandler404(request):
    return render(request,'errorapp/my404.html')
​

3、templates

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>500</title>
</head>
<body>
    <h3>發生一點小故障~~~</h3>
    <img src="{% static 'errorapp/images/ren.gif' %}"/>
</body>
</html>