Django项目:前后端联调/ModelViewSet

1.创建项目pycharm文件/cmd命令:django-admin startproject +项目名

2.创建子应用/命令:python manage.py startapp +子应用名

3.项目文件下的__init__.py 安装数据库

import pymysql
pymysql.install_as_MySQLdb()

4.项目文件下的settings.py 配置

INSTALLED_APPS = [
    'School',     # 注册子应用
    'corsheaders',    # 跨域
    'rest_framework',    # def框架
]

MIDDLEWARE = [
    # 'django.middleware.csrf.CsrfViewMiddleware',    # 注释掉 防止跨站伪造
    'corsheaders.middleware.CorsMiddleware'    # 加入 中间件
]
CORS_ORIGIN_ALLOW_ALL = True    # 允许所有的源进行访问

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST':'localhost',     # 主机
        'PORT':3306,            # 端口
        'USER':'root',          # 账号
        'PASSWORD':'123456',    # 密码
        'NAME':'zx2'            # 数据库名
    }
}

LANGUAGE_CODE = 'zh-Hans'    # 时间

TIME_ZONE = 'Asia/Shanghai'    # 地区

5.路由分发

(1)项目文件下的主路由配置

from django.contrib import admin
from django.urls import path,include
from School import urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include(urls))
]

(2)子应用下的子路由配置

from django.urls import path
urlpatterns = [

]

6.子应用下文件配置,models.py配置模型类

from django.db import models

# Create your models here.
class School(models.Model):
    school_name = models.CharField(max_length=20,verbose_name='学校名称')

    class Meta:
        verbose_name='学校表'        # admin中定义的学校表
        verbose_name_plural=verbose_name    # 复数形式
        db_table = 'School'        # 数据库表的名字
    def __str__(self):            # 定义魔法方法
        return self.school_name    # 指定school_name字段


class Student(models.Model):
    stu_name = models.CharField(max_length=20,verbose_name='姓名')
    hobby = models.CharField(max_length=20,verbose_name='爱好')
    score = models.IntegerField(verbose_name='成绩')

    # 外键绑定 to=关联School表  on_delete=级联操作 CASCADE同时删除  verbose_name=外键名字
    kind = models.ForeignKey(to=School,on_delete=models.CASCADE,verbose_name='学校名称')

    class Meta:
        verbose_name='学生表'
        verbose_name_plural=verbose_name
        db_table = 'Student'
    def __str__(self):
        return self.stu_name

7.执行数据库迁移操作

迁移:       python manage.py makemigrations
执行迁移:python manage.py migrate

8.子应用下文件配置,admin.py创建超级用户,导入模型类

from django.contrib import admin
from School.models import School,Student    #导入模型类
# Register your models here.
admin.site.register(Student)
admin.site.register(School)

9.创建超级用户

命令:python manage.py createsuperuser

10.进去django管理添加测试数据

运行项目命令:python manage.py runserver

网址:http://127.0.0.1:8000/admin/

11.子应用下创建 serializers序列化py文件

from rest_framework import serializers     #导入serializers
from School.models import School,Student     #导入模型类

# 编写序列化器 继承的是serializers中的ModelSerializer
class SchoolSerializers(serializers.ModelSerializer):
    class Meta:
        #  model中School模型
        model = School
        #  字段映射'__all__'所有字段
        fields = '__all__'

class StudentSerializers(serializers.ModelSerializer):
    #  增加school_name 字段 用于读取学校名称
    #  自定义字段school_name 继承serializers中的SerializerMethodField
    #  (read_only=True) 只读
    school_name = serializers.SerializerMethodField(read_only=True)

    #  def定义school_name用get获取的方法  obj指具体的某一个对象
    # obj 类别组 模型类对象
    def get_school_name(self,obj):
        #  返回 obj对象中调用外键kind中的school_name字段 (学校表中school_name学校名称)
        return obj.kind.school_name

    class Meta:
        model = Student
        fields = '__all__'

12.子应用下文件配置,views.py创建视图

from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet     #导入ModelViewSet
from rest_framework.filters import SearchFilter,OrderingFilter     #导入过滤和排序
from School.models import School,Student      #导入模型类
from School.serializers import SchoolSerializers,StudentSerializers     #导入序列化器

# Create your views here.

# 继承ModelViewSet 实现对学校的增删查改
class SchoolView(ModelViewSet):
    queryset = School.objects.all()
    serializer_class = SchoolSerializers

