我爱Django框架之Django数据库操作与图书管理系统简易版(你想要的这都有!!!)

Django连接数据库

安装MySQL驱动

       •当你要使用Django框架来操作MySQL时,底层还是通过Python操作实现的,因此要想用Django框架来操作MySQL时,首先必须要安装数据库驱动程序
       •常见MySQL驱动:
              •MySQLdb
              是对C语言操作MySQL数据库的简单封装,遵循了Python DB API v2,但是只支持Python2,目前还不支持Python3
              mysqlclient
              •是MySQL-python的另外一个分支,支持Python3并且修复了一些bug
              pymysql
              •纯Python实现的一个驱动,因为是纯Python编写的,因此执行效率不如MySQL-python,但是可以和Python代码无缝衔接
              mysql-connector
              •MySQL官方推出的使用纯Python连接MySQL的驱动,同样效率不高

       •这里我们选择mysqlclient驱动,直接使用命令pip install mysqlclient即可安装,如安装出错可能是以下情况造成:
       •(1)使用国内网安装,下载速度过慢导致安装失败
              解决方案:换源安装驱动,参考这篇文章pip换源安装python各种库(终极详细版)即可解决
       •(1)pip版本较低导致安装失败
              解决方案:使用命令:python -m pip install --upgrade pip来升级pip版本即可解决

Django配置数据库连接

Django支持MySQL 5.6及更高版本,同时推荐使用mysqlclient作为数据库引擎
       •(1)新建项目Django_demo_db
       •(2)在项目目录下的settings.py文件进行数据库配置
在这里插入图片描述
       •配置如下:

# 数据库配置默认使用 大写
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 将数据库改为MySQL 默认为Django自带的sqlite3
        'NAME': 'django_demo1',  # 数据库名称
        'HOST': '127.0.0.1',  # 本地地址 默认为127.0.0.1
        'PORT': 3306,  # 端口号 MySQL默认端口为3306
        'USER': 'root',  # 用户名 自己设置的
        'PASSWORD': 'root'  # 用户密码 自己设置
    }
}

       •在启动项目前,需要先开启MySQL服务,可以通过系统服务、命令行开启,也可以使用集成工具如PHPStudy开启,前提是已将安装MySQL或者使用PHPStudy安装,然后可以使用Navicat、SQLYog等数据库可视化工具操作MySQL数据库

注意

       •如果你对上述安装过程有疑问或者没有上述安装包,可在博文下留言,博主第一时间看到会回复并免费发送以上文件

       •在这里我们使用SQLYog这个可视化工具来操作MySQL数据库
       •开启服务后需要在SQLYog中创建一个名为django_demo1的数据库,同时执行python manage.py migrate映射数据库,完成后即可在SQLYog中参看
创建数据库:
在这里插入图片描述
使用命令映射数据库后查看SQLYog:
在这里插入图片描述
       •显然,已经将Django自带的系统表映射到了数据库中,这是Django为了实现一些默认的业务逻辑而建立的,同时说明连接数据库已经成功

