Django之admin管理数据库,cookie验证及分页设置

Posted linu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之admin管理数据库,cookie验证及分页设置相关的知识,希望对你有一定的参考价值。

一、admin管理数据库

1)models.py创建class类表

技术分享图片
class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")    # 会自动生成多对多的book_author的关系表

    def __str__(self):
        return self.name

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField(default=20)

    def __str__(self):
        return self.name
models.py

 强调:配置文件加入app,  LANGUAGE_CODE = ‘zh-hans‘ 修改后台显示语言

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser     生成管理员账号及密码

2)运行Django,输入http://127.0.0.1:8000/admin。

 技术分享图片

 技术分享图片

 3)添加admin管理model创建的表

name=models.CharField(max_length=20,verbose_name="姓名")  起别名
price=models.IntegerField("价格")   # 起别名
技术分享图片
from django.contrib import admin
from admin_orm import models
# Register your models here.

admin.site.register(models.Author)
admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.py

 技术分享图片

 4)自定义admin管理models表

技术分享图片
from django.contrib import admin
from admin_orm import models
# Register your models here.

# 自定义表的后台管理
class BookAdmin(admin.ModelAdmin):
    list_display = (id,name,price,pub_date)
    # 字段横着显示,字段显示不能加多对多的字段

    list_editable = (name,price)        # 横着显示,修改字段
    filter_horizontal = (authors,)         # 添加字段内容的搜索框
    list_per_page = 5          # 分页,显示数据的长度,默认是20条
    search_fields = (id,name,publish__name)
    # 按照字段搜索,publish__name因为关联了别的表,所有以 publish的name搜索

    list_filter = (pub_date,publish)    # 过滤
    ordering = ("price",id)   # 排序
    # filter_vertical =    # 垂直的,
    # fieldsets =[
    #     (None,               {fields: [title]}),
    #     (price information, {fields: [price,"publisher"], classes: [collapse]}),
    # ]         # 隐藏增加属性

admin.site.register(models.Author)
admin.site.register(models.Book,BookAdmin)      #  引用自定义的后台管理表内容
admin.site.register(models.Publish)
admin.py

技术分享图片

 技术分享图片

二、学生信息管理(自定义网站管理(数据库))

1)创建学生信息表

技术分享图片
from django.db import models

# Create your models here.
class Classes(models.Model):
    ‘‘‘
    班级表,与老师是 一对多的关系
    ‘‘‘
    titile = models.CharField(max_length=32)
    m = models.ManyToManyField("Teachers")

class Teachers(models.Model):
    ‘‘‘
    老师表
    ‘‘‘
    name = models.CharField(max_length=32)

class Student(models.Model):
    ‘‘‘
    学生表,班级是一对多的关系
    ‘‘‘
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.BooleanField()
    cs = models.ForeignKey(Classes)
models.py

2)编辑前端文件

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>
        <a href="/add_classes.html">添加</a>
    </div>
    <div>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>名称</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                {% for row in cls_list %}
                    <tr>
                        <td>
                            {{ row.id }}
                        </td>
                        <td>
                            {{ row.titile}}
                        </td>
                        <td>
                            <a href="/del_classes.html?nid={{ row.id }}">删除</a>
                            |
                            <a href="/edit_classes.html?nid={{ row.id }}">编辑</a>
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
</body>
</html>
get_classes.html
技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="add_classes.html" method="POST">
        {% csrf_token %}
        <input type="text" name="title">
        <input type="submit" value="提交">
    </form>


</body>
</html>
add_classes.html
技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="POST" action="/edit_classes.html?nid={{ obj.id }}">
        {% csrf_token %}
        <input type="text" name="xxoo" value="{{ obj.titile }}"/>
        <input type="submit" value="提交" />
    </form>
</body>
</html>
edit_classes.html

 3)定义路由

技术分享图片
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^classes.html,classes.get_classes),
    url(r^add_classes.html,classes.add_classes),
    url(r^del_classes.html, classes.del_classes),
    url(r^edit_classes.html, classes.edit_classes),
]
urls.py

