会议室预订系统(meeting room booking system)

一、目标及业务流程

期望效果:

业务流程:

  1. 用户登录
  2. 预定会议室
  3. 退订会议室
  4. 选择日期;今日以及以后日期

二、表结构设计和生成

1、models.py(用户继承AbstractUser)

from django.db import models
# Create your models here.
from django.db import models
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """用户信息表"""
    tel = models.CharField(max_length=32)

class Room(models.Model):
    """会议室表"""
    caption = models.CharField(max_length=32)   # 会议室名字
    num = models.IntegerField()   # 会议室容纳人数
    def __str__(self):
        return self.caption

class Book(models.Model):
    """会议室预订信息"""
    user = models.ForeignKey("UserInfo", on_delete=models.CASCADE)   # CASCADE级联删除
    room = models.ForeignKey("Room", on_delete=models.CASCADE)
    date = models.DateField()  # 日期
    time_choices = (    # 时段
        (1, '8:00'),
        (2, '9:00'),
        (3, '10:00'),
        (4, '11:00'),
        (5, '12:00'),
        (6, '13:00'),
        (7, '14:00'),
        (8, '15:00'),
        (9, '16:00'),
        (10, '17:00'),
        (11, '18:00'),
        (12, '19:00'),
        (13, '20:00'),
    )
    time_id = models.IntegerField(choices=time_choices)    # 存数字,choices参数
    class Meta:
        unique_together = (   # 三个联合唯一,防止有人重复预定
            ('room', 'date', 'time_id'),
        )
    def __str__(self):
        return str(self.user) + "预定了" + str(self.room)

注意:

(1)Django中提供了AbstractUser类,可以用来自由定制需要的model

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """用户信息表"""
    tel = models.CharField(max_length=32)

  如上所示,即可在Django的基础上添加我们所需要的信息。

(2)设置model的时候,设置三个字段联合唯一

class Book(models.Model):
    """会议室预订信息"""
    ....
    class Meta:
        unique_together = (   # 三个联合唯一,防止有人重复预定
            ('room', 'date', 'time_id'),
        )

   存的是key 显示的是value,且只能存key

2、修改配置文件settings.py,覆盖默认的User模型

  Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。

AUTH_USER_MODEL = "app01.UserInfo"

  上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。

注意:在创建任何迁移或者第一次运行 manager.py migrate 前设置 AUTH_USER_MODEL

  设置AUTH_USER_MODEL数据库结构有很大的影响。改变了一些会使用到的表格,并且会影响到一些外键和多对多关系的构造。在你有表格被创建后更改此设置是不被 makemigrations 支持的,并且会导致你需要手动修改数据库结构,从旧用户表中导出数据,可能重新应用一些迁移。

3、数据迁移及创建超级用户

$ python3 manage.py makemigrations
$ python3 manage.py migrate

  这里遇到了一个问题:创建项目时没有创建应用,手动通过manage.py startapp user创建子项目,修改AUTH_USER_MODEL后执行makemigrations一直报错,找不到app01。

  创建两个超级用户:

MacBook-Pro:MRBS hqs$ python3 manage.py createsuperuser
Username: yuan
Password:yuan1234

MacBook-Pro:MRBS hqs$ python3 manage.py createsuperuser
Username: alex
Password:alex1234

三、系统登录login

urls.py:

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('book/', views.book),
]

简单login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    用户名:<input type="text" name="user">
    密码:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

login视图函数:

from django.shortcuts import render, redirect
# Create your views here.
from django.contrib import auth

def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        user = auth.authenticate(username=user, password=pwd)
        if user:
            # 登录成功
            auth.login(request, user)   # 注册request.user,可以拿到登录用户对象所有信息
            redirect("/index/")

    return render(request, "login.html")

  注意:auth模块的authenticate()方法,提供了用户认证,如果认证信息有效,会返回一个  User  对象;如果认证失败,则返回None。

四、index部分

1、引入admin组件(后台数据管理组件)并完成admin注册

admin.py:

from django.contrib import admin
# Register your models here.
from app01.models import *

admin.site.register(UserInfo)
admin.site.register(Book)
admin.site.register(Room)

2、在数据库添加数据

  

  

3、index视图函数数据处理和index.html模板渲染

注意:

(1)数据处理还是在后台更加方便,前台渲染后台传递来的标签字符串

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>会议室时间</th>
            {% for time_choice in time_choices %}
                {# 在元组中取第二个值 #}
                <th>{{ time_choice.1 }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {# 由于模板语法功能不够强大,因此数据处理还是放在后台,在这里渲染后台传递来的标签字符串 #}
        {{ htmls|safe }}
    </tbody>
</table>

  由于模板语法功能不够强大,因此数据处理还是放在后台,在这里渲染后台传递来的标签字符串。

(2)视图函数字符串处理,运用format格式化函数

def index(request):
    # 拿到预定表中的时间段
    time_choices = Book.time_choices
    # 拿到所有的会议室
    room_list = Room.objects.all()
    # 构建标签
    htmls = ""
    for room in room_list:
        # 第一列td完成后,还有其他td标签需要添加,因此此处没有闭合tr
        htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

    return render(request, "index.html", locals())

显示效果:

  这是Python2.6后新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能。基本语法是通过 {} 和 : 来代替以前的 % 。format 函数可以接受不限个参数,位置可以不按顺序。

>>>"{} {}".format("hello", "world")    # 不设置指定位置,按默认顺序
'hello world'
 
>>> "{0} {1}".format("hello", "world")  # 设置指定位置
'hello world'
 
>>> "{1} {0} {1}".format("hello", "world")  # 设置指定位置
'world hello world'

  还可以设置参数:

print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))
 
# 通过字典设置参数
site = {"name": "菜鸟教程", "url": "www.runoob.com"}
print("网站名:{name}, 地址 {url}".format(**site))
 
# 通过列表索引设置参数
my_list = ['菜鸟教程', 'www.runoob.com']
print("网站名:{0[0]}, 地址 {0[1]}".format(my_list))  # "0" 是必须的

(3)循环会议室生成行,循环时段生成列,标签字符串拼接处理

def index(request):
    # 拿到预定表中的时间段
    time_choices = Book.time_choices
    # 拿到所有的会议室
    room_list = Room.objects.all()

    # 构建标签
    htmls = ""
    for room in room_list:   # 有多少会议室生成多少行,
        # 每行仅生成了第一列。还有其他td标签需要添加,因此此处没有闭合tr
        htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

        for time_choice in time_choices:   # 有多少时段就生成多少列
            # 一次循环就是一个td标签
            htmls += "<td></td>"

        # 循环完成后闭合tr标签
        htmls += "</tr>"
    return render(request, "index.html", locals())

  比如会议室有3个,循环会议室生成三行,且拿到会议室名称和人数限制生成首列;再循环时段,这里有13个时段,因此生成13列,13个td标签依次添加进一个tr中,显示效果如下:

  

(4)

猜你喜欢

转载自www.cnblogs.com/xiugeng/p/9490830.html
今日推荐