原生SQL操作数据库

       •Django中操作数据库有两种方式:
              第一种方式就是使用原生SQL语句操作,第二种就是使用ORM模型来操作。

       •在Django中使用原生SQL语句操作其实就是使用Python DB API的接口来操作的
       •如果你使用的MySQL驱动是pymysql,就是使用pymysql来操作的

       •Django将数据库连接已经封装好了,只要在settings.py文件中配置好数据库连接信息后,即可直接使用Django封装好的接口操作数据库

       •创建表book,如下:

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `price` float(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

       •也可以使用可视化工具SQLYog创建:
在这里插入图片描述
       •通过命令插入两条数据:

insert into book values(null, 'Python', 88), (null, 'Java', 99);

       •新建名为book的app,book下的views.py文件如下:

from django.http import HttpResponse
from django.db import connection


def index(request):
    # 获取对象
    cursor = connection.cursor()
    # 执行SQL语句
    cursor.execute('select * from book')
    # 获取1条数据
    data = cursor.fetchone()
    print(data)
    # 获取多条数据
    data = cursor.fetchall()
    print(data)
    return HttpResponse('图书首页')

       •网页显示:
在这里插入图片描述
此时访问http://127.0.0.1:8000/,控制台打印为:

(1, 'Python', 88.0)
((2, 'Java', 99.0),)

由控制台打印看看出:
       •在获取一条数据时,返回一个元组
       •获取所有数据时,返回由元组组成的元组,一个元组代表一条数据
       •execute()fetchone()fetchall()方法都是Python DB API规范中定义好的,任何使用Python来操作MySQL的驱动程序都应该遵循该规范,因为不管是使用pymysql或者是mysqlclient或者是mysqldb驱动,接口都是一样的

       •Python DB API规范下cursor对象常用接口如下:

操作含义
description如果cursor执行了SQL语句,那么执行cursor.description属性会返回一个列表,这个列表中装的是元组,元组中装的分别是(name,type_code,display_size,internal_size,precision,scale,null_ok),其中name代表的是查找出来的数据的字段名称
rowcount代表的是在执行了SQL语句后受影响的行数
close关闭游标,关闭游标以后就再也不能使用了,否则会抛出异常
execute(sql[,parameters])执行SQL语句,还可以根据需要传递参数,定义parameters属性即可
fetchone在执行了查询操作以后,获取第一条数据
fetchmany(size)在执行查询操作以后,获取多条数据,具体是多少条要看传的size参数,如果不传size参数,那么默认是获取第一条数据
fetchall获取所有满足sql语句的数据

       •测试上述操作如下:

from django.http import HttpResponse
from django.db import connection


def index(request):
    # 获取游标对象
    cursor = connection.cursor()
    # 执行SQL语句
    cursor.execute('select * from book')
    # 获取1条数据
    data = cursor.fetchone()
    print(data)
    # 获取多条数据
    data = cursor.fetchall()
    print(data)
    print(cursor.rowcount)
    return HttpResponse('图书首页')

访问http://127.0.0.1:8000/,控制台打印为:

(1, 'Python', 88.0)
((2, 'Java', 99.0),)
2

案例:图书馆系统(Django简易版)

       •使用原生SQL方式实现一个图书管理系统,完成图书的增删查和前端页面展示

图书首页

       •book下的views.py视图文件如下:

from django.shortcuts import render
from django.db import connection


def index(request):
    cursor = connection.cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)

       •book下新建urls.py路由文件:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index')
]

       •项目目录下的urls.py文件如下:

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', include('book.urls')),
]

       •项目目录下新建templates目录,在templates下新建index.html文夹如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书首页</title>
</head>
<body>
<ul>
    <li><a href="{% url 'index' %}">首页</a></li>
    <li><a href="#">发布图书</a></li>
</ul>

<table>
    <tr>
        <th>序号</th>
        <th>图书名称</th>
        <th>图书价格</th>
    </tr>
    {% for book in books %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ book.1 }}</td>
            <td>{{ book.2 }}</td>
        </tr>
    {% endfor %}

</table>
</body>
</html>

       •项目目录下settings.py文件中修改模板路径如下:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # 修改模板路径
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

       •启动项目并访问http://127.0.0.1:8000/book/,网页显示如下:
在这里插入图片描述
       •由上可以看出:已显示图书的基本信息(数据库中所保存的)

图书添加

       •下面使用的多个模板有公共部分,可以使用模板继承优化模板结构,新建base.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
<ul>
    <li><a href="{% url 'index' %}">首页</a></li>
    <li><a href="{% url 'add_book' %}">发布图书</a></li>
</ul>

    {% block content %}

    {% endblock %}

</body>
</html>

       •index.html文件如下:

{% extends 'base.html' %}

{% block title %}
    图书首页
{% endblock %}

{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>图书名称</th>
            <th>图书价格</th>
        </tr>
        {% for book in books %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ book.1 }}</td>
                <td>{{ book.2 }}</td>
            </tr>
        {% endfor %}
    </table>
{% endblock %}

       •templates目录下新建add_book.html文件如下(添加图书模板):

{% extends 'base.html' %}

{% block title %}
    添加图书
{% endblock %}

{% block content %}
    <form action="" method="post">
        图书名称:<input type="text" name="name"><br>
        图书价格:<input type="text" name="price"><br>
        <input type="submit" value="提交">
    </form>
    
{% endblock %}

       •book下的views.py视图文件如下:

from django.shortcuts import render
from django.db import connection


def index(request):
    cursor = connection.cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)