4)创建视图函数

技术分享图片
from django.shortcuts import render,redirect
from app01 import models
# Create your views here.

def get_classes(request):
    cls_list = models.Classes.objects.all()
    return render(request,get_classes.html,{cls_list:cls_list})

def add_classes(request):
    if request.method == "GET":
        return render(request,add_classes.html)
    elif request.method == "POST":
        title = request.POST.get(title)
        models.Classes.objects.create(titile=title)
        return redirect(/classes.html)

def del_classes(request):
    nid = request.GET.get(nid)
    models.Classes.objects.filter(id = nid).delete()
    return redirect(/classes.html)


def edit_classes(request):
    if request.method == GET:
        nid = request.GET.get(nid)
        obj = models.Classes.objects.filter(id=nid).first()
        return render(request,edit_classes.html,{obj:obj})
    elif request.method == POST:
        nid = request.GET.get(nid)
        title = request.POST.get(xxoo)
        models.Classes.objects.filter(id=nid).update(titile=title)
        return redirect(/classes.html)
views.classes.py

5)展示效果

 技术分享图片

技术分享图片

技术分享图片

三、用户登录验证

Django版本的不同,可能需要在settings.py 修改 MIDDLEWARE  为  MIDDLEWARE_CLASS

1)Django的cookie验证

准备html文件

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>

<form action="/login/" method="post">
    <p>姓名<input type="text" name="user"></p>
    <p>密码<input type="password" name="pwd"></p>
    <p><input type="submit"></p>
</form>

</body>
</html>
login.html
技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
<h1>{{ name }}</h1>
</body>
</html>
index.html

由于是post的请求

配置文件注释这一行  # ‘django.middleware.csrf.CsrfViewMiddleware‘,

准备url

技术分享图片
from django.conf.urls import url
from django.contrib import admin
from admin_orm import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^login/, views.login),
    url(r^index/, views.index),
]
urls.py

 视图函数cookie验证原理

技术分享图片
from django.shortcuts import render,redirect

# Create your views here.

def login(request):
    print("COOKIES",request.COOKIES)    # 查看cookie
    if request.method == "POST":
        name = request.POST.get("user")
        pwd = request.POST.get("pwd")
        print(name,pwd)
        if name == "user" and pwd =="123":
            ret = redirect("/index/")
            ret.set_cookie("blili",acfine)    # 第一次登陆发送给客户端cookie值
            # ret.set_cookie("username",name)
            return ret
    return render(request,login.html)


def index(request):
    if request.COOKIES.get("blili",None) == "acfine":       # 第二次登录,携带cookie值
    # if request.COOKIES.get("username", None) == "yuan":
        name = "yuan"
        return render(request, index.html,locals())
    else:
        return redirect("/login/")
views.py

 简单优化cookie验证,name = request.COOKIES.get("username",None)

技术分享图片
from django.shortcuts import render,redirect

# Create your views here.

def login(request):
    print("COOKIES",request.COOKIES)    # 查看cookie
    if request.method == "POST":
        name = request.POST.get("user")
        pwd = request.POST.get("pwd")
        print(name,pwd)
        if name == "user" and pwd =="123":
            ret = redirect("/index/")
            ret.set_cookie("username",{""})
            return ret
    return render(request,login.html)


def index(request):

    if request.COOKIES.get("username", None):
        name = request.COOKIES.get("username",None)
        return render(request, index.html,locals())
    else:
        return redirect("/login/")
views.py

2)Django的cookie与session配合实现验证

技术分享图片
from django.shortcuts import render,redirect

# Create your views here.
import datetime
expires = datetime.datetime.utcnow()+datetime.timedelta(days=3)
def login(request):
    print("COOKIES",request.COOKIES)    # 查看cookie
    print("SESSION",request.session)
    if request.method == "POST":
        name = request.POST.get("user")
        pwd = request.POST.get("pwd")
        print(name,pwd)
        if name == "user" and pwd =="123":
            # ret = redirect("/index/")
            # ret.set_cookie("username",{"11":"22"},
            #                max_age=10,  # max_age=10  有效时间10秒,找不到就找后面个
            #                expires = datetime.datetime.utcnow()+datetime.timedelta(days=3))     # 有效时间3天,
            # return ret

            # COOKIE SESSION,session默认在服务端保存15天
            request.session["is_login"] = True
            request.session["user"] = name
            return redirect("/index/")

    return render(request,login.html)