class StudentView(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerializers

    # 导入过滤,排序功能
    filter_backends = [SearchFilter,OrderingFilter]
    # 过滤字段 通过过滤出的字段来查询
    search_fields = ['stu_name','hobby','kind__id']
    # 排序字段
    ordering_fields = ['score']

13.配置子路由

from django.urls import path
from rest_framework import routers    #导入routers
from School import views    # 导入views视图
urlpatterns = [

]
# 用routers生成路由对象 通过routers中的SimpleRouter()
router = routers.SimpleRouter()

# 用router.register生成路由信息
# 'school' 前面是路由,后面是给路由起的名字,中间调用views中SchoolView视图
router.register('school',views.SchoolView,'school')
router.register('stu',views.StudentView,'stu')

# 路由追加,上面urlpatterns += router.urls
urlpatterns += router.urls

14.后端配置完成,页面查看效果

(1)运行项目python manage.py runserver

(2)根据路由对应操作

1.admin/    #django管理路由
2.^school/$ [name='school-list']    # 学校信息路由

# 学校信息动态路由    
# 根据编号查询对应的学校信息
# 例:http://127.0.0.1:8000/school/1/
3.^school/(?P<pk>[^/.]+)/$ [name='school-detail']

4.^stu/$ [name='stu-list']    # 学生信息路由


# 学生信息动态路由  可以根据高级功能设定的字段进行过滤查找和排序展示
# 查询学生id为1 :http://127.0.0.1:8000/stu/1/
# 模糊查询学生姓名:http://127.0.0.1:8000/stu/?search=宋
# 查询学生所属学校,年龄降序展示 http://127.0.0.1:8000/stu/?search=1&ordering=-score
5.^stu/(?P<pk>[^/.]+)/$ [name='stu-detail']

15.创建前端code/vue项目

项目命令cmd:vue create +项目名

(1)选3  (2)空格勾选Router 和 Vuex  (3)选版本3  (4)输y  (5)选1  (6)输n

项目开始创建

15.2  运行项目命令 npm run serve

 16.配置跨域/code文件夹全局下创建vue.config.js文件

module.exports={
    devServer:{
        proxy:'http://127.0.0.1:8000/'
    }
}

17.1  安装axios 命令:npm install axios -- save

17.2  src目录下创建工具文件夹utils,在utils文件夹下创建文件request开始封装请求方法

import Axios from "axios"
export function put(url,params){
    return Axios.put(url,params)
}
export function del(url,params){
    return Axios.delete(url,params)
}
export function post(url,params){
    return Axios.post(url,params)
}
export function get(url,params){
    return Axios.get(url,params)
}

18.可有可无的操作:

1.路由router下注释不用的两个配置文件

2.视图views下删除多余的两个vue文件

3.导航栏app注释没用的导航标题

19.views文件夹下创建需要的几个视图文件 后缀名为.vue

1.视图vue文件中输入vue回车,模板的快捷方式

20.开始配置router文件中的路由

import School from '../views/School.vue'
import Stu from '../views/Stu.vue'
import Xin from '../views/Xin.vue'
const routes = [
  {
    path: '/',        # 视图的路由
    name: 'School',    # 视图路由的名字
    component: School    # 组件
  },
  {
    path: '/stu',
    name: 'Stu',
    component: Stu
  },
  {
    path: '/xin',
    name: 'Xin',
    component: Xin
  },
]

21.在APP.vue配置导航栏  (可有可无)

    <router-link to="/">学校页面</router-link> |
    <router-link to="/stu">学生页面</router-link> |
    <router-link to="/xin">排序页面</router-link>

22.开始编写views文件中的视图

(1)主表视图

<template>
  <p>学校页面</p>
    <table border="1" align="center">
        <tr>
            <th>编号</th>
            <th>学校名称</th>
        </tr>
        <tr v-for="(item,i) in SchList" :key="i">
            <td>{{item.id}}</td>
            <td>
                <router-link :to="{name:'Stu',params:{id:item.id}}">
                {{item.school_name}}
                </router-link>
            </td>
        </tr>
    </table>
</template>

<script>
import { get } from '@/utils/request'
export default {
    data(){
        return{
            SchList:[],
        }
    },
    mounted(){
        this.SchData();
    },
    methods:{
        SchData(){
            get('school/')
            .then((resp) => {
                console.log(resp)
                this.SchList = resp.data    
            }).catch((err) => {
                console.log(err)
            });
        }
    }
}
</script>

<style>

</style>

(2)从表视图

<template>
  <p>学生页面</p>
  <table border="1" align="center">
    <tr>
      <th>编号</th>
      <th>姓名</th>
      <th>爱好</th>
      <th>成绩</th>
      <th>学校名称</th>
      <th>操作</th>
    </tr>
    <tr v-for="(item,i) in StuList" :key="i">
      <td>{{item.id}}</td>
      <td>{{item.stu_name}}</td>
      <td>{{item.hobby}}</td>
      <td>{{item.score}}</td>
      <td>{{item.school_name}}</td>
      <td>
        <button @click="upd(i)">修改</button>
        <button @click="remove(item.id)">删除</button>
      </td>
    </tr>
  </table>
  <p>修改学生信息</p>
  编号:<input type="text" v-model="id"><br>
  姓名:<input type="text" v-model="stu_name"><br>
  爱好:<input type="text" v-model="hobby"><br>
  成绩:<input type="text" v-model="score"><br>
  学校名称:<select name="aa" v-model="kind">
    <option v-for="(item,i) in SchList" :key="i" :value="item.id">{{item.school_name}}</option>
  </select>
  <button @click="update">确认修改</button>
    <p>添加学生信息</p>
  姓名:<input type="text" v-model="stu_name2"><br>
  爱好:<input type="text" v-model="hobby2"><br>
  成绩:<input type="text" v-model="score2"><br>
  学校名称:<select name="bb" v-model="kind2">
    <option v-for="(item,i) in SchList" :key="i" :value="item.id">{{item.school_name}}</option>
  </select>
  <button @click="addData">确认添加</button>
  <p>根据 学生姓名 和 爱好 搜索学生信息</p>
  <input type="text" v-model="soudata">
  <button @click="sou">搜索</button>
  <p>{{SouList}}</p>
</template>

<script>
import { del, get, post, put } from '@/utils/request'
export default {
    data(){
      return{
        Sch_id : this.$route.params.id,
        StuList:[],
        SchList:[],
        SouList:[],
        soudata:'',
        id:0,stu_name:'',hobby:'',score:0,kind:0,
        stu_name2:'',hobby2:'',score2:0,kind2:0,
      }
    },
    mounted(){
      this.StuData();
      this.SchData();
    },
    methods:{
        SchData(){
        get('school/')
        .then((resp) => {
            console.log(resp)
            this.SchList = resp.data    
        }).catch((err) => {
            console.log(err)
        });
        },
      StuData(){
        let url = 'stu/?search=' + this.Sch_id
        get(url)
        .then((resp) => {
          console.log(resp)
          this.StuList = resp.data  
        }).catch((err) => {
          console.log(err)
        });
      },
      remove(id){
        let url = 'stu/' + id  + '/'
        del(url)
        .then((resp) => {
          console.log(resp)  
          alert('删除成功')
          this.StuData()
        }).catch((err) => {
          console.log(err)
        });
      },
      upd(i){
        this.id=this.StuList[i].id
        this.stu_name=this.StuList[i].stu_name
        this.hobby=this.StuList[i].hobby
        this.score=this.StuList[i].score
        this.kind=this.Sch_id
      },
      update(){
        let url = 'stu/' + this.id + '/'
        let obj = {id:this.id,stu_name:this.stu_name,hobby:this.hobby,score:this.score,kind:this.kind}
        put(url,obj)
        .then((resp) => {
          console.log(resp)
          alert('修改成功')  
          this.StuData()
        }).catch((err) => {
          console.log(err)
        });
      },
      addData(){
        let obj = {stu_name:this.stu_name2,hobby:this.hobby2,score:this.score2,kind:this.kind2}
        post('stu/',obj)
        .then((resp) => {
          console.log(resp)
          alert('添加成功')  
          this.StuData()
        }).catch((err) => {
          console.log(err)
        });
      },
      sou(){
        let url = 'stu/?search=' + this.soudata
        get(url)
        .then((resp) => {
          console.log(resp)  
          this.SouList = resp.data
        }).catch((err) => {
          console.log(err)
        });
      }
    }
}
</script>

<style>

</style>

(3)单独一个表,排序展示信息

<template>
  <table border="1" align="center">
    <tr>
      <th>编号</th>
      <th>姓名</th>
      <th>爱好</th>
      <th>成绩</th>
      <th>学校名称</th>
    </tr>
    <tr v-for="(item,i) in StuList" :key="i">
      <td>{{item.id}}</td>
      <td>{{item.stu_name}}</td>
      <td>{{item.hobby}}</td>
      <td>{{item.score}}</td>
      <td>{{item.school_name}}</td>
    </tr>
  </table>
</template>

<script>
import { get } from '@/utils/request'
export default {
    data(){
        return{
            StuList:[],
        }
    },
    mounted(){
        this.StuData()
    },
    methods:{
        StuData(){
            let url = 'stu/?ordering=score'
            get(url)
            .then((resp) => {
                console.log(resp)
                this.StuList = resp.data  
            }).catch((err) => {
                console.log(err)
            });
        },
    }

}
</script>

<style>

</style>

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值