0


Django web 开发(四) - 员工管理系统(一)

建立新项目Django web开发(三)Django_django 个人网站开发-CSDN博客

ps:该篇都请和Django web 开发(三)结合着看,因为我懒得写

数据库环节

首先在mysql可视化创建数据库

然后创建初始表

根据初始表再在model.py里写代码创建连用的表


在mysql可视化里建表建初始数据

注意:

  • id是否要自动

  • 外键问题
  • 表名 结构为app名_表名
  • 外键关联数据删除/更新时如何

当设置删除父表时,设置为空的话必须子表要允许为空

  • 设计外键的界面,有七列:名(name):可以不填,保存时会自动生成。
  • CASCADE:当我们从父表中删除或更新任何行时,子表中匹配行的值将被自动删除或更新。 SET NULL:当我们从父表中删除或更新任何行时,子表中的外键列的值会被设置为NULL。 RESTRICT:当我们从父表中删除或更新在引用(子)表中具有匹配行的任何行时,MySQL 不允许删除或更新父表中的行。 NO ACTION:类似于RESTRICT。但有一个不同之处,它会在尝试修改表后检查引用完整性。 SET DEFAULT:MySQL 解析器能识别此橾作。但是,InnoDB 和 NDB 表都拒绝此橾作。
  • enum在这里是限定sex这一个字段只能输入“男”或“女”

页面设计

常用:div、li、container

数据库

在函数里调用数据库

在models.py里创建数据库,后面调用models

ps/常见报错

可以现在mysql可视化里创建数据库,然后导出结构文件文本,黏贴给ai让它给出orm代码,再稍作修改

外键那几个模式可以看Navicat:在 Navicat 中创建外键约束_navicat外键-CSDN博客

(或者用Alchemy插件反向生成models.py文件,但它好像是和orm用法调用不太一样,我没搞懂放弃)

在mysql可视化里修改数据库删不掉可能是因为有外键约束,耐心看一下原因,按顺序删就好

创建数据库显示重复创建时,根据ai解释的报错,可尝试删除之前的迁移数据库文件,再次重新生成(就是这些00010002,就_init_.py不能删

参照以下代码修改(id会自己创建自动增加的,注意外键

from django.db import models

# Create your models here.
class Department(models.Model):
    """部门表"""
    title = models.CharField(max_length=32, verbose_name='标题')

class UserInfo(models.Model):
    """员工表"""
    name = models.CharField(max_length=16, verbose_name="姓名")
    password = models.CharField(max_length=64, verbose_name="密码")
    age = models.IntegerField(verbose_name="年龄")
    account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
    create_time = models.DateTimeField(verbose_name="入职时间")

    # 外键约束
    # to 表示与哪张表关联
    # to_field 表示表中的哪一列
    # 在django中,数据表中的名称自动加上_id,也就是depart_id
    # on_delete=models.CASCADE 表示级联删除(删除部门,部门下的所有员工都会被删除)
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE, verbose_name="部门")
    # on_delete=models.SET_NULL, null=True, blank=True 表示置空(删除部门,部门下的所有员工的部门字段置为空)
    # depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.SET_NULL, null=True, blank=True)

    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(choices=gender_choices, verbose_name="性别")

展示页面

常规urls

views

from django.shortcuts import render
from app01 import models

# Create your views here.

def depart_list(request):
    # 部门列表

    # 去数据库获取数据
    queryset = models.Department.objects.all()
    print(queryset)

    return render(request, 'depart_list.html',{'queryset':queryset})

html

记得引用js、boot那几个样式

样式省略,表格里显示数据库信息:

<tbody>
                {% for obj in queryset %}
                <tr>
                    <th scope="row">{{ obj.id }}</th>
                    <td>{{ obj.title }}</td>
                    <td>
                        <a class="btn btn-primary btn-sm">编辑</a>
                        <a class="btn btn-danger btn-sm">删除</a>
                    </td>
                </tr>
                {% endfor %}
 </table>

删除页面

删除不需要新建html,使用view和a标签结合使用?nid

但是urls也是要写的!!这个是新建函数就要写的!!

view

def depart_delete(request):
    """部门删除"""
    # 获取id # http://localhost: 8000/depart/delete/?nid=1
    nid = request.GET.get('nid')
    # 删除
    models.Department.objects.filter(id=nid).delete()
    # 重定向回部门列表
    return redirect("/depart/list/")

在depart_list。html里修改删除标签

<tbody>
{% for obj in queryset %}
     <tr>
          <th scope="row">{{ obj.id }}</th>
          <td>{{ obj.title }}</td>
          <td>
              <a class="btn btn-primary btn-sm">编辑</a>
              <a class="btn btn-danger btn-sm" href="/depart/delete/?nid={{ obj.id }}">
                    删除
              </a>
          </td>
      </tr>
{% endfor %}
</tbody>

编辑页面

编辑按钮:编辑

urls 用int:nid要求要传入一个整形

path('depart/<int:nid>/edit/',views.depart_edit),

view

def depart_edit(request, nid):
    """修改部门"""
    # form = UserModelForm()

    if request.method == "GET":
        # 根据nid,获取数据
        row_object = models.Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object": row_object})

    # 如果是POST请求,保存修改
    depart_title = request.POST.get('depart_title')
    models.Department.objects.filter(id=nid).update(title=depart_title)

    # 重定向回部门列表
    return redirect('/depart/list/')

展示界面 value是输入框默认值

<div class="form-group">
     <label>部门名称</label>
     <input type="text" class="form-control" placeholder="部门名称" name="depart_title" value="{{ row_object.title }}">
</div>

2.模板的继承

{% block content %}{% endblock %}后面使用改模板的页面内容会替换掉这里的占位符

其中可以替换title、css、body、js等

eg:定义模板layout.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}
    {% endblock %}

    <link rel="stylesheet" href="{% static 'plugins/...bootstrap.css' %}">
    {% block css %}
    {% endblock %}