def index(request):
    # if request.COOKIES.get("username", None):
    #     name = request.COOKIES.get("username",None)
    #     return render(request, index.html,locals())

    if request.session.get("is_login",None):
        name = request.session.get(user,None)
        return render(request,"index.html",locals())
    else:
        return redirect("/login/")
views.py

 四、jquery的Ajax应用。不知觉的往后台发请求,而不刷新页面

技术分享图片

1)前端文件写入

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn{
            display: inline-block;
            padding: 5px 15px;
            background: darkgoldenrod;
            color: white;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div>
        <input placeholder="用户名" type="text" id="username">
        <input placeholder="密码" type="password" id="password">
        <div class="btn" onclick="submitForm();">提交</div>
    </div>
    <div>
        <input placeholder="数字" type="text" id="i1">
        <input placeholder="数字" type="text" id="i2">
        <div class="btn" onclick="addForm();">等于</div>
        <input placeholder="数字" type="text" id="i3">
    </div>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function submitForm() {
            var u = $(#username).val();
            var p = $(#password).val();
            console.log(u, p);
            $.ajax({
                url: /ajax2.html,
                type: GET,
                data:{username:u,password:p},
                success:function (arg) {
                    console.log(arg);
                }
            })
        }


        function addForm(){
            var v1 = $(#i1).val();
            var v2 = $(#i2).val();
            $.ajax({
                url:/ajax3.html,
                type:POST,
                data:{"v1":v1,"v2":v2},
                success:function(arg){
                    console.log(arg);
                    $(#i3).val(arg)
                    //window.location.reload(); //页面刷新
                }
            })
        }
    </script>
</body>
</html>
ajax1.html

2)路由写入

技术分享图片
urlpatterns = [
    url(r^admin/, admin.site.urls),


    url(r^ajax1.html$, ajax.ajax1),
    url(r^ajax2.html$, ajax.ajax2),
    url(r^ajax3.html$, ajax.ajax3),
]
urls.py

3)视图文件写入

技术分享图片
def ajax1(request):
    return render(request,ajax1.html)


def ajax2(request):
    user = request.GET.get(username)
    pwd = request.GET.get(password)
    import time
    time.sleep(5)
    return HttpResponse(DSB)

def ajax3(request):
    v1 = request.POST.get(v1)
    v2 = request.POST.get(v2)
    try:
        v3 = int(v1) + int(v2)
    except Exception as e:
        v3 = "输入格式有误"
    return HttpResponse(v3)
view_ajax.py

 五、分页功能

1)简单的模拟分页

 第一步:分页准备

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in user_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
</body>
</html>
index.html

  url(r‘^index.html$‘,views.index)

技术分享图片
USER_LIST = []
for i in range(1,999):
    temp = {‘name‘:‘root‘+str(i),‘age‘:i}
    USER_LIST.append(temp)

def index(request):
    return render(request,‘index.html‘,{‘user_list‘:USER_LIST})
views.py

技术分享图片

 第二步:调整url,简单的显示分页功能

技术分享图片
USER_LIST = []
for i in range(1,999):
    temp = {name:root+str(i),age:i}
    USER_LIST.append(temp)

def index(request):
    per_page_count = 10
    current_page = request.GET.get(p)
    current_page= int(current_page)
    start = (current_page-1) * per_page_count
    end = current_page * per_page_count
    data = USER_LIST[start:end]
    return render(request,index.html,{user_list:data})
views.py

技术分享图片

 手动修改url的p值来修改分页显然不现实

2)分页功能实现上一页,下一页展示

技术分享图片

修改html文件

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in user_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
    <a href="/index.html?p={{ prev_pager }}">上一页</a>
    <a href="/index.html?p={{ next_pager }}">下一页</a>
</body>
</html>
index.html

修改视图函数

技术分享图片
USER_LIST = []
for i in range(1,999):
    temp = {name:root+str(i),age:i}
    USER_LIST.append(temp)

def index(request):
    per_page_count = 10
    current_page = request.GET.get(p)
    current_page= int(current_page)

    start = (current_page-1) * per_page_count
    end = current_page * per_page_count
    data = USER_LIST[start:end]

    prev_pager = current_page -1
    next_pager = current_page +1
    return render(request,index.html,{
        user_list:data,
        prev_pager:prev_pager,
        next_pager:next_pager
    })
views.py

3)Django的内置分页设计

 3.1)增加视图函数

