django学习-武沛齐教程【day4】

管理员操作

管理员账户

models.py

class Admin(models.Model):
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)

urls.py

urlpatterns = [
    #管理员账户
    path('admin/list/', admin.admin_list),

]

templates/layout.html

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li><a href="/admin/list/">管理员账户</a></li>
                    <li><a href="/depart/list/">部门管理</a></li>
                    <li><a href="/user/list/">用户管理</a></li>
                    <li><a href="/pretty/list/">靓号管理</a></li>

                </ul>

views/admin.py

from django.shortcuts import render
from app01 import models
def admin_list(request):
    queryset = models.Admin.objects.all()
    context={
        "queryset":queryset
    }
    return render(request,"admin_list.html",context)


templates/admin_list.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
  <div style="margin-bottom: 10px;">
    <a class="btn btn-success" href="/admin/add/">
      <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
      新建管理员
    </a>
    <div style="float:right; width:300px;">
      <form method="get">
        <div class="input-group">
          <input type="text" name="q" class="form-control" placeholder="Search for..." value="{
   
   {search_data}}">
          <span class="input-group-btn">
            <button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search"
                aria-hidden="true"></span></button>
          </span>
        </div><!-- /input-group -->
      </form>
    </div>
  </div>

  <div class="bs-example" data-example-id="table-within-panel">
    <div class="panel panel-default">
      <!-- Default panel contents -->
      <div class="panel-heading">
        <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
        管理员列表
      </div>
      <!-- Table -->
      <table class="table table-bordered">
        <thead>
          <tr>
            <th>ID</th>
            <th>用户名</th>
            <th>密码</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          {% for obj in queryset %}
          <tr>
            <th>{
   
   {obj.id}}</th>
            <td>{
   
   {obj.username}}</td>
            <td>{
   
   {obj.password}}</td>
            
            <td>
              <a class="btn btn-primary btn-xs" href="/admin/{
   
   {obj.id}}/edit/">编辑 </a>
              <a class="btn btn-danger btn-xs" href="/admin/{
   
   {obj.id}}/delete/">删除 </a>
            </td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    <div class="clearfix">
      <ul class="pagination">
        {
   
   {page_string}}
      </ul>
    </div>
  </div>
</div>

{% endblock %}

新建管理员

urls.py

urlpatterns = [
    #管理员账户
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
]

views/admin.py


def admin_add(request):
    # 添加管理员
    title="新建管理员"
    if request.method == "GET":
        form = AdminModelForm()
        return render(request, 'change.html', {"form": form,"title":title})
    # 用户POST提交数据,密码校验
    form = AdminModelForm(data=request.POST)
    if form.is_valid():
        # print(form.cleaned_data)
        form.save()
        return redirect("/admin/list/")
    else:
        return render(request, 'change.html', {"form": form,"title":title})

utils/form.py

class AdminModelForm(BootstrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True)
    )

    class Meta:
        model = models.Admin
        fields = ["username", "password","confirm_password"]
        widgets={
            "password":forms.PasswordInput(render_value=True)
        }
    def clean_password(self):
        pwd= self.cleaned_data.get("password")
        return md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if pwd!=confirm:
            raise ValidationError("两次密码不一致")
        # 返回什么此字段保存到数据库就是什么
        return confirm

utils/encrypt.py

import hashlib
from django.conf import settings
def md5(data_string):
    obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
    obj.update(data_string.encode('utf-8'))
    return obj.hexdigest()

templates/change.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">{
   
   {title}}</h3>
        </div>
        <div class="panel-body">
            <form method="post" novalidate>
                {% csrf_token %}
                {% for field in form %}
                <div class="form-group">
                    <label>{
   
   {field.label}}</label>
                    {
   
   {field}}
                    <span style="color:red;">{
   
   {field.errors.0}}</span>
                </div>
                {% endfor %}
                <button type="submit" class="btn btn-primary">提交</button>
            </form>
        </div>
    </div>
</div>

{% endblock %}

编辑管理员

views/admin.py

