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())
原文地址:https://www.cnblogs.com/yb635238477/p/9526458.html