技术分享图片
def index1(request):
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    # 全部数据:USER_LIST, ==>得出共有多少条数据
    # per_page: 每页显示条目数量
    # count: 数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如:(110),(1,200)
    # page: page对象(是否具有下一页,是否有上一页)
    current_page = request.GET.get(p)
    paginator = Paginator(USER_LIST,10)
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts=paginator.page(paginator.num_pages)
    return render(request, index1.html,{posts:posts})
views.index1

    3.2)添加相应的html文件

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
    {% if posts.has_previous %}
        <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a>
        {% else %}
        <a href="#">上一页</a>
    {% endif %}
    {% if posts.has_next %}
        <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>
    {% endif %}
    <span>
        {{ posts.number }} / {{ posts.paginator.num_pages }}
    </span>
</body>
</html>
index1.html

技术分享图片

    3.3)分页功能提取出来,减少代码冗余

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
    {% include ‘include/pager.html‘ %}

</body>
</html>
index1.html

  添加 include/pager.html 页面

技术分享图片

技术分享图片
{% if posts.has_previous %}
    <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a>
    {% else %}
    <a href="#">上一页</a>
{% endif %}
{% if posts.has_next %}
    <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>
{% endif %}
<span>
    {{ posts.number }} / {{ posts.paginator.num_pages }}
</span>
pager.html

 3.4)自定义类,实现自定义分页功能

修改视图

技术分享图片
USER_LIST = []
for i in range(1,689):
    temp = {name:root+str(i),age:i}
    USER_LIST.append(temp)

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
class CustomPaginator(Paginator):
    def __init__(self,current_page,per_pager_num,*args,**kwargs):
        self.current_page = int(current_page)   # 当前页
        self.per_pager_num = int(per_pager_num) # 最多显示的页面数量
        super(CustomPaginator,self).__init__(*args,**kwargs)

    def pager_num_range(self):
        if self.num_pages < self.per_pager_num:
            return range(1,self.num_pages+1)

        # 总页数特别多 5
        part = int(self.per_pager_num/2)
        if self.current_page <=part:
            return range(1,self.per_pager_num+1)

        if (self.current_page +part) > self.num_pages:
            return range(self.num_pages-self.per_pager_num+1,self.num_pages+1)

        return range(self.current_page - part, self.current_page + part + 1)

def index1(request):
    # 全部数据:USER_LIST, ==>得出共有多少条数据
    # per_page: 每页显示条目数量
    # count: 数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如:(110),(1,200)
    # page: page对象(是否具有下一页,是否有上一页)
    current_page = request.GET.get(p)
    paginator = CustomPaginator(current_page,11,USER_LIST,10)
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts=paginator.page(paginator.num_pages)
    return render(request, index1.html,{posts:posts})
views.py

修改分页前端代码

技术分享图片
{% if posts.has_previous %}
    <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a>
    {% else %}
    <a href="#">上一页</a>
{% endif %}

{% for i in posts.paginator.pager_num_range %}
    {% if i == posts.number %}
        <a style="font-size: 30px;" href="/index1.html?p={{ i }}">{{ i }}</a>
    {% else %}
        <a href="/index1.html?p={{ i }}">{{ i }}</a>
    {% endif %}
{% endfor %}