def admin_edit(request, nid):
    # 编辑管理员
    title="编辑管理员"
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return redirect('/admin/list/')
    if request.method == "GET":
        # instance=row_object显示默认值
        form = AdminModelForm(instance=row_object)
        return render(request, 'change.html', {"form": form,"title":title})

    form = AdminModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/admin/list/')
    return render(request, 'change.html', {"form": form,"title":title})

urls.py

urlpatterns = [
    #管理员账户
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
]

删除管理员

urls.py

urlpatterns = [
    #管理员账户
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
]

views/admin.py

def admin_delete(request, nid):
    # 删除部门
    models.Admin.objects.filter(id=nid).delete()
    return redirect('/admin/list/')

Cookie和Session

cookie:【浏览器】保存在浏览器上的键值对,发送请求时自动携带

session:【网站】存储凭证(数据库、redis、文件),如果请求的凭证存在,返回信息

用户认证

基本实现

urls.py

urlpatterns = [
    #用户认证
    path('login/', account.login),

]

templates/login.html

{% load static %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.css' %}">
    <style>
        .account {
            width: 400px;
            border: 1px solid #ddd;
            border-radius: 5px;
            box-shadow: 5px 5px 20px #aaa;

            margin-left: auto;
            margin-right: auto;
            margin-top: 100px;
            padding: 20px 40px;
        }

        .account h2 {
            margin-top: 10px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="account">
        <h2>用户登录</h2>
        <form method="post" novalidate>
            {% csrf_token %}
            <div class="form-group">
                <label>用户名</label>
                {
   
   {form.username}}
                <span style="color:red;">{
   
   {form.username.errors.0}}</span>
            </div>
            <div class="form-group">
                <label>密码</label>
                {
   
   {form.password}}
                <span style="color:red;">{
   
   {form.password.errors.0}}</span>

            </div>
            <input type="submit" class="btn btn-default" value="登 录">
        </form>
    </div>
</body>

</html>

views/account.py

from django.shortcuts import render, redirect
from django import forms
from app01 import models

from app01.utils.bootstrap import BootstrapForm
from app01.utils.encrypt import md5

class LoginForm(BootstrapForm):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput
    )
    def clean_password(self):
        pwd=self.cleaned_data.get("password")
        return md5(pwd)

def login(request):
    if request.method=="GET":
        form = LoginForm()
        return render(request, "login.html", {"form": form})
    form=LoginForm(data=request.POST)
    if form.is_valid():
        admin_object=models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password","用户名或密码错误")
            return render(request,'login.html',{'form':form})
        # 用户验证通过,将他写到cookie中,再写到session中
        request.session["info"]={"id":admin_object.username,"username":admin_object.username}
        return redirect("/admin/list/")

    return render(request,'login.html',{'form':form})

中间件处理

登录成功后,在cookie中写随机字符串,在session中存用户信息

在其他需要登录才能访问的页面中,都需要加入:

  # 检查用户是否已登陆,未登录返回登陆页面
  # 用户发来请求,获取cookie随机字符串,拿着随机字符串看session中有无

info = request.session.get("info")
if not info:
    return redirect("/login/")

目标:在视图函数前统一加入判断

中间件是个类,其中定义了方法process_request和process_response,浏览器请求经过中间件的process_request,然后执行视图函数,将视图函数的结果经过process_response再返还给浏览器

utils/auth.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect

class AuthMiddleware(MiddlewareMixin):
    def process_request(self,request):
        # 0、排除不需要登录就能访问的页面
        if request.path_info=="/login/":
            return 

        # 1\读取当前访问用户的session信息,如果能读到,说明登录过,可以继续向后走
        info_dict = request.session.get("info")
        if info_dict:
            return 
        # 2\没有登录过,跳到登录页面
        return redirect("/login/")
    def process_response(self,request,response):
        return response

settings.py

MIDDLEWARE = [
    'app01.middleware.auth.AuthMiddleware',
]

注销

就是将cookie和session中去除

urls.py

#用户认证
path('login/', account.login),
path('logout/', account.logout),


views/account.py

def logout(request):
    request.session.clear()
    return redirect('/login/')

Ajax请求

浏览器向网站发送请求时:URL和表单的提交形式

  • GET
  • POST

也可以通过ajax向后台发请求

1、依赖jquery,编写ajax代码

$.ajax({
  url:"发送地址",
  type:"post",
  data:{
    n1:123,
    n2:456
  },
  success:function(res){
    console.log(res);
  }
})

任务管理

GET请求

urls.py

urlpatterns = [
    #任务管理
    path('task/list/',task.task_list),
]

views/task.py

from django.shortcuts import render, redirect

def task_list(request):
    return render(request,"task_list.html")

tempaltes/task_list.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
    <h1>任务管理</h1>
    <h3>示例1</h3>
    <input type="button" class="btn btn-primary" value="点击" οnclick="clickMe();" />
</div>
{% endblock %}
{% block js %}
    <script type="text/javascript">
        function clickMe(){
            $.ajax({
                url: '/task/ajax/',
                type:"get",
                data:{
                    n1:123,
                    n2:456
                },
                success: function(res){
                    console.log(res);
                }
            });
        }
    </script>
{% endblock %}

POST请求

需要免除csrf验证

views/task.py

from django.shortcuts import render, redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def task_ajax(request):
    print(request.GET)
    print(request.POST)

    return HttpResponse("chengong")

templates/task_list.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
    <h1>任务管理</h1>
    <h3>示例1</h3>
    <input type="button" class="btn btn-primary" value="点击" id="btn1" />

    
</div>

{% endblock %}

{% block js %}
    <script type="text/javascript">
        // 页面框架加载完成之后代码自动执行
        $(function(){
            bindBtn1Event();

        })
        // 页面加载完成后,给btn绑定一个
        function bindBtn1Event(){
            $("#btn1").click(function(){
                $.ajax({
                    url: '/task/ajax/',
                    type:"post",
                    data:{
                        n1:123,
                        n2:456
                    },
                    success: function(res){
                        console.log(res);
                    }
                });
            })
        }
    </script>
{% endblock %}

ajax请求的返回值

一般会返回json格式

/task_list.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
    <h1>任务管理</h1>
    <h3>示例1</h3>
    <input type="button" class="btn btn-primary" value="点击" id="btn1"/>
    <h3>示例2</h3>
    <input type="text" id="txtUser" placeholder="姓名"/>
    <input type="text" id="txtAge" placeholder="年龄"/>
    <input type="button" class="btn btn-primary" value="点击" id="btn2"/>
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
        // 页面框架加载完成之后代码自动执行
        $(function(){
            bindBtn1Event();
            bindBtn2Event();
        })
        // 页面加载完成后,给btn绑定一个
        function bindBtn1Event(){
            $("#btn1").click(function(){
                $.ajax({
                    url: '/task/ajax/',
                    type:"post",
                    data:{
                        n1:123,
                        n2:456
                    },
                    dataType:"JSON",
                    success: function(res){
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                });
            })
        }
        function bindBtn2Event(){
            $("#btn2").click(function(){
                $.ajax({
                    url: '/task/ajax/',
                    type:"post",
                    data:{
                        n1:$("#txtUser").val(),
                        n2:$("#txtAge").val()
                    },
                    dataType:"JSON",
                    success: function(res){
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                });
            })
        }
</script>
{% endblock %}

views/task.py

from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt



@csrf_exempt
def task_ajax(request):
    print(request.GET)
    print(request.POST)
    data_dict = {"status": True, "data": [11, 22, 33, 44]}
    return JsonResponse(data_dict)

创建任务

models.py

class Task(models.Model):
    level_choices = (
        (1, "1级"),
        (2, "2级"),
        (3, "3级"),
    )
    level = models.IntegerField(verbose_name="级别", choices=level_choices, default=1)
    title = models.CharField(verbose_name="标题", max_length=64)
    detail = models.TextField(verbose_name="详细信息")
    user= models.ForeignKey(verbose_name="负责人",to="Admin",on_delete=models.CASCADE)
    

utils/task.py

@csrf_exempt
def task_add(request):
    # print(request.POST)
    # 1、用户发送过来的数据进行校验,(ModelForm进行校验)
    form = TaskModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        data_dict = {"status": True}
        return HttpResponse(json.dumps(data_dict))

    data_dict = {"status":False,'errors':form.errors}
    return HttpResponse(json.dumps(data_dict,ensure_ascii=False))

templates/task_list.html

{% extends 'layout.html' %}
{% block content %}

<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">新建表单</div>
        <div class="panel-body">
            <div class="clearfix">
                <form id="formAdd" novalidate>
                    {% for field in form %}
                    <div class="col-xs-6">
                        <div class="form-group" style="position: relative;margin-bottom: 20px;">
                            <label>{
   
   {field.label}}</label>
                            {
   
   {field}}
                            <span class="error-msg" style="color:red; position: absolute;"></span>
                        </div>
                    </div>
                    {% endfor %}
                    <div class="col-xs-12">
                        <button type="button" id="btnAdd" class="btn btn-primary">提交</button>
                    </div>
                </form>
            </div>
        </div>
    </div>


    <h1>Ajax学习</h1>
    <h3>示例1</h3>
    <input type="button" class="btn btn-primary" value="点击" id="btn1"/>
    <h3>示例2</h3>
    <input type="text" id="txtUser" placeholder="姓名"/>
    <input type="text" id="txtAge" placeholder="年龄"/>
    <input type="button" class="btn btn-primary" value="点击" id="btn2"/>
    <h3>示例3</h3>
    <form id="form3">
        <input type="text" name="txtUser" placeholder="姓名"/>
        <input type="text" name="txtAge" placeholder="年龄"/>
        <input type="text" name="txtEmail" placeholder="邮箱"/>
        <input type="text" name="txtMore" placeholder="更多"/>

        <input type="button" class="btn btn-primary" value="点击" id="btn3"/>
    </form>
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
    // 页面框架加载完成之后代码自动执行
    $(function(){
        bindBtn1Event();
        bindBtn2Event();
        bindBtn3Event();
        bindBtnAddEvent();
    })
    // 页面加载完成后,给btn绑定一个
    function bindBtn1Event(){
        $("#btn1").click(function(){
            $.ajax({
                url: '/task/ajax/',
                type:"post",
                data:{
                    n1:123,
                    n2:456
                },
                dataType:"JSON",
                success: function(res){
                    console.log(res);
                    console.log(res.status);
                    console.log(res.data);
                }
            });
        })
    }
    function bindBtn2Event(){
        $("#btn2").click(function(){
            $.ajax({
                url: '/task/ajax/',
                type:"post",
                data:{
                    n1:$("#txtUser").val(),
                    n2:$("#txtAge").val()
                },
                dataType:"JSON",
                success: function(res){
                    console.log(res);
                    console.log(res.status);
                    console.log(res.data);
                }
            });
        })
    }
    function bindBtn3Event(){
        $("#btn3").click(function(){
            $.ajax({
                url: '/task/ajax/',
                type:"post",
                data:$("#form3").serialize(),
                dataType:"JSON",
                success: function(res){
                    console.log(res);
                    console.log(res.status);
                    console.log(res.data);
                }
            });
        })
    }
    function bindBtnAddEvent(){
        $("#btnAdd").click(function(){
            $(".error-msg").empty();
            $.ajax({
                url: '/task/add/',
                type:"post",
                data:$("#formAdd").serialize(),
                dataType:"JSON",
                success: function(res){
                    if(res.status){
                        alert("添加成功")
                    }
                    else{
                        $.each(res.errors,function(name,data){
                            // console.log(name,data)
                            $("#id_"+name).next().text(data[0]);
                        })
                    }
                }
            });
        })
    }

</script>
{% endblock %}

猜你喜欢

转载自blog.csdn.net/weixin_65656674/article/details/126681139
今日推荐