VUE3脚手架 + Django3.2前后端分离运动会赛事管理系统(尚未完工,待更新...)
VUE3脚手架 + Django3.2前后端分离运动会赛事管理系统前期准备需求文档数据库表设计功能设计接口文档运动员登录运动员注册学院名查询比赛查询报名表查询投诉申请新闻发布新闻发布环境搭建前端:创建VUE3脚手架项目准备环境:搭建项目:后端:创建Django3项目代码编写前端后端项目部署项目测试前期准备需求文档利用脑图简单绘制一下业务功能数据库表设计用PowerDesigner简单先设计一下需要
VUE3脚手架 + Django3.2前后端分离运动会赛事管理系统
前期准备
需求文档
利用脑图简单绘制一下业务功能
数据库表设计
用PowerDesigner简单先设计一下需要用到的表(因为后端我用的是Django,所以不要把所有的表都设计一遍,只要简单把业务层的表设计一下即可)
功能设计
运动员:填写注册信息 => 登录 => 填写报名表
普通用户:无需注册 => 查询赛事 、 运动员信息 、投诉
记录组:录入成绩、 添加决赛名单、 发布成绩
宣传组:发布新闻、 投诉管理
移动web应用原型图
接口文档
运动员登录
协议:http(s)
请求方式:POST
请求地址:http://localhost:8000/login
说明:运动员登录验证接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
username | 是 | String | 学号 |
password | 是 | Srring | 密码 |
登录成功返回:
{
"msg":"操作成功",
"data":{
"uname":"你登录的用户名",
"pwd":"你登录的密码",
"uid":"运动员id"
},
"code":1
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
data | Json | 登录的学号、密码和用户id |
code | int | 登录状态:1成功,0失败 |
运动员的赛事查询
协议:http(s)
请求方式:POST
请求地址:http://localhost:8000/player
说明:根据username查询运动员赛事接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
username | 是 | String | 学号 |
查询成功返回:
{
"msg":"操作成功",
"code":1,
"data":[
{
"gameid": 1,
"game": "【男子】100米预赛",
"finall_gameid":2,
"finall_game":"【男子】100米(决赛)",
"uid": 1,
"name": "周星驰",
"institution": "体育学院"
}
]
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
运动员注册
协议:http(s)
请求方式:POST
请求地址:http://localhost:8000/register
说明:运动员注册接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
username | 是 | String | 学号 |
password | 是 | String | 密码 |
name | 是 | String | 姓名 |
gender | 是 | int | 性别(男1 女0) |
institutionid | 是 | int | 学院id |
注册成功返回:
{
"msg":"操作成功",
"code":1
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
学院名查询
协议:http(s)
请求方式:GET
请求地址:http://localhost:8000/institutions
说明:id查询学院名接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
id | 否 | int | 通过学院id查询(如果为空,则返回所有学院) |
查询返回:
{
"msg":"操作成功",
"code":1,
"data":[
{
"id":1,
"name":"体育学院"
}
]
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
data | List | 列表:学院的id和名字 |
比赛查询
协议:http(s)
请求方式:GET
请求地址:http://localhost:8000/games
说明:id查询比赛信息接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
id | 否 | int | 通过比赛id查询(如果为空,则返回所有比赛) |
查询返回:
{
"msg":"操作成功",
"code":1,
"data":[
{
"id":1,
"name":"【男子】100米(初赛)",
"type":"田赛",
"game_type":1,
"gender":1,
"unit":"秒",
"data":"",
"status":1,
"start_time":"2020-01-01 12:48:00",
"end_time":"2020-01-01 12:48:00"
}
]
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
data | List | 列表:比赛名称、赛事分类 (田赛、径赛、团体赛)、初决赛(初赛:1,决赛2)、性别、成绩单位、信息、比赛状态(准备中:0,检录:1,结束2)、开始时间、结束时间 |
报名表查询
协议:http(s)
请求方式:GET
请求地址:http://localhost:8000/enroll
说明:id查询报名表接口
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
playerid | 否 | int | 通过运动员id查询(如果为空,则返回所有报名表) |
查询返回:
{
"msg":"操作成功",
"code":1,
"data":[
{
"id":1,
"name":"姓名",
"institution":"体育学院",
"game_name":"比赛名",
"gender":1,
"gameid":2,
}
]
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
data | List | 列表:报名id、用户姓名、所属学院、比赛名、性别、比赛id |
投诉申请
协议:http(s)
请求方式:POST
请求地址:http://localhost:8000/complain
说明:申请投诉
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
contact | 是 | String | 联系方式 |
content | 是 | String | 投诉内容 |
查询返回:
{
"msg":"操作成功",
"code":1,
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
新闻发布
协议:http(s)
请求方式:POST
请求地址:http://localhost:8000/news
说明:创建新闻
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
title | 是 | String | 标题 |
content | 是 | String | 新闻内容(Markdown语法) |
查询返回:
{
"msg":"操作成功",
"code":1,
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
新闻查询
协议:http(s)
请求方式:GET
请求地址:http://localhost:8000/news
说明:id查询新闻
请求参数 | 是否必须 | 类型 | 说明 |
---|---|---|---|
id | 否 | int | 新闻id(如果为空则返回所有新闻内容) |
查询返回:
{
"msg":"操作成功",
"code":1,
"data":[
{
"id":1,
"title":"新闻标题",
"content":"Markdown语法的正文内容",
"create_time":"2021-01-01 12:20:00"
}
]
}
返回说明:
返回参数 | 类型 | 说明 |
---|---|---|
msg | String | 返回信息 |
code | int | 注册状态:1成功,0失败 |
data | List | 新闻的id、内容、创建时间 |
环境搭建
前端:创建VUE3脚手架项目
准备环境:
搭建项目:
- 安装Vue-Cli 3
npm install -g @vue/cli
- 创建vue项目
vue create 项目名
- 选择配置(我选自定义)
Manually select features
选择:
Router
Vuex
Babel
最后:
Chose Vue version
3.x
历史路由:y
选择In package.json
是否保存配置:n(也可以选择y保存)
- 进入目录测试项目启动
npm run serve
- 用IDEA打开项目
-
- 添加npm配置
命令:run
脚本:serve
-
- 配置 package.json设置自动打开浏览器
serve 命令后面加上 --open
- 配置ElementUI-Plus
-
- 安装
npm install element-plus --save
-
- 在main.js中引入Element-Plus
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import 'dayjs/locale/zh-cn'
import lang from 'element-plus/lib/locale/lang/zh-cn'
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')
后端:创建Django3项目
准备环境:
- SimpleUI后台管理 =>官方文档
- 导入导出模块django-import-export
搭建项目:
- 安装Django
pip install django
- 创建项目(可用Pycharm直接创建)
django-admin startproject 项目名
- 创建应用(Pycharm可自动创建)
python manage.py startapp App名
- 安装导入导出神器django-import-export
pip install django-import-export
在setting.py的INSTALLED_APPS里添加
# settings.py
INSTALLED_APPS = (
...
'import_export',
)
- 安装simpleUI
pip install django-simpleui
- 在settings.py的INSTALLED_APPS添加App
修改settings.py, 将simpleui和创建的App加入到INSTALLED_APPS里去,放在第一行,也就是django自带admin的前面。
INSTALLED_APPS = [
'simpleui', # 注意这里
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
...
]
-
- 设置语言, 去Logo和管理后台名字
修改settings.py, 添加如下代码:
- 设置语言, 去Logo和管理后台名字
# 更改默认语言为中文
LANGUAGE_CODE = 'zh-hans'
# 更改地区时间
TIME_ZONE = 'Asia/Shanghai'
# 去掉默认Logo或换成自己Logo链接
SIMPLEUI_LOGO = 'https://th.bing.com/th/id/R2411a2b340731d67dfa0d84503e915e3?rik=zmYce%2fLys72JVQ&pid=ImgRaw'
- 在App目录下新建一个admin.py
# tasks/admin.py
from django.contrib import admin
admin.site.site_header = '大江狗管理后台' # 设置header
admin.site.site_title = '大江狗管理后台' # 设置title
admin.site.index_title = '大江狗管理后台'
from .models import Task
admin.site.register(Task)
- 关闭Csrf验证
由于我们需要开发POST接口,Django框架当中封装了防跨站攻击的验证,但是我们仅仅只要一个简单的POST接口,所以先关闭Csrf验证。打开setting.py找到MIDDLEWARE并把’django.middleware.csrf.CsrfViewMiddleware’注释
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Django的配置引用了大江狗的文章
代码编写
前端
后端
- 模型设计:
根据数据库设计的表,编写App目录下的models.py
from django.db import models
# Create your models here.
class Institution(models.Model):
# id = models.IntegerField(verbose_name='学院id', primary_key=True, auto_created=True)
name = models.CharField(verbose_name='学院名称', max_length=255, null=False)
data = models.CharField(verbose_name='学院信息', max_length=255, null=True, blank=True)
class Meta:
verbose_name_plural = '学院表'
def __str__(self):
return self.name
class Player(models.Model):
gender_chices = ((0, '女'), (1, '男'), (2, '未知'))
# id = models.IntegerField(verbose_name='运动员id', primary_key=True)
username = models.CharField(verbose_name='学号', max_length=7, null=False)
password = models.CharField(verbose_name='密码', max_length=255, null=False)
name = models.CharField(verbose_name='姓名', max_length=255, null=False)
gender = models.IntegerField(verbose_name='性别', choices=gender_chices, null=False)
institution = models.ForeignKey(Institution, null=True, on_delete=models.SET_NULL, verbose_name='学院名')
data = models.CharField(verbose_name='数据 ', max_length=255, null=True, blank=True)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
class Meta:
verbose_name_plural = '运动员表'
def __str__(self):
return self.name
class Game(models.Model):
gender_chices = ((0, '女'), (1, '男'), (2, '未知'))
status_chices = ((0, '未开始'), (1, '检录'), (2, '结束'))
# id = models.IntegerField(verbose_name='赛事id', primary_key=True)
name = models.CharField(verbose_name='赛事名称', max_length=255, null=False)
type = models.CharField(verbose_name='赛事类型', max_length=255, null=False)
gender = models.IntegerField(verbose_name='性别', choices=gender_chices, null=False)
unit = models.CharField(verbose_name='成绩单位', max_length=255, null=False)
status = models.IntegerField(verbose_name='状态', choices=status_chices, null=False)
start_time = models.DateTimeField(verbose_name='开始时间')
end_time = models.DateTimeField(verbose_name='结束时间')
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
data = models.CharField(verbose_name='信息', max_length=255, null=True, blank=True)
class Meta:
verbose_name_plural = '赛事表'
def __str__(self):
return "【" + self.get_gender_display() + "子】" + self.name
class enroll(models.Model):
# id = models.IntegerField(verbose_name='报名表id', primary_key=True)
player = models.ForeignKey(Player, null=True, on_delete=models.SET_NULL, verbose_name='运动员')
game = models.ForeignKey(Game, null=True, on_delete=models.SET_NULL, verbose_name='比赛')
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
class Meta:
verbose_name_plural = '报名表'
def __str__(self):
return self.player.name + " 报名了: " + "【" + self.game.get_gender_display() + "子】" + self.game.name
class Score(models.Model):
# id = models.IntegerField(verbose_name='成绩表id', primary_key=True)
player = models.ForeignKey(Player, null=True, on_delete=models.SET_NULL, verbose_name='运动员')
game = models.ForeignKey(Game, null=True, on_delete=models.SET_NULL, verbose_name='比赛')
score = models.FloatField(verbose_name='成绩', null=True)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
class Meta:
verbose_name_plural = '成绩表'
def __str__(self):
return self.player.name + " 在" + \
"【" + self.game.get_gender_display() + \
"子】" + self.game.name + " 比赛中取得:" + str(self.score) + self.game.unit + "的成绩"
- models.py编写class时的要点:
序号 | 关键字 | 要点 |
---|---|---|
1 | id | 定义模型时,models会对每个模型自动添加一个主键,因此可以不需要再添加一个id字段,因为如果添加了,对应的Admin添加数据时要输入id |
2 | __str__ | 在模型中重写__str__相当于Java中的重写toString,可以解决外键关联时返回成对象的问题,__str__可以自定义返回内容 |
3 | null=True | 数据库级别可以为空,False反之(需要修改表结构) |
4 | blank=True | admin级别可以为空、False反之(只需要修改model) |
5 | Meta | db_table自定义表名,verbose_name指定在admin管理界面中显示中文;verbose_name表示单数形式的显示,verbose_name_plural表示复数形式的显示;中文的单数和复数一般不作区别。 |
6 | choices | 对应字段值的映射(元组映射) |
- 在admin.py中注册models
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.site_header = '大江狗管理后台' # 设置header
admin.site.site_title = '大江狗管理后台' # 设置title
admin.site.index_title = '大江狗管理后台'
class InstitutionAdmin(admin.ModelAdmin):
list_display = ('name', 'data')
class PlayerAdmin(admin.ModelAdmin):
list_display = ('username', 'name', 'gender', 'institution')
search_fields = ('username', 'name')
list_filter = ('gender', 'institution')
class GameAdmin(admin.ModelAdmin):
list_display = ('type', 'gender', 'name', 'status', 'start_time', 'end_time')
list_filter = ('type', 'gender', 'status', 'start_time', 'end_time')
search_fields = ['name']
list_editable= ['status', 'end_time']
class enrollAdmin(admin.ModelAdmin):
list_display = ('gametype', 'username', 'player', 'gender', 'game', 'institution', 'create_time')
list_filter = ['game__type', 'player__gender', 'game', 'player__institution', 'create_time']
search_fields = ['player__name', 'player__username']
def gametype(self, obj):
"""
写方法查询比赛类型
:param obj:
:return game_type:
"""
return obj.game.type
def username(self, obj):
"""
写方法查询运动员学号
:param obj:
:return game_type:
"""
return obj.player.username
def institution(self, obj):
"""
写方法查询学院名称
:param obj:
:return instution_name:
"""
return obj.player.institution.name
def gender(self, obj):
"""
写方法查询运动员性别
:param obj:
:return player_gender:
"""
return obj.player.get_gender_display()
class ScoreAdmin(admin.ModelAdmin):
list_display = ('gametype', 'username', 'player', 'institution', 'game', 'score', 'unit', 'create_time')
search_fields = ['player__name', 'player__username']
list_filter = ['game__type', 'player__gender', 'game', 'player__institution', 'create_time']
def username(self, obj):
"""
写方法查询运动员学号
:param obj:
:return game_type:
"""
return obj.player.username
def unit(self, obj):
return obj.game.unit
def institution(self, obj):
"""
写方法查询学院名称
:param obj:
:return instution_name:
"""
return obj.player.institution.name
def gametype(self, obj):
"""
写方法查询比赛类型
:param obj:
:return game_type:
"""
return obj.game.type
class NewsAdmin(admin.ModelAdmin):
list_display = ('title', 'content', 'create_time')
search_fields = ('title', 'content')
list_filter = ('create_time',)
list_editable = ('content', )
class ComplaintAdmin(admin.ModelAdmin):
search_fields = ('contact', 'content')
list_display = ('contact', 'content', 'create_time')
admin.site.register(Institution, InstitutionAdmin)
admin.site.register(Player, PlayerAdmin)
admin.site.register(Game, GameAdmin)
admin.site.register(enroll, enrollAdmin)
admin.site.register(Score, ScoreAdmin)
admin.site.register(News, NewsAdmin)
admin.site.register(Complaint, ComplaintAdmin)
添加admin.ModelAdmin子类装饰器到原模型:
关键字 | 说明 |
---|---|
list_display | 显示的字段 |
search_fields | 搜索字段 |
list_filter | 过滤字段(过滤外键时,添加的列表元素格式为:外键名__字段名, 多级外键过滤:外键名__外键表的外键字段__字段名…) |
date_hierarchy | 顶部添加逐层深入的导航条 |
ordering | 设置模块界面显示的排序顺序 |
fields | 表示编辑表单界面各字段的顺序,也可以少些一些,用来屏蔽不让用户改的字段。(即:按顺序显示什么字段) |
filter_horizontal | 和admin中给予权限选择一样的多选移动框 |
filter_vertical | 与filter_horizontal一样,只不过是垂直显示的。 |
raw_id_fields | 显示外键详细信息 |
list_editable | 设置字段可以页面修改 |
- 在views.py中写入api
from django.shortcuts import render
from django.http import HttpResponse
import datetime
import json
from sportmeeting.models import *
class api:
def __init__(self, data):
"""
初始化data
:param data: List或Dict 数据库数据
"""
self.data = data
def success(self):
"""
成功返回的json
:return: String 编码后的json字符串
"""
return HttpResponse(json.dumps(
{
'msg': '操作成功',
'code': 1,
'data': self.data
}
),
content_type="application/json"
)
def error(self):
"""
错误返回的json
:return:
"""
return HttpResponse(json.dumps(
{
'msg': '非法操作',
'code': 0,
'data': self.data
}
),
content_type="application/json"
)
def current_datetime():
return str(datetime.datetime.now())[:-7]
# Create your views here.
def login(request):
if request.method == 'POST':
try:
json_data = json.loads(request.body)
username = json_data['username']
password = json_data['password']
except:
return api({'msg': 'json格式不正确'}).error()
try:
user = Player.objects.get(username=username)
if user.password == password:
return api({'uname': user.username, 'pwd': user.password, 'uid': user.id}).success()
else:
return api('密码错误').error()
except Exception as e:
return api('账号未注册').error()
return api('must be post').error()
def register(request):
if request.method == 'POST':
try:
json_data = json.loads(request.body)
username = json_data['username']
password = json_data['password']
name = json_data['name']
gender = json_data['gender']
institutionid = json_data['institutionid']
except:
return api({'msg': 'json格式不正确'}).error()
if Player.objects.filter(username=username).exists():
return api('账号已存在').error()
else:
try:
Player.objects.create(
username=username,
password=password,
name=name,
gender=gender,
institution_id=institutionid
)
return api('注册成功').success()
except Exception as e:
return api(e).error()
def institutions(request):
if request.method == 'GET':
ins_id = request.GET.get('id', '')
if ins_id == '':
ins = Institution.objects.all()
datalist = []
for item in ins:
datalist.append({'id': item.id, 'name': item.name})
return api(datalist).success()
else:
ins = Institution.objects.filter(id=ins_id)
datalist = []
for item in ins:
datalist.append({'id': item.id, 'name': item.name})
return api(datalist).success()
def games(request):
if request.method == 'GET':
game_id = request.GET.get('id', '')
if game_id == '':
ins = Game.objects.all()
datalist = []
for item in ins:
datalist.append(
{'id': item.id,
'name': item.name,
'type': item.type,
'gender': item.gender,
'unit': item.unit,
'data': item.data,
'status': item.status,
'start_time': str(item.start_time)[:-6],
'end_time': str(item.end_time)[:-6]
}
)
return api(datalist).success()
else:
ins = Game.objects.filter(id=game_id)
datalist = []
for item in ins:
datalist.append(
{'id': item.id,
'name': item.name,
'type': item.type,
'gender': item.gender,
'unit': item.unit,
'data': item.data,
'status': item.status,
'start_time': str(item.start_time)[:-6],
'end_time': str(item.end_time)[:-6]
}
)
return api(datalist).success()
def enroll_model(request):
if request.method == 'GET':
enroll_id = request.GET.get('id', '')
if enroll_id == '':
items = enroll.objects.all()
datalist = []
for item in items:
datalist.append(
{'id': item.id,
'name': item.player.name,
'institution': item.player.institution.name,
'game_name': item.game.name,
'gender': item.game.gender,
'gameid': item.game.id,
}
)
return api(datalist).success()
else:
ins = enroll.objects.filter(id=enroll_id)
datalist = []
for item in ins:
datalist.append(
{'id': item.id,
'name': item.player.name,
'institution': item.player.institution.name,
'game_name': item.game.name,
'gender': item.game.gender,
'gameid': item.game.id,
}
)
return api(datalist).success()
def complain(request):
if request.method == 'POST':
try:
json_data = json.loads(request.body)
contact = json_data['contact']
content = json_data['content']
except:
return api({'msg': 'json格式不正确'}).error()
try:
Complaint.objects.create(
contact=contact,
content=content
)
return api({'msg': '投诉提交成功'}).success()
except:
return api({'msg': '投诉提交错误'}).error()
else:
return api({'msg': '投诉提交错误'}).error()
def news(request):
if request.method == 'POST':
try:
json_data = json.loads(request.body)
title = json_data['title']
content = json_data['content']
except:
return api({'msg': 'json格式不正确'}).error()
try:
News.objects.create(
title=title,
content=content,
)
return api({'msg': '提交成功'}).success()
except:
return api({'msg': '投诉错误'}).error()
else:
news_id = request.GET.get('id', '')
if news_id == '':
items = News.objects.all()
datalist = []
for item in items:
datalist.append(
{'id': item.id,
'title': item.title,
'content': item.content
}
)
return api(datalist).success()
else:
items = News.objects.filter(id=news_id)
datalist = []
for item in items:
datalist.append(
{'id': item.id,
'title': item.title,
'content': item.content
}
)
return api(datalist).success()
def player(request):
if request.method == 'GET':
username = request.GET.get('username')
try:
playerobj = Player.objects.get(username=username)
except:
return api("查无此用户").error()
items = playerobj.enroll_set.all()
data = []
for item in items:
data.append(
{
"gameid": item.id,
"game": str(item.game),
"uid": item.player.id,
"name": item.player.name,
"institution": item.player.institution.name
}
)
return api(data).success()
api主要就是对数据库的查询处理
转载:objects.all()、objects.get()与objects.filter()区别
关键字 | 说明 |
---|---|
.objects.all() | 返回的是QuerySet对象,程序并没有真的在数据库中执行SQL语句查询数据,但支持迭代,使用for循环可以获取数据 |
.objects.get(id=‘1’) | 从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。它返回的是一个字典的形式,如果去取得关联表的数据的话,而关键表的数据如果多于2条的话也会报错 |
.objects.filter() | filter和get类似,但支持更强大的查询功能。方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话, |
它会返回[]
主表对象.从表_set.all()|外键反查,上述api中是通过用户来查询出他的报名表(主表对象先通过get获取,然后再.从表_set.all())
- 基本命令
数据库迁移模型生成
python manage.py makemigrations
数据库迁移
python manage.py migrate
创建admin后台用户
python manage.py createsuperuser
运行Django
python manage.py runserver 0.0.0.0:8000
* [Django3官方文档](https://docs.djangoproject.com/zh-hans/3.1/)
项目部署
项目测试
更多推荐
所有评论(0)