目录
后端:
# 数据库创建:
create database 数据库名字 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
# settings 更改
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':' ', # 数据库名字
'USER': ' ',
'PASSWORD': ' ',
'HOST': '127.0.0.1',
'PORT': 3306,
}
}# 数据迁移
python manage.py makemigrations
python manage.py migrate
# 新建app (写入settings中)
python manage.py startapp app01
# 启动
python manage.py runserver
模板:
数据库设计models
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="用户")
age = models.IntegerField(verbose_name="年龄")def __str__(self):
return self.name
app01用户接口
path('zz/', views.Zzview.as_view()),
re_path('zz/(?P<pk>\d+)/', views.Zzdetailview.as_view()),
views功能函数和增删改查
class Zzview(APIView):
# 单个禁用 token 验证
authentication_classes = [TokenAuthtication]def get(self, request):
# 获取数据集(模型对象)
students_data = Author.objects.all()
pageNum = request.GET.get('pageNum', '')
pageSize = request.GET.get('pageSize', '')
# 过滤
search_nick_term = request.GET.get('name', '')
if search_nick_term:
search_nick_term = search_nick_term.strip()
students_data = students_data.filter(name__icontains=search_nick_term)
# 自定义分页 过滤后再次分页
paginator = Paginator(students_data, pageSize)
page_obj = paginator.get_page(pageNum)
# 拿到分页对象
page_obj_dq = page_obj.object_list
# 拿到总数
page_obj_zs = paginator.count
# 实例化序列化器,得到序列化器对象
# 分页对象进行序列化
ser = AuthorSerializer(instance=page_obj_dq, many=True)
# 调用序列化器对象的data属性方法获取转换后的数据
data = ser.data# 响应数据
return Response(data={'code': 200, 'zs': page_obj_zs, 'data': data})def post(self, request):
print(request.data)
# 反序列化数据
student = AuthorSerializer(data=request.data)
# 校验不通过
if not student.is_valid():
# 返回错误信息
return Response(data={'code': 500, 'data': student.errors})
# 校验通过,保存数据
student.save()
# 响应数据
return Response(data={'code': 200, 'message': '增加成功', 'data': student.data})
class Zzdetailview(APIView):
authentication_classes = [TokenAuthtication]def get(self, request, pk):
student = Author.objects.get(pk=pk)
ser = AuthorSerializer(instance=student)
return Response(ser.data)# 修改一个信息
def put(self, request, pk):
print(request.data)
instance = Author.objects.get(pk=pk)
ser = AuthorSerializer(instance=instance, data=request.data)
if not ser.is_valid():
return Response(data={'code': 500, 'message': ser.errors})
ser.save()
return Response(data={'code': 200, 'message': '修改成功', 'data': ser.data})# 删除一个信息
def delete(self, request, pk):
Author.objects.get(pk=pk).delete()
return Response(data={'code': 200, 'message': '删除成功'})
序列化器serializer
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from . import modelsclass GuanliModelSerializers(ModelSerializer):
"""管理员信息模型序列化器"""
username = serializers.CharField(read_only=True)class Meta:
model = models.Guanli
fields = '__all__'class PublishSerializer(serializers.ModelSerializer):
class Meta:
model=models.Publish
fields = "__all__"class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model=models.Author
fields = "__all__"class BookInfoModelSerializermodel(serializers.ModelSerializer):
# 使用PublishSerializer作为publish字段的嵌套序列化器
publish = PublishSerializer(read_only=True)
# 使用主键字段类型 并且将publish_id设置为"只写",也就是读取的时候不会返回!
publish_id = serializers.PrimaryKeyRelatedField(queryset=models.Publish.objects.all(), source='publish',
write_only=True)# 使用AuthorSerializer作为author字段的嵌套序列化器
authors = AuthorSerializer(read_only=True, many=True)
# 使用主键字段类型 并且将author_id设置为"只写",也就是读取的时候不会返回!
authors_id = serializers.PrimaryKeyRelatedField(queryset=models.Author.objects.all(), source='authors',
write_only=True, many=True)class Meta:
model = models.Book
fields = "__all__"
前端:
接口:
完整代码:
<template>
<el-button type="primary" @click="visible = true">添加作者</el-button>
<el-card shadow="never" style="margin-top: 10px;">
<!-- 查询区域 -->
<el-card shadow="never" style="margin: 10px 0;">
<el-form :model="search">
<el-row :gutter="30">
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="作者名:">
<el-input v-model="search.name" placeholder="请输入作者名:" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div style="text-align: right;">
<el-button type="primary" @click="getList()">查询</el-button>
<el-button @click="resetSearch()">重置</el-button>
</div>
</el-card>
<!-- 表格区域 -->
<el-table :data="tableData" stripe>
<el-table-column prop="id" label="ID" width="70" />
<el-table-column prop="name" label="姓名" />
<el-table-column prop="age" label="年纪" />
<!-- <el-table-column prop="createdAt" label="创建时间" width="180" />
<el-table-column prop="updatedAt" label="更新时间" width="180" /> -->
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" size="small" @click="editItem(scope.row)">编辑</el-button>
<el-popconfirm title="确定要删除吗?" @confirm="deleteItem(scope.row.id)">
<template #reference>
<el-button link type="primary" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
layout="sizes, total, prev, pager, next" :total="totalNum" :currentPage="search.pageNum"
:pageSize="search.pageSize">
</el-pagination>
</el-card>
<!-- 新增或编辑的抽屉 -->
<sDrawer v-model="visible" :title="form.id ? '编辑作者' : '添加作者'" size="35%" :close-on-click-modal="false">
<el-form :model="form" label-width="100px" ref="ruleFormRef">
<el-form-item label="作者名称:">
<el-input v-model="form.name" />
</el-form-item>
</el-form>
<el-form :model="form" label-width="100px" ref="ruleFormRef">
<el-form-item label="作者年纪:">
<el-input v-model="form.age" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="saveData()">确定</el-button>
</template>
</sDrawer>
</template>
<script>
import sDrawer from "@/components/s-drawer/s-drawer.vue"
export default {
components: {
sDrawer,
},
watch: {
visible(value) {
if (!value) {
this.form = {}
}
}
},
data() {
return {
form: {
},
visible: false,
tableData: [],
totalNum: 100,
search: {
pageNum: 1,
pageSize: 10,
// token: "",
},
};
},
created() {
// this.search.token = localStorage.getItem("token");
this.getList();
},
methods: {
async getList() {
const res = await this.$request.get(
"/tushu/zz/",
{ params: this.search }
);
if (res.data.code === 200) {
// this.tableData = res.data.data.sort((a, b)
console.log(res.data)
this.tableData = res.data.data;
this.totalNum = res.data.zs
}
},
// 每页条数改变时触发 选择一页显示多少行
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.search.pageSize = val;
this.getList();
},
// 当前页改变时触发 跳转其他页
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.search.pageNum = val;
this.getList();
},
resetSearch() {
let search = {
pageNum: this.search.pageNum,
pageSize: this.search.pageSize,
};
this.search = search;
this.getList();
},
editItem(row) {
this.form = this.$deepClone(row)
this.visible = true
},
async saveData() {
if (this.form.id) {
const res = await this.$request.put('/tushu/zz/' + this.form.id + '/', this.form)
if (res.data.code === 200) {
this.$message.success(res.data.message)
this.getList()
this.visible = false
}
} else {
const res = await this.$request.post('/tushu/zz/', this.form)
if (res.data.code === 200) {
this.$message.success(res.data.message)
this.getList()
this.visible = false
}
}
// const res = await this.$request.post(this.form.id ? '/tushu/guanli/' : '/tushu/guanli/', this.form)
// if (res.data.code === 200) {
// this.$message.success(res.data.message)
// this.getList()
// this.visible = false
// }
},
async deleteItem(id) {
const res = await this.$request.delete("/tushu/zz/" + id + '/')
if (res.data.code === 200) {
this.$message.success(res.data.message)
this.getList()
}
},
// 照片文件超出个数限制时的钩子
handleExceed(files, fileList) {
this.$notify.warning({
title: '警告',
message: `只能选择 ${this.limitNum} 个文件,当前共选择了 ${files.length + fileList.length} 个`
})
},
// 上传照片文件之前的钩子
handleBeforeUpload(file) {
const size = file.size / 1024 / 1024
if (size > 1) {
this.$notify.warning({
title: '警告',
message: '图片大小必须小于1M'
})
}
},
handleSuccess1(res) {
console.log(res.data,'777777777777777777777777777777777777777')
this.form.img_url = res.data.file
this.dialogImageUrl = ''
this.$notify({
title: '通知',
message: '上传照片成功~',
type: 'success',
duration: 5000
})
},
},
};
</script>
<style scoped>
.el-pagination {
margin-top: 10px;
}
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0px;
}
</style>
(如果前端使用的是html的话要添加)
在form表单添加框选的内容(如果是POST请求)加上{% csrf_token %}
因为创建的是静态static文件,所以要在.html第一行加上{% load static % }
23.9--