zoukankan      html  css  js  c++  java
  • 会议室预定作业代码梳理

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

    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=" 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方法更新数据

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

  • 相关阅读:
    QQ家园熄灭不了解决方法
    那时我们还年轻[转]
    QQ游戏图标熄灭大全
    FlashDevelop快捷键
    linux 全局搜索某一文件并将文件内容并进行替换的命令
    navigate 10.0.5 regist cn
    线程、socket、stl 以及并发设计
    drupal真不错
    网卡问题解决思路linux版
    socket错误:Program received signal SIGPIPE, Broken pipe
  • 原文地址:https://www.cnblogs.com/bainianminguo/p/10069110.html
Copyright © 2011-2022 走看看