建立新项目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>
版权归原作者 m0_73907818 所有, 如有侵权,请联系我们删除。