1. 程式人生 > >modelform和django中的logging模塊的使用

modelform和django中的logging模塊的使用

lec endif 路徑 提示信息 例子 edit true 利用 json

內容回顧:

  內容回顧
1. 同源策略
1. 什麽叫同源策略
1. 一個源的定義
協議+IP(域名)+端口一致,就是同一個源。
2. 同源策略限制了腳本(js)跨網站發請求,能發請求但是拿不到響應
3. 不受同源策略限制的
1. a標簽、重定向、form表單的提交
2. script、link標簽等不受同源策略的限制,可以引用其他站點內容
2. jsonp(json padding)
1. jsonp的原理是什麽?
利用script標簽繞過同源策略的限制,拿到數據

alex(‘{name:"alex", "age": 18}‘)
2. jQuery封裝的jsonp
1. 簡單的getJSON()
$.getJSON("http://127.0.0.1:8010/abc/?callback=?",function(){})

2. 進階的用法
$.ajax({
url: "http://127.0.0.1:8010/abc/",
dataType: "jsonp",
jsonp: "callback",
jsonpCallback: "回調函數名",
success:function(res){
// 拿到響應的數據之後要做的事兒
}
})

3. 江西電視臺的例子

我們先來復習一下前邊學的東西:

我們之前學過圖書館管理系統,接下來我們不用form表單,和用form表單,用formmodels,三種方法對比一下有什麽不同。

首先我們不用form表單:

當然是先從url配起,然後寫views視圖函數,

def book_list(request):
    book_list = models.Book.objects.all()
    return render(request,book_list.html,locals())   # locals()是將所有的變量返回

然後寫html

