以下是drf+vue3+element-plus搭建CRUD的案例:
1. 创建Django项目,命名为backend,创建Django APP,命名为api。
2. 在api中创建models.py文件,定义模型:
```
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
```
3. 在api中创建serializers.py文件,定义序列化器:
```
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
```
4. 在api中创建views.py文件,定义视图:
```
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
```
5. 在backend中配置api的url:
```
from django.urls import path, include
from rest_framework import routers
from api.views import BookViewSet
router = routers.DefaultRouter()
router.register(r'books', BookViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
```
6. 在frontend中创建vue3项目,命名为frontend,安装element-ui和axios:
```
yarn add element-plus axios
```
7. 在frontend中创建src/api/index.js文件,定义请求:
```
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:8000/api/',
timeout: 1000,
headers: {'Content-Type': 'application/json'}
})
export default {
getBooks() {
return instance.get('books/')
},
createBook(data) {
return instance.post('books/', data)
},
updateBook(id, data) {
return instance.put(`books/${id}/`, data)
},
deleteBook(id) {
return instance.delete(`books/${id}/`)
}
}
```
8. 在frontend中创建src/views/BookList.vue文件,定义书籍列表组件:
```
<template>
<el-table :data="books" style="width: 100%">
<el-table-column prop="title" label="书名"></el-table-column>
<el-table-column prop="author" label="作者"></el-table-column>
<el-table-column prop="price" label="价格"></el-table-column>
<el-table-column label="操作">
<template #default="{row}">
<el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
import api from '@/api'
export default {
name: 'BookList',
data() {
return {
books: []
}
},
async created() {
const res = await api.getBooks()
this.books = res.data
},
methods: {
handleEdit(row) {
this.$router.push({name: 'BookEdit', params: {id: row.id}})
},
async handleDelete(row) {
try {
await api.deleteBook(row.id)
this.books = this.books.filter(book => book.id !== row.id)
this.$message.success('删除成功')
} catch (error) {
this.$message.error('删除失败')
}
}
}
}
</script>
```
9. 在frontend中创建src/views/BookCreate.vue文件,定义创建书籍组件:
```
<template>
<el-form :model="form" :rules="rules" ref="form" label-width="80px">
<el-form-item label="书名" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="作者" prop="author">
<el-input v-model="form.author"></el-input>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="form.price"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">创建</el-button>
</el-form-item>
</el-form>
</template>
<script>
import api from '@/api'
export default {
name: 'BookCreate',
data() {
return {
form: {
title: '',
author: '',
price: ''
},
rules: {
title: [
{required: true, message: '请输入书名', trigger: 'blur'}
],
author: [
{required: true, message: '请输入作者', trigger: 'blur'}
],
price: [
{required: true, message: '请输入价格', trigger: 'blur'},
{type: 'number', message: '价格必须为数字', trigger: 'blur'}
]
}
}
},
methods: {
async handleSubmit() {
try {
await this.$refs.form.validate()
await api.createBook(this.form)
this.$message.success('创建成功')
this.$router.push({name: 'BookList'})
} catch (error) {
this.$message.error('创建失败')
}
}
}
}
</script>
```
10. 在frontend中创建src/views/BookEdit.vue文件,定义编辑书籍组件:
```
<template>
<el-form :model="form" :rules="rules" ref="form" label-width="80px">
<el-form-item label="书名" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="作者" prop="author">
<el-input v-model="form.author"></el-input>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="form.price"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<script>
import api from '@/api'
export default {
name: 'BookEdit',
data() {
return {
id: this.$route.params.id,
form: {
title: '',
author: '',
price: ''
},
rules: {
title: [
{required: true, message: '请输入书名', trigger: 'blur'}
],
author: [
{required: true, message: '请输入作者', trigger: 'blur'}
],
price: [
{required: true, message: '请输入价格', trigger: 'blur'},
{type: 'number', message: '价格必须为数字', trigger: 'blur'}
]
}
}
},
async created() {
const res = await api.getBooks()
const book = res.data.find(book => book.id == this.id)
this.form = book
},
methods: {
async handleSubmit() {
try {
await this.$refs.form.validate()
await api.updateBook(this.id, this.form)
this.$message.success('保存成功')
this.$router.push({name: 'BookList'})
} catch (error) {
this.$message.error('保存失败')
}
}
}
}
</script>
```
11. 在frontend中创建src/router/index.js文件,定义路由:
```
import {createRouter, createWebHistory} from 'vue-router'
import BookList from '@/views/BookList.vue'
import BookCreate from '@/views/BookCreate.vue'
import BookEdit from '@/views/BookEdit.vue'
const routes = [
{path: '/', name: 'BookList', component: BookList},
{path: '/create', name: 'BookCreate', component: BookCreate},
{path: '/edit/:id', name: 'BookEdit', component: BookEdit},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
```
12. 在frontend中创建src/main.js文件,初始化vue3和element-plus:
```
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
createApp(App).use(router).use(ElementPlus).mount('#app')
```
至此,我们成功地实现了一个简单的CRUD功能。