会议室预定作业代码梳理详解编程语言

先梳理一下我们的会议室预定是怎么做的

1、使用django自带的auth模块做用户认证

2、使用form表单生成登录的form表单

3、使用bookstrap做登录的css的渲染

4、设计会议室预定的model,用户表,我们不自己设计,使用django的user表,在设计一个会议室的表,最后在设计一个预定的表

5、会议室预定的前端的页面我们用table标签,通过bootstrap进行css渲染

6、通过ajax将预定的信息发送给后端,后端写入数据库后,前端重新加载页面,实现预定的效果

—————————————————————————————————–

一、登录相关的知识点梳理

1、首先先看下如何利用django自带的user表,和如何通过继承的方式扩展user表,因为user表中的字段是固定的,我们如果想扩展的话,就可以通过继承的方式,或者建立一张一对一的表两种方式来实现扩展user表

a、通过继承的方式扩展user表的字段

from django.contrib.auth.models import AbstractUser 
 
 
class Userinfo(AbstractUser): 
    iphone = models.CharField(max_length=11, null=True, blank=True) 
    email = models.CharField(max_length=64, null=True, blank=True) 
    create_time = models.DateTimeField(auto_now_add=True, blank=True) 
 
    def __str__(self): 
        return self.username 

b、在settings中指明,django自带的auth模块要去我们新的userinfo表中去认证

AUTH_USER_MODEL = "app1.Userinfo" 

c、还需要用到一个装饰器,就是校验用户是否登录的方法

这就是一个装饰器,可以用在任何需要登录的试图函数上

from django.contrib.auth.decorators import login_required 
@login_required 
def index(request): 

这里还 要定义,如果用户没有登录,我要跳转到什么页面,这个也要在settings中设置,下面的意思就是如果没有登录,则跳转到登录页面

LOGIN_URL = "/app1/login/" 

d、这里还有一个点要掌握,就是注销,auth模块自带的logout方法会删除session和cookies

def logout(request): 
    auth.logout(request) 
    return redirect("/app1/login/") 

2、然后我们通过forms生成登录页面的form表单

a、首先导入用到的模块

from django import forms 
from django.core.validators import RegexValidator 
from django.forms import widgets 
from django.contrib import auth 
from django.contrib.auth.decorators import login_required 

b、然后写forms的代码

class Loginclass(forms.Form): 
    user_name = forms.CharField( 
        label="用户名", 
        label_suffix=":", 
        max_length=12, 
        min_length=5, 
        validators = [ 
            RegexValidator(r'^/D{2}/d+/D+',code="checkfirst"), 
        ], 
 
        widget=widgets.Input(attrs={"placeholder":"请输入用户名","class":"form-control"}), 
        error_messages= { 
            "required":"用户名不能为空", 
            "max_length":"用户名的最大长度为12", 
            "min_length":"用户名的最小长度为5", 
            "checkfirst":"用户名必须以2个非数字开头,中间为数字,以非数字结尾" 
        } 
    ) 
    user_pwd = forms.CharField( 
        label="密码", 
        label_suffix=":", 
        max_length=12, 
        min_length=5, 
        widget=widgets.PasswordInput(attrs={"placeholder": "请输入密码","class":"form-control"},render_value=True), 
        # validators = [ 
        #     RegexValidator(r'^/d+',code="checkfirst",message="密码必须全部为数字"), 
        # ], 
        error_messages= { 
            "required":"密码不能为空", 
            "max_length":"密码的最大长度为12", 
            "min_length":"密码的最小长度为5" 
        } 
    ) 

c、然后就是登录的视图函数,这里我们会做两层的校验,首先forms表单会做一层校验,保证数据是符合条件的,第二层校验就是auth模块会去userinfo表中去校验用户名和密码是否正确

def login(request): 
    method = request.method.lower() 
    if method == "get": 
        obj = Loginclass() 
        return render(request,"book_login.html",{"obj":obj}) 
 
    else: 
        obj = Loginclass(request.POST) 
        if obj.is_valid(): 
            user = auth.authenticate(username=obj.cleaned_data["user_name"],password=obj.cleaned_data["user_pwd"]) 
            if user: 
                auth.login(request,user) 
                return redirect("/app1/index/") 
            else: 
 
                return redirect("/app1/login/") 
        else: 
            return render(request,"book_login.html",{"obj":obj}) 

