• 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())
  • 相关阅读:
    Yii数据库操作增删改查-[增加查询更新删除 AR模式]
    Yii2 关于时间格式的用法
    常用Linux命令
    数据库设计规范
    PHP代码规范
    git fetch 的简单用法:更新远程代码到本地仓库及冲突处理
    yii2 URL重写 nginx的配置
    Linux下免安装mysql
    在CentOS下搭建自己的Git服务器
    开源技术推荐之个人使用心得
  • 原文地址:https://www.cnblogs.com/yb635238477/p/9526458.html
Copyright © 2020-2023  润新知