def add_book(request):
    return render(request, 'add_book.html')

       •book下的urls.py路由文件如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('add_book/', views.add_book, name='add_bbok')
]

       •启动项目并访问http://127.0.0.1:8000/book/,网页显示如下:
在这里插入图片描述

       •访问报错,提示CSRF验证失败、请求已中止
              Django框架为表单提交设置了CSRF保护,解决办法有两种:
              (1)关闭Django框架的CSRF保护,即在项目目录下settings.py中移除CSRF保护中间件即可:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

              (2)模板中增加CSRF标签

{% extends 'base.html' %}

{% block title %}
    添加图书
{% endblock %}

{% block content %}
    <form action="" method="post">
        {% csrf_token %}
        图书名称:<input type="text" name="name"><br>
        图书价格:<input type="text" name="price"><br>
        <input type="submit" value="提交">
    </form>
    
{% endblock %}

       •网页显示如下:
在这里插入图片描述

       •由上可看出,网页可以正常访问,并且模板中加载了隐藏的CSRF Token推荐使用第二种方式

       •在views.py视图文件中实现图书提交之后的代码逻辑,代码如下:

from django.shortcuts import render, redirect, reverse
from django.db import connection


def get_cursor():
    return connection.cursor()


def index(request):
    cursor = get_cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)


def add_book(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        price = request.POST.get('price')
        cursor = get_cursor()
        cursor.execute("insert into book(`name`, `price`) values('%s', '%s')" % (name, price))
        return redirect(reverse('index'))
    else:
        return render(request, 'add_book.html')

       •代码测试如下:
在这里插入图片描述
       •数据库显示如下:
在这里插入图片描述

       •显然,此时可以正常添加数据,并且添加成功后重定向到首页;
       •对于添加add_book路由来说,如果请求方法为GET,直接渲染模板,如果请求方法为POST,则进行数据提交,提交后重定向到首页模板并将数据添加到数据库

图书详情

       •book下的视图函数views.py如下:

from django.shortcuts import render, redirect, reverse
from django.db import connection


def get_cursor():
    return connection.cursor()


def index(request):
    cursor = get_cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)


def add_book(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        price = request.POST.get('price')
        cursor = get_cursor()
        cursor.execute("insert into book(`name`, `price`) values('%s', '%s')" % (name, price))
        return redirect(reverse('index'))
    else:
        return render(request, 'add_book.html')


def book_detail(request, book_id):
    cursor = get_cursor()
    cursor.execute("select * from book where id=%s" % book_id)
    book = cursor.fetchone()
    context = {
        'book': book
    }
    return render(request, 'book_detail.html', context=context)

       •book下的路由urls.py如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('add_book/', views.add_book, name='add_book'),
    path('book_detail/<int:book_id>', views.book_detail, name='book_detail'),
]

       •templates目录下的index.html如下:

{% extends 'base.html' %}

{% block title %}
    图书首页
{% endblock %}

