django-ORM单表操作

1、ORM与数据库的关系

Python语法 SQL 备注
 
类属性 表字段  
对象 表记录  

2、Django 创建表

class Books(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)  # 最大值: 999999.99
    pub_date = models.DateTimeField()  # django 要求必须存这种格式:2019-07-12
    publish = models.CharField(max_length=32)

执行数据库迁移命令,生成表:(在这之前请确保settings中配置了数据库连接,比如mysql,以及存在相应的database)

3、配置Django连接MySQL数据库

见:文档https://www.cnblogs.com/miaocbin/p/11311323.html

4、ORM单表操作

4.1 增加数据

#
## 方式一:
book = Book(title="python", price=123, pub_date="2019-9-22", publish="人民出版社")
book.save()

## 方式二:推荐
book = Book.objects.create(title="python", price=123, pub_date="2019-9-22", publish="人民出版社")
print(book.title)
########### 添加书籍完整代码 ############
def addbook(request):   # get请求拿数据,post请求提交数据
    if request.method == "POST":
        title = request.POST.get('title')
        price = request.POST.get('price')
        pub_date = request.POST.get('pub_date')
        publish = request.POST.get('publish')
        Books.objects.create(title=title, price=price, pub_date=pub_date, publish=publish)
        return redirect(reverse("books"))
    else:  # get请求,请求的是添加书籍的表单页面,返回addbook.html页面给用户
        return render(request, "addbook.html", locals())

展示页面

<!-- 书籍显示:完整的前端代码 -->
<!-- 书籍添加:完整的前端代码 -->
<h3>添加书籍</h3>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <!--action在此处硬编码了,也可以利用反向解析实现:action="{% url 'addbook' %}"-->
            <form action="/books/add/" method="post">   <!-- action 可以什么都不写,默认发到当前页面 -->
                {% csrf_token %}
                <div class="form-group"><label for="title">书籍名称</label>
                    <input type="text" class="form-control" id="title" placeholder="Title" name="title">
                </div>
                <div class="form-group"><label for="price">价格</label>
                    <input type="text" class="form-control" id="price" placeholder="Price" name="price">
                </div>
                <div class="form-group"><label for="pub_date">出版日期</label>
                    <input type="date" class="form-control" id="pub_date" placeholder="pub_date" name="pub_date">
                </div>
                <div class="form-group"><label for="publish">出版社</label>
                    <input type="text" class="form-control" id="publish" placeholder="publish" name="publish">
                </div>
                <button type="submit" class="btn btn-success pull-right">Submit</button>
            </form>
        </div>
    </div>
</div>

4.2 查询数据

# 查 -- 用的最多,最繁琐的
## 查询所有,结果为QuerySet(特殊的列表),可以for循环,可以切片 取数据
book_list = Book.objects.all()   # <QuerySet [<Books: Books object (1)>, <Books: Books object (2)>]>
## 条件查询
book_list= Book.objects.filter(price=100) # 返回的结果也是 QuerySet

################# 完整的后端代码 #################
def books(request):
    # 查询所有
    book_list = Books.objects.all()
    return render(request, "books.html", {"book_list": book_list})

展示数据

<!-- 书籍显示:完整的前端代码 -->
<h3>书籍列表</h3>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
        <a href="/books/add/" class="btn btn-primary">添加书籍</a>
            <table class="table table-striped table-hover">  <!-- striped为斑马线,hover为悬浮效果-->
                <thead>
                <tr>
                    <th>编号</th>
                    <th>书籍名称</th>
                    <th>价格</th>
                    <th>出版日期</th>
                    <th>出版社</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for book in book_list %}
                    <tr>
                        <td>{{ book.nid }}</td>
                        <td>{{ book.title }}</td>
                        <td>{{ book.price }}</td>
                        <td>{{ book.pub_date|date:'Y-m-d'}}</td>
                        <td>{{ book.publish }}</td>
                    <td>
                        <a href="/books/edit/{{ book.nid }}" class="btn btn-warning btn-sm">编辑</a>
                        <!--href这里也是硬编码了,可以写成:href="{% url 'editbook' book.nid %}"-->
                        <!-- 如果有多个动态参数,用空格隔开即可 -->
                        <a href="/books/delete/{{ book.nid }}/" class="btn btn-danger btn-sm">删除</a>
                    </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

4.3 删除数据

# 删 -- 想删谁,要先查出来,要用到查询
Book.objects.filter(nid=3).delete()   # 先找到要删除的结果(QuerySet),直接删除
Book.objects.get(nid=7).delete()   # model对象,找到自己,然后删除
####### 完整的后端代码 ########
def delbooks(request, delete_book_id):
    Books.objects.filter(nid=delete_book_id).delete()
    return redirect(reverse("books"))

4.4 修改数据

# 改,与删的语法都很简单,关键点在于查,怎么能够将要操作的记录给查出来,语法如下
Books.objects.filter(nid=edit_book_id).update(price=120)  # http://127.0.0.1:8000/edit/9 就直接修改掉了
Books.objects.filter(price=111).update(publish="南京出版社")
return redirect("/books/")
############## 完整代码 ################
def editbooks(request, edit_book_id):
    if request.method == "GET":
        edit_book = Books.objects.filter(nid=edit_book_id)[0]
        return render(request, "editbook.html", {"edit_book": edit_book})
    else:
        title = request.POST.get('title')
        price = request.POST.get('price')
        pub_date = request.POST.get('pub_date')
        publish = request.POST.get('publish')
        Books.objects.filter(nid=edit_book_id).update(title=title, price=price, pub_date=pub_date, publish=publish)
        return redirect(reverse("books"))