这里有一段代码非常重要,下面这段代码就会在request添加一个属性就是request.user,这个的值就是当前登录的用户的对象

auth.login(request,user) 

3、然后在看下登录页面的html的代码

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Title</title> 
    <link rel="stylesheet" href="/static/css/bootstrap.min.css"> 
 
</head> 
<body> 
<h3>登陆页面</h3> 
<form method="post" action="/app1/login/" novalidate> 
    {% csrf_token %} 
    <div class="form-group {% if obj.user_name.errors.0 %} has-error {% endif %}"> 
        <p>{{ obj.user_name.label }}{{ obj.user_name }}</p> 
        <span class="help-block">{{ obj.user_name.errors.0 }}</span> 
    </div> 
    <div class="form-group {% if obj.user_pwd.errors.0 %} has-error {% endif %}"> 
        <p>{{ obj.user_pwd.label }}{{ obj.user_pwd }}</p> 
        <span class="help-block">{{ obj.user_pwd.errors.0 }}</span> 
    </div> 
    <div class="form-group"> 
        <p><input type="submit" value="登陆" class="btn btn-success"></p> 
    </div> 
</form> 
 
 
<script src="/static/jq/jquery-3.3.1.js"></script> 
<script src="/static/jq/bootstrap.min.js"></script> 
<script> 
 
 
</script> 
</body> 
</html> 

这里复习一下这个点,就是报错的的效果,如果某个字段有错误信息,则会有一个圈红的效果

    <div class="form-group {% if obj.user_name.errors.0 %} has-error {% endif %}"> 
        <p>{{ obj.user_name.label }}{{ obj.user_name }}</p> 
        <span class="help-block">{{ obj.user_name.errors.0 }}</span> 
    </div> 

—————————————————————————————————–

二、这里我们主要看下表结构的设计

a、会议室表

class room(models.Model): 
    rid = models.AutoField(primary_key=True) 
    title = models.CharField(max_length=64,verbose_name="会议室名称") 
    num = models.SmallIntegerField() 
 
    def __str__(self): 
        return self.title 
 
    class Meta: 
        verbose_name = "会议室表" 
        verbose_name_plural = verbose_name 

b、预定表

class book(models.Model): 
    bid = models.AutoField(primary_key=True) 
    user_obj = models.ForeignKey(to=Userinfo,on_delete=models.CASCADE) 
    room_obj = models.ForeignKey(to=room,on_delete=models.CASCADE) 
    choices = ( 
        ("1","01:00"), 
        ("2","02:00"), 
        ("3","03:00"), 
        ("4","04:00"), 
        ("5","05:00"), 
        ("6","06:00"), 
        ("7","07:00"), 
        ("8","08:00"), 
    ) 
    time_id = models.CharField(choices=choices,max_length=64) 
    book_time = models.DateTimeField(auto_now_add=True) 
 
    # def __str__(self): 
    #     return self.user_obj + "预定了" + self.room_obj 
 
    class Meta: 
        unique_together = ["user_obj","room_obj","time_id"] 
        verbose_name = "预定表" 
        verbose_name_plural = verbose_name 

c、因为我们要通过admin去增加数据,所有我们需要在admin中注册我们的表结构,这一步不是必须的

from django.contrib import admin 
 
# Register your models here. 
 
 
from app1 import models 
class rootclass(admin.ModelAdmin): 
    list_display = ["rid","title","num"] 
 
class bookclass(admin.ModelAdmin): 
    list_display = ["bid","user_obj","room_obj","time_id","book_time"] 
 
admin.site.register(models.room,rootclass) 
admin.site.register(models.book,bookclass) 

—————————————————————————————————–

三、在看下预定会议室的功能的实现

a、首先看下视图函数的get方式是如何处理的

