modelform和django中的logging模块的使用
Posted yb635238477
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>{% 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模块的使用的主要内容,如果未能解决你的问题,请参考以下文章
Django 模型和 ModelForms 中的空白、Null 和必需
django 中的 ModelForms 是不是仅用于发布?