巨蟒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类型
 
今日内容总结

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

 

 

 最终得到结果:

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

原文地址:https://www.cnblogs.com/studybrother/p/10440623.html