@login_required 
def index(request): 
    import datetime 
    current_time = datetime.datetime.now().date() 
    # request.GET["book_time"] = "2018-12-02" 
    check_time = request.GET.get("book_time",current_time) 
    print(check_time) 
    time_choice = models.book.choices 
    room_list = models.room.objects.all() 
    current_book_list = [] 
    book_list = models.book.objects.all() 
    for i in book_list: 
        if str(i.book_time.strftime("%Y-%m-%d")) == "2018-12-04": 
            temp = (i.user_obj,i.room_obj.rid,i.time_id) 
            current_book_list.append(temp) 
    htmls = "" 
    print(current_book_list) 
    for room in room_list: 
        temp_r = """<tr><td>{meetname}:(容量:{num}人)</td>""".format(meetname = room.title,num = room.num) 
        for t in time_choice: 
            if current_book_list: 
                for book_room in current_book_list: 
                    # print(str(book_room[1]),str(room.rid),str(book_room[2]),str(t[0]),sep="==================") 
                    if str(book_room[1]) == str(room.rid) and str(book_room[2]) == str(t[0]): 
                        current_login_user = request.user.username 
                        print(current_login_user,book_room[0],sep="-------------") 
                        if str(current_login_user) == str(book_room[0]): 
                            temp_t = "<td room_id={rid} time_id={tid} class='checked item'>{name}</td>".format(rid=room.rid,tid=t[0],name=book_room[0]) 
                        else: 
                            temp_t = "<td room_id={rid} time_id={tid} class='active_now item'>{name}</td>".format(rid=room.rid, 
                                                                                                          tid=t[0], 
                                                                                                          name=book_room[0]) 
 
                        break 
                    else: 
                        temp_t = "<td room_id={rid} time_id={tid} class='item'></td>".format(rid=room.rid, tid=t[0]) 
                    # temp_r = temp_r + temp_t 
            else: 
                temp_t = "<td room_id={rid} time_id={tid} class='item'></td>".format(rid=room.rid, tid=t[0]) 
            temp_r = temp_r + temp_t 
        temp_r = temp_r + "</tr>" 
        htmls = htmls + temp_r 
    # print(htmls) 
    return render(request,"index.html",locals()) 

这里主要是针对不同的数据返回不同的html代码,主要是css样式的不同的

首先从数据库中拿到所有的预定的信息,然后对不同的数据渲染不同的css样式

不同的数据有,“未被选中的会议室”,“当前用户选中的会议室”,“非当前用户选中的会议室”

b、前端的代码的

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Title</title> 
    <link rel="stylesheet" href="/static/css/bootstrap.min.css"> 
    <link rel="stylesheet" href="/static/datetimepicker/bootstrap-datetimepicker.min.css"> 
    <style> 
        .checked{ 
            background-color: yellow; 
        } 
        .active_now{ 
            background-color: red; 
        } 
        td{ 
            text-align: center; 
        } 
        th{ 
            text-align: center; 
        } 
 
        .td_active{ 
            background-color: #2e6da4; 
        } 
    </style> 
</head> 
<body> 
<h3>会议室预定</h3> 
 
<div class="calender pull-right"> 
      <div class='input-group' style="width: 230px;"> 
            <input type='text' class="form-control" id='datetimepicker11' placeholder="请选择日期"/> 
            <span class="input-group-addon"> 
                <span class="glyphicon glyphicon-calendar"> 
                </span> 
            </span> 
 
      </div> 
</div> 
<table class="table table-bordered table-striped"> 
    <thead> 
        <tr> 
            <th>会议室/时间</th> 
            {% for times in time_choice %} 
                <th>{{ times.1 }}</th> 
            {% endfor %} 
 
        </tr> 
    </thead> 
    <tbody> 
        {{ htmls |safe }} 
 
    </tbody> 
