zoukankan      html  css  js  c++  java
  • 巨蟒python全栈开发django5:组件&&CBV&FBV&&装饰器&&ORM增删改查

    内容回顾:

    补充反向解析
    Html:{% url ‘别名’ 参数 %}
    
    Views:reverse(‘别名’,args=(参数,))
    
    模板渲染
    
    变量  {{ 变量名 }}
    逻辑相关 {% %}
    
    过滤器:
    {{ 变量|过滤器方法:’参数’ }}
    
    标签:
    {% for i in list%}   for k,v in dict.items
    {{ i }}
    {% endfor %}
    
    {% if 条件 %}
    
    {%elif%}
    
    {%else%}
    
    {% endif %}
    
    据点符 . 可以做深度查询
    
    {% with 变量名=变量.属性.属性.. %}
    {% with 变量.属性.属性..  as 变量名%}
    
    
    {% endwith %}
    
    母板继承
    先写一个母板,大家共用的地方
    母板预留钩子:
    {% block ‘名字’ %}
    
    母板里面的可以被替换的内容
    {%Endblock 名字%}
    
    
    
    
    再写子页面
    
    子页面里面第一行  {% extends ‘母板名称’ %}  
    {% block ‘名字’ %}
    {{ block.super }}
    子页面的内容
    
    {%Endblock 名字%}
    
    Csrf_token : 
    
    {% csrf_token %}
    View Code

    1.模板渲染组件

    可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。

    {% include 'navbar.html' %}

     例如:有个如下的导航栏,nav.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .c1{
                background-color: red;
                height: 40px;
            }
        </style>
    </head>
    <body>
    
    <div class="c1">
        <div>
            <a href="">xx</a>
            <a href="">dd</a>
        </div>
    </div>
    
    </body>
    </html>

     嵌入导航栏的页面,test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {% include 'nav.html' %}
    <h1>xxxxxxxxxx</h1>
    </body>
    </html>

     

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^user/', views.user),
        url(r'^order/', views.order),
        url(r'^zujian/', views.zujian),
    ]
    urls.py
    from django.shortcuts import render
    
    # Create your views here.
    def index(request):
        return render(request,'index.html')
    
    def user(request):
        return render(request,'usercenter.html')
    
    def order(request):
        return render(request,'order.html')
    
    def zujian(request):
        return render(request,'xiaomi.html')
    views.py
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
    </head>
    <body>
    {% include 'zujian.html' %}
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    </body>
    </html>
    xiaomi.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .c1{
                background-color: red;
                height: 40px;
            }
        </style>
    </head>
    <body>
    
    <div class="c1">
        <div>
            <a href="">xx</a>
            <a href="">dd</a>
        </div>
    </div>
    
    </body>
    </html>
    zujian.html

    根据位置进行引入.

    2.CBV和FBV=>dispatch方法

    开发的两种模式:

    FBV:(function base views)就是在视图里使用函数处理请求

    CBV:(class base views) 就是在视图里使用类处理请求

      Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

    1. 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
    2. 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

    平时我们写的是FBV,下面我们说一下基于类的视图

    首先导入模块,才能让django找到对应的方法:

    CBV模式的url写法:

    运行,得到结果:

    刷新,拿到表单

    输入用户名,提交

    应该在form表单输入:

    {% csrf_token %}

     

    再次提交得到如上结果,这就是cbv,可拓展性强,fbv写起来更简单一些,

    get和post接收的参数,要进行对应.

    注意:urls.py里边有name

    view.py必须有name属性

    FBV版的装饰器

    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            ret = func(*args, **kwargs)
            end_time = time.time()
            print("used:", end_time-start_time)
            return ret
        return inner
    
    
    # FBV版添加班级
    @wrapper
    def add_class(request):
        if request.method == "POST":
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
        return render(request, "add_class.html")

    装饰器表达

      装饰器的本质:一个闭包函数

      装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

    CBV版的装饰器

    from django.views import View
    from django.utils.decorators import method_decorator
    
    class AddClass(View):
    
        @method_decorator(wrapper)
        def get(self, request):
            return render(request, "add_class.html")
    
        def post(self, request):
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")

    扩展:

    # 使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,
    如get,post等做一些操作的时候,
    这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。
    class Login(View): def dispatch(self, request, *args, **kwargs): print('before') obj = super(Login,self).dispatch(request, *args, **kwargs) print('after') return obj def get(self,request): return render(request,'login.html') def post(self,request): print(request.POST.get('user')) return HttpResponse('Login.post')

    3.input标签值补充

    从数据库调用各种参数,进行页面的处理,怎样通过django处理数据库

     

    最终得到的结果是,用户输入的名字

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
    </head>
    <body>
    
    <form action="/zujian/" method="post">
        {% csrf_token %}
        用户名: <input type="text" name="username" value="xxx">
        <input type="submit">
    </form>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    {% include 'zujian.html' %}
    </body>
    </html>
    xiaomi
    """day53_moban URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^user/', views.user),
        url(r'^order/', views.order),
        url(r'^zujian/', views.zujian),
    
        #CBV模式的url写法
        url(r'^cbv/', views.MyView.as_view(name='sss')),
    ]
    urls.py
    from django.shortcuts import render,HttpResponse
    from django.views import View
    
    # Create your views here.
    def index(request):
        return render(request,'index.html')
    
    def user(request):
        return render(request,'usercenter.html')
    
    def order(request):
        return render(request,'order.html')
    
    def zujian(request):
        if request.method=='POST':
            uname=request.POST.get('username')
            print(uname)
            return HttpResponse('OK')
        return render(request,'xiaomi.html')
    
    class MyView(View):
        name='xxx'
        def get(self,request):
            return render(request,'xiaomi.html')
        def post(self,request):
            return HttpResponse('hello')
    views.py

    4.ORM创建表

    ORM 对象关系映射

    怎样通过数据库调用各种参数?
    之前操作数据库的三种方式:pymysql,cmd,Navicat

    学完orm,原生sql几乎就不写了

    类对应数据库中的表,          (类====>表)

    类实例化一个对象,我们就得到一条记录  (类对象===>记录)

    类中的属性,对应mysql中的字段,        (类属性====>字段)

    数据库的变更,只需要简单修改一些配置引擎就可以进行迁移了.

    类.属性名,我们就拿到了属性对应的值.

    orm就像一个引擎一样,

    sqlachemy开源(功能稍弱),orm没有开源(功能更强大一些),

     新创建一个项目,开始测试功能!!!
    原来app中的models.py需要连接pymysql进行写语句进行测试.

    磁盘是存储数据的,pymysql写完数据,存到磁盘,

    orm把类对象转化成sql语句,存储到磁盘,再拿到orm上.

    django不要深抠,关注实现功能就可以了,会用,用熟练就行

    继承,类是创建表,属性表示字段

    第一张表

    from django.db import models
    # Create your models here.
    class Book(models.Model):
        id=models.AutoField(primary_key=True)
        #主键自增字段
        title=models.CharField(max_length=32)
        #书名,字符串,后边必须写长度
        price=models.DecimalField(max_digits=16,decimal_places=2)
        #mysql中有float,double,decimal(单双精度,精准)
        #float(12,6) ,总长度是12,其中6位是小数长度
        #面试会用到mysql,还是需要复习的!!!!!
        pub_time=models.DateField()
        #出版日期
        publish=models.CharField(max_length=20)
        #出版社
        # id=models.PrimaryFied()
        #主键字段,但是没有自增,现在去掉了

    在下面的,输入命令,(python manage.py makemigrations)

    结果:

    项目中多了红框中的内容.

    这就是一个记录,记录了修改了什么!!!

    执行命令:(python manage.py migrate)

    db.sqlite3,是嵌套在django里边的数据库,操作简单,默认是这个,

    观察pycharm右侧是否有下图:

    ,如果没有,我们点击View里边的Tool Buttons按钮,就可以显示了.

    右侧的Database,,出现下图

    将左侧框里边的  db.sqlite3,左键拉到上图的框中,得到如下图

     

    这是因为第一次,需要下载,其他的数据库也是一样

     

    先点击下载,(下载的位置变成下图的样子)

    然后apply(应用),最后选择OK

     

    下边里面是django自带的内容

    输入完两条指令,python会在settings.py里边,找到下图:installed_apps里边的东西

    上图里边的最后一条,注册了app01,因为添加了app01

     执行两条指令的时候,python会扫描这些被安装的应用,上边几个都是自带的应用,而最后一个是自己安装的应用,每个自己安装的应用,都需要自己进行配置一下.这是自己创建了,通过扫描app01里边的models.py

    其实在apps.py里边就有这个配置

    也可以写成下面这种,也就是说,写上下两种都可以

    需求:现在我们再创建一个app,进行相关的操作练习一下.

    创建app的命令是=>(django-admin startapp app02)

     写下面的程序,现在数据库已经发生了更改.

     

    无论在数据库中的那张表中数据库做了修改,都需要重新执行这两条指令:

    python manage.py makemigrations

    python manage.py migrate

    记住这样就可以了

    我们看到了,这个结果没有发生变化.

    这时候,我们进行下面的操作:(将app02放在下面的settings.py文件里边)

    这时候,我们再执行刚才的两条命令

    在app02下多了migrations文件,也就是执行的记录

     

    点击刷新前:

    点击刷新后:(多了一张食物表)

    双击表,我们可以看到对应的结构:

    注意,这是pycharm帮助提供的,不是django帮助提供的东西

     

    每张表,必须有一个自增字段,也就是如上图显示的一样,如果我们创建的时候不写,内部会给我们提供一个

    注意,通过类创建表,类名和数据库生成的表名的区别

    Book类名对应app01_book表名

    Food类名对应app02_food表名

     以上全是sqllite3里边的一些配置和操作.

    下面我们进行mysql的一些操作.

    在settings.py里边默认写的是sqlite3:

    现在不用了,先断开,点击红色按钮,再移除这个db数据库即可

     

    这时候,数据的记录是不需要了,删除就可以了,留着可能会有一些其他的问题,将红框内的删除.

    配置mysql文件

    首先,修改配置文件settings.py的配置

    创建orm1的库.

    我们发现多了一个库

    这时候,我们再修改配置文件

    将刚刚创建好的orm1配置上.

    这时候,我们发现没有,mysqldb模块

    5.pycharm连接mysql

     默认用的是mysqldb这个模块,进行了连接的,用到这个地方,安装也没有用,这个模块只支持到python3.4,我们该如何处理?

    我们通过pymysql连接数据库即可,也是这样操作的,如何配置呢?

    在项目文件中找到__init__py.

     

    ,这时候,再运行,那两条命令.

    第一条命令表示创建记录,第二条命令表示创建表

    运行完成也就,创建成功了.

    这时候,我们再在CMD窗口里边,展示所有的表.如上图,可以看到已经创建成功了.

    这时候查表,我们可以看到查出的结果是空的,注意这里的表名是app01_book

     这是django做的优化机制.并且全部是小写,必须记住这些东西.

    只要一加载这个项目,就会执行这个文件.,所以放到了这个项目的__init__.py的文件下.

    此时,我们也就将表创建成功了.

     这时候,我们可以用pycharm给我们提供的Navicat功能界面,操作和连接sqlite3数据库一样

    依次找到,这些步骤操作.,点击进入,看下有没有下载,没有下载下来,要先下载下来.

    ok之后,弹出下图:

    右侧,得到结果.

    注意,这时候,是两个客户端,一个是django提供的,一个是pycharm提供的.

    6.图书管理系统增加和查询

    (1)更多字段和参数

      每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数。 这些参数在文档中有详细定义,这里我们只简单介绍一些最常用的:

    更多字段:

    <1> CharField
            字符串字段, 用于较短的字符串.
            CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
     
    <2> IntegerField
           #用于保存一个整数.
     
    <3> FloatField
            一个浮点数. 必须 提供两个参数:
             
            参数    描述
            max_digits    总位数(不包括小数点和符号)
            decimal_places    小数位数
                    举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                     
                    models.FloatField(..., max_digits=5, decimal_places=2)
                    要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                     
                    models.FloatField(..., max_digits=17, decimal_places=10) #max_digits大于等于17就能存储百万以上的数了
                    admin 用一个文本框(<input type="text">)表示该字段保存的数据.
     
    <4> AutoField
            一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
            自定义一个主键:my_id=models.AutoField(primary_key=True)
            如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
     
    <5> BooleanField
            A true/false field. admin 用 checkbox 来表示此类字段.
     
    <6> TextField
            一个容量很大的文本字段.
            admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
     
    <7> EmailField
            一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
     
    <8> DateField
            一个日期字段. 共有下列额外的可选参数:
            Argument    描述
            auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
            auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
            (仅仅在admin中有意义...)
     
    <9> DateTimeField
             一个日期时间字段. 类似 DateField 支持同样的附加选项.
     
    <10> ImageField
            类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
            如果提供这两个参数,则图片将按提供的高度和宽度规格保存.    
    <11> FileField
         一个文件上传字段.
         要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
         该格式将被上载文件的 date/time
         替换(so that uploaded files don't fill up the given directory).
         admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
     
         注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
                (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
                (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
                 WEB服务器用户帐号是可写的.
                (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
                 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
                 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
                 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
     
    <12> URLField
          用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
          没有返回404响应).
          admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
     
    <13> NullBooleanField
           类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
           admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes""No" ) 来表示这种字段数据.
     
    <14> SlugField
           "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
           若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #
           以前的 Django 版本,没有任何办法改变50 这个长度.
           这暗示了 db_index=True.
           它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
           the slug, via JavaScript,in the object's admin form: models.SlugField
           (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
     
    <13> XMLField
            一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
     
    <14> FilePathField
            可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
            参数    描述
            path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
            Example: "/home/images".
            match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 
            注意这个正则表达式只会应用到 base filename 而不是
            路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
            recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
            这三个参数可以同时使用.
            match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
            FilePathField(path="/home/images", match="foo.*", recursive=True)
            ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
     
    <15> IPAddressField
            一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
    <16> CommaSeparatedIntegerField
            用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.

    具体用到再细说,

    更多参数:

    (1)null
     
    如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
     
    (1)blank
     
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
     
    (2)default
     
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
     
    (3)primary_key
     
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
     
    (4)unique
     
    如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
     
    (5)choices
    由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
    (6)db_index
      如果db_index=True 则代表着为此字段设置数据库索引。
    
    
    DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
    
    (7)auto_now_add
        配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    
    (8)auto_now
        配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。

     怎样添加记录?
    写一个页面,写一个函数,将后端mysql数据库所有数据读取出来,放到前端页面展示

    写一条数据到app01_book表中

    注意,左边这个才是保存按钮.

     首先是查:

    urls.py写法

    先写一个展示数据的页面,book_list.html,目前什么都没有写

    运行,我们看一下all_books打印的是什么!!!

    all_books=models.Book.objects.all()    #拿到所有对象

    QuerySet类型是一种新的数据类型,ORM提供的一种新的数据类型.里边放的是一个个类的对象,每个对象对应一条记录

    QuerySet类型操作和列表的操作是一样的,

    all_books=models.Book.objects.all()[0]  #拿到第一个对象
    all_books=models.Book.objects.all()[0].title  #拿到第一个对象的名字

    修改如上如,我们在运行,查看

    在浏览器中输入(http://127.0.0.1:8000/book_list/)

    服务端可以得到结果如下:

    修改成第二条记录:

    运行:

    浏览器中输入地址(http://127.0.0.1:8000/book_list/)

    服务端得到如下

    修改:

    这时候,我们再写,book_list是怎样展示的,也就是写book_list.html文件

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
    </head>
    <body>
    <table>
        <thead>
            <tr>
                <th>id</th>
                <th>书名</th>
                <th>价钱</th>
                <th>出版时间</th>
                <th>出版社</th>
            </tr>
        </thead>
        <tbody>
            {% for one_book in all_books %}
                <tr>
                <td>{{ one_book.id }}</td>
                <td>{{ one_book.title }}</td>
                <td>{{ one_book.price }}</td>
                <td>{{ one_book.pub_time }}</td>
                <td>{{ one_book.publish }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    </body>
    </html>

    运行,输入地址,我们拿到如下界面

     为了让界面好看一些,我们配置动态文件,cdn,也就是网络版的bootstrap,如下图内,红框内的地址.

    添加的cdn文件

    运行:

     我们再在table里边添加属性:class="table"

     运行:得到如下结果:

    运用栅格系统,居中,自己占6份,移动3份

    具体代码:

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
    {#表开始#}
                <table class="table">
        <thead>
            <tr>
                <th>id</th>
                <th>书名</th>
                <th>价钱</th>
                <th>出版时间</th>
                <th>出版社</th>
            </tr>
        </thead>
        <tbody>
            {% for one_book in all_books %}
                <tr>
                <td>{{ one_book.id }}</td>
                <td>{{ one_book.title }}</td>
                <td>{{ one_book.price }}</td>
                <td>{{ one_book.pub_time }}</td>
                <td>{{ one_book.publish }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    {#表结束#}
            </div>
        </div>
    </div>
    
    </body>
    </html>

    运行:结果

    向下移动100px

    加上外边框:

    得到结果:

     

    再写一个添加书的功能 

     

    运行,输入地址,提交

     双击右边的书籍表,得到这样的图表,有时候需要刷新一下

     

    运行:

    反应慢,需要刷新一下.

     

     添加完成之后,应该做什么?应该显示添加之后的结果

    这样写,就将路径写死了,

     应该先起好别名

    通过别名进行反向解析,

    其实不用 reverse也是可以的,

     在views.py导入模块

    from django.urls import reverse

    访问地址:得到结果如下.

     

    如何通过按钮实现"添加",删除功能?还有,上边显示的出版日期不认识,怎么办?

    通过过滤器实现:(在book_list.html中修改)

    得到如下结果:

    "点击"添加数据,我们可以跳转到新的页面进行添加操作?
    新建一个"add_book.html"页面.

     

     在通过解析,将点击之后,地址反向到"添加书籍"上

     运行,点击添加书籍

    跳转到,

     

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width" ,initial-scale="1">
        <!--上边这个表示手机版的调整尺寸-->
        <!--上述2个meta标签"必须"放在最前面,任何其他内容都必须跟随其后-->
        <title>Title</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
    
                {#表单开始#}
                <form class="form-horizontal" action="{% url 'add_book' %}" method="post">
                    {#action 属性规定当提交表单时,向何处发送表单数据。#}
                    {% csrf_token %}
                    {#安全认证#}
                    <div class="form-group">
                        <label for="book_name" class="col-sm-2 control-label">书名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="book_name" placeholder="书名" name="book_name">
                        </div>
                    </div>
    
                    <div class="form-group">
                        <label for="book_price" class="col-sm-2 control-label">价格</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="book_price" placeholder="价格" name="book_price">
                        </div>
                    </div>
    
                    <div class="form-group">
                        <label for="book_time" class="col-sm-2 control-label">出版时间</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="book_time" placeholder="出版时间" name="book_time">
                        </div>
                    </div>
    
                    <div class="form-group">
                        <label for="book_publish" class="col-sm-2 control-label">出版社</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="book_publish" placeholder="出版社" name="book_publish">
                        </div>
                    </div>
    
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <input type="submit" value="保存" class="btn btn-default">
                        </div>
                    </div>
                </form>
                {#表单结束#}
            </div>
        </div>
    </div>
    
    </body>
    </html>
    修改之后的add_book.html

    刷新页面:

    添加下面的代码:(向下移动了100px)

     

    将保存放在右侧,颜色改成绿色

     

    出版时间,里边的input标签的type属性改成从text改成date

    现在的需求是,点击'保存',将数据发送到book_list.html页面和数据库中.

    点击"保存"之后,返回页面

    结果:成功添加进去了.

    服务端得到的结果:

    另一种创建方式,得到另一条记录

    浏览器得到的结果:

     

     保存

    服务端得到的结果:

    记录返回的结果应该是,添加完成之后的列表,所以,我们需要进行,修改返回返回的页面

    展示页面:

    点击保存:

    重点::添加数据的语句,查找数据的语句

    还有删改

     

     刷新页面:

     两个button中间加个空格

    设置垂直居中,

    实现了居中的效果:

      !important 的使用。

      !important:设置权重为无限大 
      !important 不影响继承来的权重,只影响选中的元素。不要随便使用!important,因为使用它会影响页面的布局

    7.图书管理系统删除和更改操作的ORM演示

     打印日志的配置文件,在settings里边放进去:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }  

     重启项目,就可以看到一些语句了

     运行:

     服务端什么结果都没有.

    修改

     

    运行:

    这个服务器端应该显示一条记录,但是结果是空的.

     

     

     运行:

    显示出4条结果

    思考如何让上边类的对象显示出来?

     

    获得对象的地址

    如何显示字符串的内容?

     在models里自定义一个str,不需要重启数据库,只需要重新运行项目即可

     

    再运行项目,得到结果

     filter里边的条件暂且用不了or

     

    全部删除,出版社是"18期出版社"的,数据,展示的应该是空

    运行,

     

    展示的是4本,这样的书,

    书籍列表里边也没有书了,也就是没有"18期出版社"的书籍了

     

    运行:

     点击'刷新',得到下面的结果:

     

     再看book_list,多了下面的数据.

     

    今日内容
    1.模板渲染中的组件:{% include ‘xx.html’ %}
    2.CBV通过类的方式来写视图
    from django.views import View
    class My(View):
    def get(self,request):    #获取get请求的
    self.xxx()
    pass
    def post():
    pass
    def xxx():
    pass    #其他请求方法
    #如何找到这个类?
    Url(r‘^index/’,views.My.as_view())
    
    FBV这是通过函数的形式来写视图
     
     函数装饰器:
    def wrapper(fn):
    def inner(*args,**kwargs):
    print(‘Before’)
    ret=fn(*args,**kwargs)
    print(‘after’)
    return ret
    return inner
     
    Cbv装饰器
    from django.views import View
    from django.utils.decorators import method_decorator
    @method_decorator(wrapper,name=’get’)
    class My(View):
    @method_decorator(wrapper)
    def get(self,request):
    self.xxx()
    pass
    def post()
    pass
    def xxx()
              pass
    url(r‘^index/’,views.My.as_view())
     
    ORM 对象关系映射
    类  -----  表
    类对象--- 记录
    类属性--- 字段
     
    应用里面的models文件里面写类 
     
    class Book(models.Model):
     
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32,unique=True)
        price = models.DecimalField(max_digits=16,decimal_places=2)
        pub_time = models.DateField()
        publish = models.CharField(max_length=20)
     
        def __str__(self):
            return self.title
     
    连接mysql
    1 mysql里面创建一个库
    2 配置mysql的链接(引擎)
    Settings :database
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME':'bms',           # 要连接的数据库,连接前需要创建好
            'USER':'root',        # 连接数据库的用户名
            'PASSWORD':'',        # 连接数据库的密码
            'HOST':'127.0.0.1',       # 连接主机,默认本级
            'PORT'3306            #  端口 默认3306
        }
    }
     
    项目那个包里面的init文件里面写上:
    import pymysql
    pymysql.install_as_MySQLdb()
     
    如果先添加了app应用的话,别忘了在settings配置文件里面的installapp那个列表里面注册上你的app
    引入app
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',  方式1
        'app02',                  方式2
     
    ]
     
     
    生成到MySQL数据库里面
    Python manage.py makemigrations
    Python manage.py migrate
     
     
    增:
    方式1 :book_obj = models.Book(title=’xx’,pub=’xx’)
       book_obj.save()
    方式2:models.Book.objects.create(title=’xx’,pub=’xx’)
    删:
    models.Book.objects.filter(title=’冬瓜’,id=2).delete()
    改:
    models.Book.objects.filter(title=’冬瓜’,id=2).update(title=’冬瓜’)
     
    查:
    查询所有的:models.Book.objects.all() 
    查询筛选的:models.Book.objects.filter(title=’冬瓜’,id=2)  and多添加查询
    上边两个都是querset类型
     
    今日内容总结

     对上边的问题,进一步调试:

     

     

     最终得到结果:

    对上边出错的原因可能是,没有刷新数据库等原因吧

  • 相关阅读:
    抓包来看ftp状态码
    socket基础篇
    密码复杂度检查函数
    time模块
    读取日志文件,搜索关键字,打印关键字前5行。yield、deque实例
    装饰器--函数
    yield用法
    字符编码
    pycharm + git实现两台电脑代码同步
    PyCharm常见用法
  • 原文地址:https://www.cnblogs.com/studybrother/p/10440623.html
Copyright © 2011-2022 走看看