{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>图书名称</th>
            <th>图书价格</th>
        </tr>
        {% for book in books %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td><a href="{%  url 'book_detail' book_id=book.0 %}">{{ book.1 }}</a></td>
                <td>{{ book.2 }}</td>
            </tr>
        {% endfor %}

    </table>
{% endblock %}

       •templates目录下新建的book_detail.html如下:

{% extends 'base.html' %}

{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>图书名称</th>
            <th>图书价格</th>
        </tr>
        <tr>
            <td>{{ book.0 }}</td>
            <td>{{ book.1 }}</td>
            <td>{{ book.2 }}</td>
        </tr>

    </table>
{% endblock %}

       •网页显示:
在这里插入图片描述

       •查看图书详情成功

图书删除

       •views.py中实现删除图书如下:

from django.shortcuts import render, redirect, reverse
from django.db import connection


def get_cursor():
    return connection.cursor()

def index(request):
    cursor = get_cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)


def add_book(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        price = request.POST.get('price')
        cursor = get_cursor()
        cursor.execute("insert into book(`name`, `price`) values('%s', '%s')" % (name, price))
        return redirect(reverse('index'))
    else:
        return render(request, 'add_book.html')


def book_detail(request, book_id):
    cursor = get_cursor()
    cursor.execute("select * from book where id=%s" % book_id)
    book = cursor.fetchone()
    context = {
        'book': book
    }
    return render(request, 'book_detail.html', context=context)


def book_delete(request, book_id):
    if book_id:
        cursor = get_cursor()
        cursor.execute("delete from book where id=%s" % book_id)
        return redirect(reverse('index'))
    else:
        return render(request, 'book_detail.html')

       •book下的urls.py文件如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('add_book/', views.add_book, name='add_book'),
    path('book_detail/<int:book_id>', views.book_detail, name='book_detail'),
    path('book_delete/<int:book_id>', views.book_delete, name='book_delete'),
]

       •templates下的book_detail.html如下:

{% extends 'base.html' %}

{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>图书名称</th>
            <th>图书价格</th>
            <th>操作/删除</th>
        </tr>
        <tr>
            <td>{{ book.0 }}</td>
            <td>{{ book.1 }}</td>
            <td>{{ book.2 }}</td>
            <td><a href="{% url 'book_delete' book_id=book.0 %}">删除图书</a></td>
        </tr>

    </table>
{% endblock %}

       •网页显示如下:
在这里插入图片描述

       •数据库显示如下:
在这里插入图片描述
       •显然删除图书成功

图书修改

       •views.py中实现修改图书业务逻辑:

from django.shortcuts import render, redirect, reverse
from django.db import connection


def get_cursor():
    return connection.cursor()

def index(request):
    cursor = get_cursor()
    cursor.execute('select * from book')
    books = cursor.fetchall()
    context = {
        'books': books
    }
    return render(request, 'index.html', context=context)


def add_book(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        price = request.POST.get('price')
        cursor = get_cursor()
        cursor.execute("insert into book(`name`, `price`) values('%s', '%s')" % (name, price))
        return redirect(reverse('index'))
    else:
        return render(request, 'add_book.html')


def book_detail(request, book_id):
    cursor = get_cursor()
    cursor.execute("select * from book where id=%s" % book_id)
    book = cursor.fetchone()
    context = {
        'book': book
    }
    return render(request, 'book_detail.html', context=context)


def book_delete(request, book_id):
    if book_id:
        cursor = get_cursor()
        cursor.execute("delete from book where id=%s" % book_id)
        return redirect(reverse('index'))
    else:
        return render(request, 'book_detail.html')


def update_book(request, book_id):
    cursor = get_cursor()
    if request.method == 'POST':
        name = request.POST.get('name')
        price = request.POST.get('price')
        book_id = request.POST.get('book_id')
        cursor.execute("update book set name='%s', price='%s'where id='%s'" % (name, price, book_id))
        return redirect(reverse('index'))
    else:
        cursor.execute("select * from book where id=%s" % book_id)
        book = cursor.fetchone()
        context = {
            'book': book
        }
        return render(request, 'book_update.html', context=context)

       •book下的urls.py文件如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('add_book/', views.add_book, name='add_book'),
    path('book_detail/<int:book_id>', views.book_detail, name='book_detail'),
    path('book_delete/<int:book_id>', views.book_delete, name='book_delete'),
    path('update_book/<int:book_id>', views.update_book, name='update_book'),
]

       •templates下的index.html如下:

{% extends 'base.html' %}

{% block title %}
    图书首页
{% endblock %}

{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>图书名称</th>
            <th>图书价格</th>
            <th>修改信息</th>
        </tr>
        {% for book in books %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td><a href="{%  url 'book_detail' book_id=book.0 %}">{{ book.1 }}</a></td>
                <td>{{ book.2 }}</td>
                <td><a href="{% url 'update_book' book_id=book.0 %}">修改</a></td>
            </tr>
        {% endfor %}

    </table>
{% endblock %}

       •templates下新建book_update.html如下:

{% extends 'base.html' %}

{% block content %}
    <form action="" method="post">
        {% csrf_token %}
        <table>
            <tr>
                <th>序号</th>
                <th>图书名称</th>
                <th>图书价格</th>
            </tr>
            <tr>
                <td>{{ book.0 }}</td>
                <td><input type="hidden" value="{{ book.0 }}" name="book_id"></td>
                <td><input type="text" value="{{ book.1 }}" name="name"></td>
                <td><input type="text" value="{{ book.2 }}" name="price"></td>
                <td><input type="submit" value="提交"></td>
            </tr>
        </table>
    </form>

{% endblock %}

       •网页显示如下:
在这里插入图片描述

       •数据库显示如下:
在这里插入图片描述

       •显示已经实现修改图书的功能

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值