<!DOCTYPE html>
<html lang="
en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="/add_book/">添加書籍</a> <table border="1"> {% for book in book_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> <td>{{ book.price }}</td> <td>{{ book.publisher }}</td> <td>{{ book.publishe_date }}</td> <td>{% for
author in book.authors.all %} {{ author.name }} {% endfor %}</td> <td><a href="/edit_book/{{ book.id }}">編輯</a></td> </tr> {% endfor %} </table> </body> </html>

然後再寫添加書籍的a標簽,和路由,寫好後再寫視圖函數

def add_book(request):
    if request.method == POST:
        title = request.POST.get(title)
        price = request.POST.get(price)
        publish_date = request.POST.get("publish_date")
        publisher = request.POST.get("publisher")
        authors = request.POST.getlist("authors")  # get 只是取到最後一個,所以要用getlist
        book_obj = models.Book.objects.create(
            title = title,
            price=price,
            publishe_date=publish_date,
            publisher_id=publisher,
            # authors字段並不是book表的所以不能再book表裏創建,
        )
        print(authors)
        book_obj.authors.add(*authors)   #  add添加的是一個個的id值,所以要打散
        # book_obj.authors.set(authors)  #  set添加的是一個列表
        return redirect(/book_list/)
    publisher_list = models.Publisher.objects.all()
    author_list = models.Author.objects.all()
    return render(request,add_book.html,locals())

再寫添加書籍 的html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加書籍</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
    <p> 書名
        <input type="text" name="title">
    </p>
    <p>價格
        <input type="text" name="price">
    </p>
    <p>日期
        <input type="date" name="publish_date">
    </p>
    <p>出版社
        <select name="publisher">
            {% for publisher in publisher_list %}
             <option value="{{ publisher.id }}">{{ publisher.name }}</option>
            {% endfor %}
        </select>
    </p>
    <p>作者
        <select name="authors" multiple>
            {% for author in author_list %}
            <option value="{{ author.id }}">{{ author.name }}</option>
            {% endfor %}
        </select>
    </p>
    <p>
        <input type="submit" >
    </p>
</form>
</body>
</html>

再寫編輯書籍,

views視圖函數

def edit_book(request,pk):
    book_obj = models.Book.objects.filter(id = pk).first()
    if request.method == POST:
        title = request.POST.get(title)
        price = request.POST.get(price)
        publishe_date = request.POST.get(publish_date)
        publisher = request.POST.get(publisher)
        authors = request.POST.get(authors)
        book_obj.title = title
        book_obj.price = price
        book_obj.publishe_date = publishe_date
        book_obj.publisher_id = publisher
        book_obj.save()
        book_obj.authors.set(authors)
        return redirect(/book_list/)
    publisher_list = models.Publisher.objects.all()
    author_list = models.Author.objects.all()
    return render(request,edit_book.html,locals())

編輯書籍的html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>編輯書籍</title>
</head>
<body>
<h1>編輯書籍</h1>
<form action="" method="post">
    {% csrf_token %}
    <p>書名:
        <input type="text" name="title" value="{{ book_obj.title }}">
    </p>
    <p>價格:
        <input type="text" name="price" value="{{ book_obj.price }}">
    </p>
    <p>日期:
        <input type="date" name="publish_date" value="{{ book_obj.publishe_date|date:‘Y-m-d‘ }}">
    </p>
    <p>出版社:
        <select name="publisher">
            {% for publisher in publisher_list %}
                {% if publisher.id == book_obj.publisher_id %}
                    <option selected value="{{ publisher.id }}">{{ publisher.name }}</option>
                    {% else %}
                    <option value="{{ publisher.id }}">{{ publisher.name }}</option>
                {% endif %}
            {% endfor %}
        </select>
    </p>
    <p>作者:
        <select name="authors" multiple>
            {% for author in author_list %}
                {% if author in book_obj.authors.all %}
                    <option selected value="{{ author.id }}">{{ author.name }}</option>
                    {% else %}
                    <option value="{{ author.id }}">{{ author.name }}</option>
                {% endif %}
            {% endfor %}
        </select>
    </p>
    <p>
        <input type="submit">
    </p>
</form>
</body>
</html>

這就是不用form表單的方法,看上去就很麻煩,然後我們用form表單做:(form組件是用來搭建html頁面的,models是用來建表的,總混淆。)

首先在app01下新建一個py文件,在裏面寫form組件:

from django import forms
from app01 import models

class BookForm(forms.Form):
    title = forms.CharField(max_length=32,label=書名)
    price = forms.DecimalField(max_digits=5,decimal_places=2,label=價格)
    publish_date = forms.DateField(
        label=日期,
        widget=forms.widgets.DateInput(
            attrs={type:date}
        )
    )
    #  form中的單選標簽
    publisher = forms.ChoiceField(
        choices=models.Publisher.objects.all().values_list(id,name),
        widget = forms.widgets.Select()
    )
    # from中的多選標簽
    authors = forms.ChoiceField(
        choices=models.Author.objects.all().values_list(id,name),
        widget = forms.widgets.SelectMultiple()
    )

添加書籍 的頁面就可以簡化了:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加書籍</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
    {% for field in form_obj %}
        <p>
        {{ field.label }}
        {{ field }}
        </p>
    {% endfor %}
    <p>
        <input type="submit" >
    </p>
</form>
</body>
</html>

添加書籍的視圖當然也可以簡化:

def add_book(request):
    if request.method == POST:
        form_obj = forms.BookForm(request.POST)
        if form_obj.is_valid():
            authors = form_obj.cleaned_data.pop(authors)
            book_obj = models.Book.objects.create(**form_obj.cleaned_data)
            book_obj.authors.add(*authors)   #  add添加的是一個個的id值,所以要打散
            # book_obj.authors.set(authors)  #  set添加的是一個列表
            return redirect(/book_list/)
   # publisher_list = models.Publisher.objects.all()
   # author_list = models.Author.objects.all()
    form_obj = forms.BookForm()
    return render(request, v2/add_book.html, locals())

但是編輯書籍的時候能不能用form組建呢?因為編輯書籍的input框裏要有原來的書籍信息,這怎麽弄? 這時候form組建裏有一個initial默認值,在實例化的時候把他傳進去。

這時候也需要引入一個模塊,model_to_dict,將一個models對象轉化為字典

def edit_book(request,pk):
    from django.forms.models import model_to_dict
    book_obj = models.Book.objects.filter(id = pk).first()
    obj_dict = model_to_dict(book_obj)
    if request.method == POST:
        form_obj = forms.BookForm(request.POST)
        if form_obj.is_valid():
            title = form_obj.cleaned_data.get("title")
            price = form_obj.cleaned_data.get("price")
            publish_date = form_obj.cleaned_data.get("publish_date")
            publisher = form_obj.cleaned_data.get("publisher")
            authors = form_obj.cleaned_data.get("authors")
            book_obj.title = title
            book_obj.price = price
            book_obj.publishe_date = publish_date
            book_obj.publisher_id = publisher
            book_obj.save()
            book_obj.authors.set(authors)
            return redirect(/book_list/)
    form_obj = forms.BookForm(initial=obj_dict)
    publisher_list = models.Publisher.objects.all()
    author_list = models.Author.objects.all()
    return render(request, v1/edit_book.html, locals())

這樣就有原來的值了。只不過有些多選的字段還沒有選中。將form組建的字段該成:

from django import forms
from app01 import models

class BookForm(forms.Form):
    title = forms.CharField(max_length=32,label=書名)
    price = forms.DecimalField(max_digits=5,decimal_places=2,label=價格)
    publishe_date = forms.DateField(
        label=日期,
        widget=forms.widgets.DateInput(
            attrs={type:date}
        )
    )
    #  form中的外鍵
    #ModelsChoiceFied是將form中的字段和數據庫中的models的字段綁定
    publisher = forms.ModelChoiceField(
        queryset=models.Publisher.objects.all()
    )
    # from中的多對多關聯字段
    # ModelMultipleChoiceField是將form中的字段和數據庫中的models的字段綁定
    authors = forms.ModelMultipleChoiceField(
        queryset=models.Author.objects.all()
    )

但是這樣寫仍然會有點麻煩。

接下來就是用modelsform了。modelsform就是form與model的終極結合。

同樣是在forms文件裏寫一個類:繼承forms.ModelForm

class BookModelForm(forms.ModelForm):
    class Meta:
        # 告訴django這個form類和哪個model對應
        model = models.Book
        # 告訴django這個form類裏面有那些字段
        fields = "__all__"
        # fields = ["title", "price"]

這樣在添加書籍的時候就可以更簡單了。

def add_book(request):
    if request.method == POST:
        form_obj = forms.BookModelForm(request.POST)
        if form_obj.is_valid():
            form_obj.save()
            return redirect(/book_list/)
    form_obj = forms.BookModelForm()
    return render(request, v2/add_book.html, locals())

在編輯書籍的時候就更簡單了:

def edit_book(request,pk):
    book_obj = models.Book.objects.filter(id = pk).first()
    if request.method == POST:
        form_obj = forms.BookModelForm(request.POST,instance=book_obj)  # instance是需要修改的字段
        if form_obj.is_valid():
            form_obj.save()
            return redirect(/book_list/)
    form_obj = forms.BookModelForm(initial=book_obj) # 直接傳,不需要轉成字典
    return render(request, v2/edit_book.html, locals())

接下來我們說一下modelform的一些屬性。

class Meta:下常用參數:

model = models.Student  # 對應的Model中的類
fields = "__all__"  # 字段,如果是__all__,就是表示列出所有的字段
exclude = None  # 排除的字段
labels = None  # 提示信息
help_texts = None  # 幫助提示信息
widgets = None  # 自定義插件
error_messages = None  # 自定義錯誤信息
class BookModelForm(forms.ModelForm):
    class Meta:
        # 告訴django這個form類和哪個model對應
        model = models.Book
        # 告訴django這個form類裏面有那些字段
        fields = "__all__"
        # fields = ["title", "price"]  # 只展示title和price字段
        exclude = [authors] # 不要哪個字段

        # modelform如何設置插件
        widgets = {
            "publishe_date": forms.widgets.DateInput(
                attrs={"type": "date", "class": "form-control"}
            )
        }
        #modelform設置label
        labels = {
            "title": "書名",
            "price": "價格"
        }
        # 設置提示信息
        error_messages = {
            "title": {
                "required": "書名不能為空"
            }
        }

modelform只適合在小項目裏使用,所以還是主要掌握form組件。

接下來說一說在項目裏如何使用日誌。

做開發離不開日誌,以下是老師在工作中寫Django項目常用的logging配置。

在settings中配置一下:

BASE_LOG_DIR = os.path.join(BASE_DIR,路徑)
BASE_LOG_DIR = os.path.join(BASE_DIR, "log")
LOGGING = {
    version: 1, #  保留的關鍵字  暫時沒用
    disable_existing_loggers: False,  # 不禁用已經存在的那些logger實例
    formatters: { # 定義日誌的格式化樣式
        standard: {
            format: [%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]
                      [%(levelname)s][%(message)s]
        },
        simple: {
            format: [%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s
        },
        collect: {
            format: %(message)s
        }
    },
    filters: {
        require_debug_true: {
            (): django.utils.log.RequireDebugTrue,
        },
    },
    handlers: {  #處理器
        console: {  # 往屏幕終端打印
            level: DEBUG,
            filters: [require_debug_true],  # 只有在Django debug為True時才在屏幕打印日誌
            class: logging.StreamHandler,
            formatter: simple
        },
        default: {
            level: INFO,
            class: logging.handlers.RotatingFileHandler,  # 保存到文件,根據文件大小自動切
            filename: os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日誌文件
            maxBytes: 1024 * 1024 * 500,  # 日誌大小 500M
            backupCount: 3,  # 備份數為3  xx.log --> xx.log.1 --> xx.log.2 --> xx.log.3
            formatter: standard,
            encoding: utf-8,  # 寫日誌的編碼格式
        },
error: {
            level: ERROR,
            class: logging.handlers.RotatingFileHandler,  # 保存到文件,自動切
            filename: os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日誌文件
            maxBytes: 1024 * 1024 * 500,  # 日誌大小 500M
            backupCount: 5,
            formatter: standard,
            encoding: utf-8,
        },
        collect: {
            level: INFO,
            class: logging.handlers.RotatingFileHandler,  # 保存到文件,自動切
            filename: os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
            maxBytes: 1024 * 1024 * 50,  # 日誌大小 50M
            backupCount: 5,
            formatter: collect,
            encoding: "utf-8"
        }
    },
    loggers: {
        ‘‘: {  # 默認的logger應用如下配置
            handlers: [SF, console, error],  # 上線之後可以把‘console‘移除
            level: DEBUG,
            propagate: True,
        },
        collect: {  # 名為 ‘collect‘的logger還單獨處理
            handlers: [console, collect],
            level: INFO,
        }
    },
}

配置完了怎麽用 呢?

在view.py中

import logging
logger = logging.getLogger(__name__)# 生成一個以當前文件名為名字的日誌實例對象
collect_logger = logging.getLogger(‘collect‘) # 生成一個名為collect的日誌實例對象

然後再視圖函數中

logger.debug(啊士大夫{}‘.format())
logger.info(‘阿斯蒂芬{}‘.format())
collect_logger.info(‘阿斯頓飛過‘.format())

modelform和django中的logging模塊的使用