</head>
<body>

{#上方导航栏#}
<nav class="navbar navbar-expand-lg bg-body-tertiary" style="..."...>

{#中间#}
<div>
    <div class="container">
        {# 特殊占位符 后面使用会替换掉{}里面东西#}
        {% block content %}{% endblock %}

    </div>
</div>

<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'plugins/...bootstrap.bundle.js' %}"></script>

{% block js %}     
{% endblock %}

<!--<script type="text/javascript"
   这里写js代码#}
   写block里面#}
    </script>#}-->

</body>
</html>

继承模板:

再不用重复导入插件以及重复的页面代码了,连<!DOCTYPE html> <html lang="en"> <head>这些页面开头结尾都不用写

{% extends 'layout.html' %}

{% block title %}
     <title>Title</title>
{% endblock %}

{% block css %}
    <link rel=...>
    <style>
        ...
    </style>
{% endblock %}

{% block content %}
    <h1>首页</h1>
    ...
{% endblock %}

{% block js %} 
    <script type="text/javascript">
    <!--这里写js代码-->
    ...
    </script>
        
{% endblock %}

如果其他例如style的地方需要不同,也可以多写几个block,eg:{% block css %}、{% block js %}

添加页面

target="_blank"可以让a标签打开一个全新页面
{#    新建按钮#}
    <div style="margin-bottom: 20px;">
        <a class="btn btn-success" href="/depart/add/" target="_blank">
            新建部门
        </a>
    </div>

弹幕:v5版本使用model配合input_group可以实现弹窗添加而非新网页

可以把之前的标题列表样式复制过来

提交记得写post和get

提交一般都是form表单,要写提交形式

view那也要写get去提交页面,post去提交

def user_add(request):
    """添加用户"""
    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_add.html', {'form': form})
    else:
        form = UserModelForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('success_url')  # 重定向到操作成功的页面
        else:
            return render(request, 'user_add.html', {'form': form})

action那不写就是默认跳到当前页面,请注意一定要写**{% csrf_token %}**

ps:所以我选择让ai帮我写form(○` 3′○)

def depart_add(request):
    """添加部门  modelform"""
    form = UserModelForm()

    if request.method == 'GET':
        return render(request, 'depart_add.html', {'form': UserModelForm()})
    title = request.POST.get("title")
    # ???咋写

    # 保存在数据库
    models.Department.objects.create(title=title)

    # 重定向回部门列表
    return redirect("/depart/list/")
    # return render(request, 'depart_add.html', {'form': form})

modelform

views 用modelform调用models.py里表的部分数据

以后增加就可以直接在fields里面改

# modelform示例##########################################
from django import forms

class UserModelForm(forms.ModelForm):
    class Meta:
        model = models.UserInfo
        fields = ['name',  'password', 'age']

def depart_add(request):
    """添加部门  modelform"""
    form = UserModelForm()
    return render(request, 'depart_add.html', {'form': form})

html,使用这个显示这三个输入框

{#formmodel#}
<form method="post">
    {%  csrf_token %}

    {{ form.name }}
    {{ form.password }}
    {{ form.age }}

</form>

更方便地是使用for循环展示之前写在Meta里面的fields里的

label表示的是model.py里面的verbose_name

name = models.CharField(max_length=16, verbose_name="姓名")
<form method="post">
    {%  csrf_token %}
    {% for field in form %}
        {{ field.label }} : {{ field }}        
    {% endfor %}  
</form>

对象

当depart调用另一个表的内容时,直接显示就会这样

所以要用面向对象的知识

在model.py里depart字段调用的另一个表的title

class Department(models.Model):
    """部门表"""
    title = models.CharField(max_length=32, verbose_name='标题')

    def __str__(self):
        return self.title

在这个例子中,当您在 Django 管理后台查看Department实例时,将显示其

title

属性的值。

给所有Input框添加样式

view里的class这么写

注意不是Meta里面的 注意缩进 def init(self, *args, **kwargs):

# modelform示例##########################################
from django import forms

class UserModelForm(forms.ModelForm):
    class Meta:
        model = models.UserInfo
        fields = ['name', 'password', 'age', 'gender', 'depart']
        # # 逐一控制标签的样式 较麻烦
        # widgets = {
        #     "name": forms.TextInput(attrs={"class": "form-control"}),
        #     "password": forms.PasswordInput(attrs={"class": "form-control"}),
        # }

    # 循环找到所有的插件,添加 "class": "form-control"
    # 注意不是Meta里面的 注意缩进
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            # 可以排除指定的字段
            if name == "password":
                continue
            print(name, field)
            field.widget.attrs = {"class": "form-control"}

数据校验错误提示

修改myproject/myproject/settings.py

改为中文,目的是为了让页面提示错误信息时显示中文,否则会显示英文

#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'

如果我们没有写入任何内容直接点击"保存",那么页面会提示错误

因为我们在/root/python/myproject/employee_management/templates/user_model_form_add.html中加入了{{ field.errors.0 }}字段

form后面的novalidate是取消浏览器的验证效果,仅使用自己写的验证

验证有很多 懒得记了 ai吧。。

日期设置

数据库字段中,DataTimeField默认有年月日时分秒

所以用DataField更好,只有年月日

时间输入换成可选择的:

参考Django web 开发(四) - Django项目实践(四)-用户管理_django 转字符串-CSDN博客

效果

编辑用户

编辑用户和删除都要用nid

调用之前的modelform(不用重新写了)

path('user/<int:nid>/edit/', views.user_edit),
form = UserModelForm(instance=row_object)会自动把input输入框的内容填上原有数据 
def user_edit(request,nid):
    """编辑用户"""
    # 根据id去获取要编辑的那一行数据(对象
    row_object = models.UserInfo.objects.filter(id=nid).first()

    form = UserModelForm(instance=row_object)
    return render(request,'user_edit.html',{'form': form})

更新view,换成有post get的

post和get都用到row_object = models.UserInfo.objects.filter(id=nid).first()

def user_edit(request, nid):
    """编辑用户"""
    # post提交时,要获取nid才能知道它要更新哪个
    row_object = models.UserInfo.objects.filter(id=nid).first()
    # 根据id去获取要编辑的那一行数据(对象
    if request.method == "GET":        
        form = UserModelForm(instance=row_object)
        return render(request, 'user_edit.html', {'form': form})
    # post提交时,要获取nid才能知道它要更新哪个   
    # 这里加个instance=row_object就告诉它不要新增数据啦,是更新数据
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/user/list/')
    render(request, 'user_edit.html', {'form': form})

html

注意,按钮类型为submit,并且在form表单里面

{% extends 'layout.html' %}

{% block content %}

{#中间输入表格#}
<div class="container" style="width: 800px">
    <div class="card ">
        <div class="card-header">
            修改用户
        </div>
        <div class="card-body">
            <form method="post" >
                {% csrf_token %}
                {% for field in form %}
                    <div style="margin-bottom: 10px;">
                        {{ field.label }} : {{ field }}
                    </div>
                {% endfor %}
                <button type="submit" class="btn btn-primary">保存</button>
            </form>
        </div>
    </div>
</div>

{% endblock %}

删除用户

利用nid

path('user/<int:nid>/delete/', views.user_delete),
def user_delete(request,nid):
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list/')
<a class="btn btn-primary btn-sm" href="/user/{{ obj.id }}/edit/">编辑</a>
<a class="btn btn-danger btn-sm" href="/user/{{ obj.id }}/delete/">删除</a>
标签: django python 后端

本文转载自: https://blog.csdn.net/m0_73907818/article/details/142308670
版权归原作者 m0_73907818 所有, 如有侵权,请联系我们删除。

“Django web 开发(四) - 员工管理系统(一)”的评论:

还没有评论