{% if posts.has_next %}
    <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>
{% endif %}
<span>
    {{ posts.number }} / {{ posts.paginator.num_pages }}
</span>
pager.html

 3.5)模块化定制分页

    定制模块,在app01下写入pager.py

技术分享图片
#!/usr/bin/env python
#-*-coding: utf8-*-


class Pagination(object):
    def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7):
        # 数据总个数
        self.total_count = totalCount
        # 当前页
        try:
            v = int(currentPage)
            if v <= 0:
               v = 1
            self.current_page = v
        except Exception as e:
            self.current_page = 1
        # 每页显示的行数
        self.per_page_item_num = perPageItemNum
        # 最多显示页面
        self.max_page_num = maxPageNum

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

    def end(self):
        return self.current_page * self.per_page_item_num
    @property
    def num_pages(self):
        """
        总页数
        :return:
        """
        # 666
        # 10
        a,b = divmod(self.total_count,self.per_page_item_num)
        if b == 0:
            return a
        return a+1

    def pager_num_range(self):
        # self.num_pages()
        # self.num_pages
        # 当前页
        #self.current_page
        # 最多显示的页码数量 11
        #self.per_pager_num
        # 总页数
        # self.num_pages
        if self.num_pages < self.max_page_num:
            return range(1,self.num_pages+1)
        # 总页数特别多 5
        part = int(self.max_page_num/2)
        if self.current_page <= part:
            return range(1,self.max_page_num+1)
        if (self.current_page + part) > self.num_pages:
            return range(self.num_pages-self.max_page_num+1,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1)

    def page_str(self):
        page_list = []

        first = "<li><a href=‘/index2.html?p=1‘>首页</a></li>"
        page_list.append(first)

        if self.current_page == 1:
            prev = "<li><a href=‘#‘>上一页</a></li>"
        else:
            prev = "<li><a href=‘/index2.html?p=%s‘>上一页</a></li>" %(self.current_page-1,)
        page_list.append(prev)
        for i in self.pager_num_range():
            if i == self.current_page:
                temp = "<li class=‘active‘><a href=‘/index2.html?p=%s‘>%s</a></li>" %(i,i)
            else:
                temp = "<li><a href=‘/index2.html?p=%s‘>%s</a></li>" % (i, i)
            page_list.append(temp)

        if self.current_page == self.num_pages:
            nex = "<li><a href=‘#‘>下一页</a></li>"
        else:
            nex = "<li><a href=‘/index2.html?p=%s‘>下一页</a></li>" % (self.current_page + 1,)
        page_list.append(nex)

        last = "<li><a href=‘/index2.html?p=%s‘>尾页</a></li>" %(self.num_pages,)
        page_list.append(last)

        return ‘‘.join(page_list)
app01_pager.py

写url路由:url(r‘^index2.html$‘, views.index2),

技术分享图片
# 模拟页面内容
USER_LIST = []
for i in range(1,689):
    temp = {name:root+str(i),age:i}
    USER_LIST.append(temp)


def index2(request):
    from app01.pager import Pagination
    current_page = request.GET.get(p)
    page_obj = Pagination(666,current_page)

    data_list = USER_LIST[page_obj.start():page_obj.end()]
    return render(request,index2.html,{data:data_list,page_obj:page_obj})
views.index2

写入前端

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"/>
</head>
<body>
    <ul>
        {% for row in data %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}
    </ul>
    {% for i in page_obj.pager_num_range %}
        <a href="/index2.html?p={{ i }}">{{ i }}</a>
    {% endfor %}
    <hr/>
index2.html

需要导入js的一个插件

技术分享图片

  展示效果

技术分享图片

 

以上是关于Django之admin管理数据库,cookie验证及分页设置的主要内容,如果未能解决你的问题,请参考以下文章

django之admin后台管理

django 之admin后台管理

django基础知识之后台管理Admin站点:

Django框架之admin管理后台

BBS(第二天) Django之Admin 自动化管理数据页面 与创建一个用户注册的验证码

Django Admin登录403 Forbidden(未设置CSRF cookie。)