</table> 
<input type="button" class="btn btn-success pull-right keep" value="提交"> 
<a href="/app1/logout"><input type="button" class="btn btn-info pull-left keep" value="注销"></a> 
<script src="/static/jq/jquery-3.3.1.js"></script> 
<script src="/static/jq/bootstrap.min.js"></script> 
<script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script> 
<script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script> 
 
 
<script> 
        var POST_DATA = { 
            'ADD':{}, 
            "DEL":{} 
        } 
        function bindtd() { 
        $(".item").bind("click",function () { 
            var room_id = $(this).attr("room_id"); 
            var time_id = $(this).attr("time_id"); 
            if ($(this).hasClass("checked")){ 
                $(this).removeClass("checked"); 
                $(this).empty(); 
                if (POST_DATA.DEL[room_id]){ 
                    POST_DATA.DEL[room_id].push(time_id) 
                } 
                else { 
                   POST_DATA.DEL[room_id] = [time_id,] 
                } 
            } 
 
            else if ($(this).hasClass('td_active')){ 
                $(this).removeClass("td_active"); 
                var del_index = POST_DATA.ADD[room_id].indexOf(time_id); 
                POST_DATA.ADD[room_id].splice(del_index,1) 
            } 
            else if ($(this).hasClass("active_now")){ 
{#                pass#} 
            } 
            else { 
                $(this).addClass("td_active"); 
                if (POST_DATA.ADD[room_id]){ 
                    POST_DATA.ADD[room_id].push(time_id); 
{#                    alert(time_id)#} 
                } 
                else { 
                   POST_DATA.ADD[room_id] = [time_id,] 
                } 
 
            } 
 
 
        }) 
        } 
        bindtd(); 
 
    {#        提交ajax数据#} 
 
    $(".keep").bind("click",function () { 
        $.ajax( 
            { 
                url:"/app1/book/", 
                type:"POST", 
                data:JSON.stringify(POST_DATA), 
                contentType:"application/json", 
{#              编码格式1:  application/json 这个是编码格式,告诉后端,我这次发的是json格式的数据,数据在请求体里的格式为'{"a":1,"b":2}',在视图函数中进行反序列化处理#} 
{#              编码格式2:这个是默认的格式, 一般我们传递一个字典的格式过去,其实是用urldecode格式的数据发送给后端,在请求体里传递的数据类型为a=1&b=2&c=3#} 
 
                success:function (data) { 
                    document.location.reload() 
                } 
 
 
            } 
        ) 
    }) 
 
 
 
</script> 
</body> 
</html> 

这里需要注意的是这里

        function bindtd() { 
        $(".item").bind("click",function () { 
            var room_id = $(this).attr("room_id"); 
            var time_id = $(this).attr("time_id"); 
            if ($(this).hasClass("checked")){ 
                $(this).removeClass("checked"); 
                $(this).empty(); 
                if (POST_DATA.DEL[room_id]){ 
                    POST_DATA.DEL[room_id].push(time_id) 
                } 
                else { 
                   POST_DATA.DEL[room_id] = [time_id,] 
                } 
            } 
 
            else if ($(this).hasClass('td_active')){ 
                $(this).removeClass("td_active"); 
                var del_index = POST_DATA.ADD[room_id].indexOf(time_id); 
                POST_DATA.ADD[room_id].splice(del_index,1) 
            } 
            else if ($(this).hasClass("active_now")){ 
{#                pass#} 
            } 
            else { 
                $(this).addClass("td_active"); 
                if (POST_DATA.ADD[room_id]){ 
                    POST_DATA.ADD[room_id].push(time_id); 
{#                    alert(time_id)#} 
                } 
                else { 
                   POST_DATA.ADD[room_id] = [time_id,] 
                } 
 
            } 
 
 
        }) 
        } 
        bindtd(); 

  

分别对空的表格,刚才点击过的预定的表格【但是还未更新到数据库】,当前用户预定的表格,其他用户预定的表格做分别的处理,添加不同的样式,同时更新POST_DAT

这里还有一个知识点

就是增加js的数组中的数据

POST_DATA.DEL[room_id].push(time_id)  

js删除数组中的元素的方式,首先要获取要删除元素的索引,然后在删除

                var del_index = POST_DATA.ADD[room_id].indexOf(time_id); 
                POST_DATA.ADD[room_id].splice(del_index,1) 

  

c、最后在看下更新数据库的试图函数

import json 
def book(request): 
    method = request.method.lower() 
    if method == "post": 
        add_dict = json.loads(request.body.decode('utf-8'))["ADD"] 
        del_dict = json.loads(request.body.decode('utf-8'))["DEL"] 
        print(add_dict,del_dict) 
        user_obj = request.user 
        if add_dict: 
            for k in add_dict.keys(): 
                for v in add_dict[k]: 
                    models.book.objects.create( 
                        user_obj = user_obj, 
                        room_obj = models.room.objects.get(rid=int(k)), 
                        time_id = v, 
                    ) 
        if del_dict: 
            for k in del_dict.keys(): 
                for v in del_dict[k]: 
                    models.book.objects.filter( 
                        user_obj = user_obj, 
                        room_obj = models.room.objects.get(rid=int(k)), 
                        time_id = v 
                    ).delete() 
 
        return HttpResponse("ok") 

首先从ADD的字典中拿出数据,然后调用create方法更新数据

然后从DEL的字典中拿出数据,然后调用del方法更新数据

最后返回结果,前端重新加载当前页面即可

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/20780.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论