modelform和django中的logging模塊的使用
內容回顧:
內容回顧
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>{% forauthor 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模塊的使用