Python全栈之路-Django(八)

1 CBV

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test.html$', views.test),
    url(r'^login.html$', views.Login.as_view()),
]

app01.views.py

from django.views import View


class Login(View):
    """
    get     查找
    post    创建
    put     更新
    delete  删除
    """
    # 寻找类里面的功能函数
    def dispatch(self, request, *args, **kwargs):
        # 类似装饰器功能
        print('执行前')
        obj = super(Login, self).dispatch(request, *args, **kwargs)
        print('执行后')
        return obj

    def get(self, request):
        # return HttpResponse('Login get')
        return render(request, 'login.html')

    def post(self, request):
        print(request.POST.get('user'))
        return HttpResponse('Login post')

templates.login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login.html" method="post">
    {% csrf_token %}
    <input type="text" name="user">
    <input type="submit" value="提交">
</form>

</body>
</html>

2 ORM 操作

ForeignKey 正/反向操作以及连表操作

from django.shortcuts import render,HttpResponse

# Create your views here.

# 数据库操作
from app01 import models
def test(request):
    # 创建数据
    # models.UserType.objects.create(title='普通用户')
    # models.UserType.objects.create(title='超级用户')
    # models.UserType.objects.create(title='牛逼用户')
    # models.UserInfo.objects.create(name='万永振', age=18, ut_id=2)
    # models.UserInfo.objects.create(name='李智', age=18, ut_id=2)
    # models.UserInfo.objects.create(name='温艳杰', age=18, ut_id=1)
    # models.UserInfo.objects.create(name='苏浩智', age=18, ut_id=1)
    # models.UserInfo.objects.create(name='杨振威', age=18, ut_id=3)
    # models.UserInfo.objects.create(name='韩星宇', age=18, ut_id=3)

    # 查找
    # 正向操作
    result = models.UserInfo.objects.all()
    for obj in result:
        print(obj.id, obj.name, obj.age, obj.ut_id, obj.ut.title)
    result = models.UserInfo.objects.all().first() # 取一行数据
    print(obj.id, obj.name, obj.age, obj.ut_id, obj.ut.title) # ut是ForeignKey字段
    # 反向操作
    # 表名小写_set.all() 查找与之关联的多条数据行
    result = models.UserType.objects.all()
    for obj in result:
        print(obj.id, obj.title, obj.userinfo_set.all()) # obj.userinfo_set.all() QuerySet类型
    result = models.UserType.objects.all()
    for item in result:
        print(item.title, item.userinfo_set.filter(name='万永振'))
    # 连表操作
    # 0 默认
    # QuerySet 里面是对象类型  遍历时可以跨表(会产生多次查询,效率低)
    result = models.UserInfo.objects.all()
    result = models.UserInfo.objects.filter(id=1)

    # 1 .values
    result = models.UserInfo.objects.all().values('id', 'name')
    # result = models.UserInfo.objects.all().values('id', 'name', 'ut__title') # 获取数据时跨表
    # QuerySet 但是里面是字典类型  遍历时不能跨表
    for row in result:
        print(row)   # {'id': 1, 'name': '万永振'} ...
    # 2 .values_list
    result = models.UserInfo.objects.all().values_list('id', 'name')
    # result = models.UserInfo.objects.all().values_list('id', 'name', 'ut__title') # 获取数据时跨表
    # QuerySet 但是里面是元组类型  遍历时不能跨表
    for row in result:
        print(row)   # (1, '万永振') ...
    # 反向操作
    # 1. 小写的表名_set
    obj = models.UserType.objects.all().first()
    result = obj.userinfo_set.all()
    print(result)
    # 2. 小写的表名
    result = models.UserType.objects.all().values('id', 'title')
    print(result)
    result = models.UserType.objects.all().values('id', 'title', 'userinfo')
    print(result)
    result = models.UserType.objects.all().values('id', 'title', 'userinfo__age')
    print(result)
    return HttpResponse('...')

3 分页

分批获取数据

models.UserInfo.objects.all()[0:10]
models.UserInfo.objects.all()[10:20]

3.1 Django自带分页

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test.html$', views.test),
    url(r'^login.html$', views.Login.as_view()),
    url(r'^index.html$', views.index),
]

app01.views.py