展示数据

<!-- 书籍编辑:完整的前端代码 -->
<a href="#">编辑书籍</a>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <form action="" method="post">   <!-- action 可以什么都不写,默认发到当前页面 /books/edit/{{ edit_book.nid }} -->
                {% csrf_token %}
                <div class="form-group"><label for="title">书籍名称</label>
                    <input type="text" value="{{ edit_book.title }}" class="form-control" id="title" placeholder="Title" name="title">
                </div>
                <div class="form-group"><label for="price">价格</label>
                    <input type="text" value="{{ edit_book.price }}" class="form-control" id="price" placeholder="Price" name="price">
                </div>
                <div class="form-group"><label for="pub_date">出版日期</label>
                    <input type="date" value="{{ edit_book.pub_date|date:'Y-m-d'}}" class="form-control" id="pub_date" placeholder="pub_date" name="pub_date">
                </div>
                <div class="form-group"><label for="publish">出版社</label>
                    <input type="text" value="{{ edit_book.publish }}" class="form-control" id="publish" placeholder="publish" name="publish">
                </div>
                <button type="submit" class="btn btn-success pull-right">Submit</button>
            </form>
        </div>
    </div>
</div>

5、美化显示模板

<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
   .container {
        margin-top: 65px;
    }
</style>

6、URL路由配置

from django.contrib import admin
from django.urls import path, re_path
from book import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/add/', views.addbook, name='addbook'),
    re_path('books/delete/(\d+)/', views.delbooks, name='delbooks'),
    re_path('books/edit/(\d+)/', views.editbooks, name='editbooks'),
    path('books/', views.books, name='books'),
    path('index/', views.index, name='index'),
]

7、ORM 查询补充--单表查询API

  1. all() 查询所有结果

  2. filter() 带条件查询

  3. get() 查询结果只有一个,超过一个或没有都会报错(应用场景:)

  4. exclude() 查询与所给条件不匹配的对象

  5. order_by() 对查询结果排序

  6. reverse() 对查询结果倒序

  7. count() 返回匹配结果的个数

  8. first() 返回第一条记录

  9. last() 返回最后一条记录

  10. exists() 如果QuerySet包含数据返回True,否则返回False,bool值

  11. values() 返回一个特殊的Queryset,运行后得到的并不是一列model实例化对象,而是一个可迭代的字典序列

  12. values_list() 与values相似,返回的是一个元组序列,values返回的是一个字典序列

  13. distinct() 对查询结果去重

# queryset
# get()方法应用场景(它的特性决定了它的使用场景很特别)
# 在上面的编辑书籍代码中的filter方法也可以换成get方法,因为用主键查询到的结果有且只有一个,不可能有重复的。又因为是编辑书籍,书籍也不可能不存在,所以这里用get方法很完美。
edit_book = Books.objects.get(nid=edit_book_id)   # 使用get方法,利用要编辑书籍的id,找到要编辑的书籍操作

# 1 all()  返回 QuerySet
ret = Books.objects.all()  # <QuerySet [<Books: Python>, <Books: Shell>, <Books: GO>, <Books: ELK>]>
print(ret)
# 2 filter 返回 QuerySet
ret = Books.objects.filter(title='linux')  # <QuerySet [<Books: linux>]>
ret = Books.objects.filter(title='linux', price=23)  # <QuerySet [<Books: linux>]>
print(ret)
# 3 get() 返回查询到的 model对象,查到的结果有且只有一个才能正确返回,超过一个或不足一个就报错
ret = Books.objects.get(title='linux')
print(ret.title)   # model对象可以去点它的属性
# 4 first(),last()方法 QuerySet调用,返回model对象
fbook = Books.objects.all()[0]
fbook = Books.objects.all().first()
lbook = Books.objects.all().last()
# 5 exclude() 返回 QuerySet
ret = Books.objects.exclude(price=111)  # <QuerySet [<Books: Python>, <Books: ELK>, <Books: linux>]>
print(ret)
# 6 order_by() 返回 QuerySet
ret = Books.objects.all().order_by("price")
# 默认升序<QuerySet [<Books: linux>, <Books: ELK>, <Books: Python>, <Books: Shell>, <Books: GO>]>
ret = Books.objects.all().order_by("-price")
# 降序 <QuerySet [<Books: Shell>, <Books: GO>, <Books: Python>, <Books: ELK>, <Books: linux>]>
print(ret)

8、基于双下线的模糊查询

Book.objects.filter(price__in=[100,200,300])
Book.objects.filter(price__gt=100)
Book.objects.filter(price__gte=100)
Book.objects.filter(price__lt=100)
Book.objects.filter(price__range=[100,200])
Book.objects.filter(title__contains="python")
Book.objects.filter(title__icontains="python")
Book.objects.filter(title__startswith="py")
Book.objects.filter(pub_date__year=2012)

猜你喜欢

转载自www.cnblogs.com/miaocbin/p/11311438.html