from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage
from django.shortcuts import render,HttpResponse

def index(request):
    """
    分页功能
    :param request: 
    :return: 
    """
    # 生产测试数据
    # for i in range(300):
    #     name='root' + str(i)
    #     models.UserInfo.objects.create(name=name, age=18, ut_id=1)
    current_page = request.GET.get('page')
    user_list = models.UserInfo.objects.all()
    paginator = Paginator(user_list, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
    except PageNotAnInteger as e:
        # 非数字跳到第一页
        posts = paginator.page(1)
    except EmptyPage as e:
        # 负数跳到第一页
        posts = paginator.page(1)
    # has_next              是否有下一页
    # next_page_number      下一页页码
    # has_previous          是否有上一页
    # previous_page_number  上一页页码
    # object_list           分页之后的数据列表
    # number                当前页
    # paginator             paginator对象

    return render(request, 'index.html', {'posts': posts})

templates.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <ul>
        {% for user in posts.object_list %}
        <li>{{ user.name }} </li>
        {% endfor %}

    </ul>
    <div>
        {% if posts.has_previous %}
            <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
        {% endif %}

        {% for num in posts.paginator.page_range %}
            <a href="/index.html?page={{ num }}">{{ num }}</a>
        {% endfor %}
        
        {% if posts.has_next %}
            <a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
        {% endif %}
    </div>
</body>
</html>

3.2 自定义分页

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test.html$', views.test),
    url(r'^login.html$', views.Login.as_view()),
    url(r'^index.html$', views.index),
    url(r'^custom.html$', views.custom),
]

views.py

from utils.pager import PageInfo
from django.shortcuts import render


def custom(request):
    all_count = models.UserInfo.objects.all().count()
    page_info = PageInfo(request.GET.get('page'), 10, all_count, '/custom.html')
    user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]

    return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})

utils.pager.py

#!/usr/bin/env python
# __Author__: "wanyongzhen"
# Date: 2017/7/3

# 自定义分页
class PageInfo(object):
    def __init__(self, current_page, per_page, all_count, base_url, show_page=11):
        """

        :param current_page: 当前页的页码
        :param per_page: 每页显示的行数
        :param all_count: 总行数
        :param base_url: 指定url地址
        :param show_page: 总共显示多少页码
        """
        try:
            self.current_page = int(current_page)
        except Exception as e:
            self.current_page = 1

        self.per_page = per_page
        self.all_count = all_count
        self.base_url = base_url
        self.show_page = show_page
        a, b = divmod(self.all_count, per_page)
        if b:
            a = a + 1
        self.all_pager = a  # 总页数
        if self.current_page < 1 or self.current_page > self.all_pager:
            self.current_page = 1

    def start(self):
        return (self.current_page - 1) * self.per_page

    def end(self):
        return self.current_page * self.per_page

    def pager(self):
        page_list = []
        half = int((self.show_page - 1) / 2)
        # 如果数据总页数 < 11
        print(self.all_pager, self.show_page)
        if self.all_pager < self.show_page:
            begin = 1
            stop = self.all_pager + 1
        # 如果数据总页数 >= 11
        else:
            # 如果当前页小于等于half 永远显示 1 - 11页
            if self.current_page <= half:
                begin = 1
                stop = self.show_page + 1
            # 如果当前页大于half并且小于(最大页-half)正常显示
            elif self.current_page > half and self.current_page < (self.all_pager - half):
                begin = self.current_page - half
                stop = self.current_page + half + 1
            # 如果当前页大于等于(最大页-half) 显示最后11页
            elif self.current_page >= (self.all_pager - half):
                begin = self.all_pager - self.show_page
                stop = self.all_pager + 1

        # begin = self.current_page - half
        # stop = self.current_page + half + 1
        if self.current_page <= 1:
            prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page)
        else:
            prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page - 1)
        page_list.append(prev)
        for i in range(begin, stop):
            if i == self.current_page:
                temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
            else:
                temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
            page_list.append(temp)
        if self.current_page >= self.all_pager:
            after = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page)
        else:
            after = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1)
        page_list.append(after)

        return ''.join(page_list)
原文地址:https://www.cnblogs.com/wanyuetian/p/7113408.html