一、elemetu的使用,首页显示轮播图:

前端:首先创建vue,(前面已有vue安装方法,这里便不在叙述),只写相关的文件。(http://localhost:8080/
)

相关的url: http://element-cn.eleme.io/#/zh-CN/component/carousel

首先安装--->emement-ui

npm install element-ui

main.js(总的入口js)

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.prototype.$http = axios
Vue.config.productionTip = false
Vue.prototype.$url = 'http://127.0.0.1:8000/'  // 后台请求地址
Vue.use(ElementUI);
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

Home.vue

<template>
    <div class="home">
        <el-carousel :interval="5000" arrow="always" height="400px">
            <el-carousel-item v-for=" img in imgs">
                <img :src="img">
            </el-carousel-item>
        </el-carousel>
    </div>
</template>

<script>

    export default {
        data:function () {
            return {
                imgs:[]
            }
        },
        methods:{
            init:function () {
                let _this=this
                this.$http.request({
                    url:this.$url+'get_imgs/',
                    method:'get',
                }).then(function (response) {
                    _this.imgs=response.data
                })
            }
        },
        mounted:function () {
            this.init()
        }
    }
</script>
<style>
  .el-carousel__item h3 {
    color: #475669;
    font-size: 18px;
    opacity: 0.75;
    line-height: 300px;
    margin: 0;
  }

  .el-carousel__item:nth-child(2n) {
    background-color: #99a9bf;
  }

  .el-carousel__item:nth-child(2n+1) {
    background-color: #d3dce6;
  }
</style>

Course.vue

<template>
    <div class="about">
        <h1>课程</h1>
        {{course}}
        <p v-for="c in course">
            {{c}}
        </p>
        <button @click="init">点我</button>
    </div>
</template>

<script>
    export default {
        data: function () {
            return {
                course: ['python', 'linux'],
                name: 'this is test name'
            }
        },
        methods: {
            init: function () {
                let _this=this
                this.$http.request({
                    url: 'http://127.0.0.1:8000/course/',
                    method: 'get'
                }).then(function (response) {
                    _this.course(response.data)
                }).catch(function (response) {
                    console.log(response)
                })
            },
            test:function () {
                this.course=['about','dict',]
            }
        }
    }
</script>

<style scoped>

</style>

App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/course">课程</router-link>
    </div>
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Course from './views/Course'
Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    },
      {
      path: '/course',
      name: 'course',
      component: Course
    }
  ]
})


后端django:(http://127.0.0.1:8000/)

settings.py,并且在项目下创建media 目录,并放入图片3张

# 自定义中间件(作用:跨域访问),最后一段添加
# 中间件的应用名,文件名,类名。
MIDDLEWARE = ['app01.myMiddle.MyCorsMiddle']
增加图片走马灯的目录存放位置。
MEDIA_ROOT=os.path.join(BASE_DIR,'media')

app01/myMiddle.py

from django.utils.deprecation import MiddlewareMixin

class MyCorsMiddle(MiddlewareMixin):
    def process_response(self,request,response):
        # 简单请求:
        # 允许http://127.0.0.1:8001域向我发请求
        # ret['Access-Control-Allow-Origin']='http://127.0.0.1:8001'
        # 允许所有人向我发请求
        response['Access-Control-Allow-Origin'] = '*'
        if request.method == 'OPTIONS':
            # 所有的头信息都允许
            response['Access-Control-Allow-Headers'] = '*'
        return response

url.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
from django.views.static import serve
from django.conf import settings
# 添加:
url(r'^course/', views.course.as_view()),
url(r'^get_imgs/', views.img.as_view()),
url(r'^media/(?P<path>.*)', serve,{'document_root':settings.MEDIA_ROOT}),

views.py

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
class course(APIView):
    def get(self,request,*args,**kwargs):
        return Response(['python','linux'])

class img(APIView):
    def get(self,request,*args,**kwargs):
        return Response(['http://127.0.0.1:8000/media/1.jpg','http://127.0.0.1:8000/media/2.jpg','http://127.0.0.1:8000/media/3.jpg'])

测试访问:

http://localhost:8080/

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用成功。


二、课程列表接口,以及前端页面编写

后端

settings.py

INSTALLED_APPS=['rest_framework',] # 最后添加
MIDDLEWARE=['app01.myMiddle.MyCorsMiddle',]   # 最后添加
MEDIA_ROOT=os.path.join(BASE_DIR,'media')   # 给media 目录添加路由口

app01/myMiddle.py   # 跨域问题解决

from django.utils.deprecation import MiddlewareMixin

class MyCorsMiddle(MiddlewareMixin):
    def process_response(self,request,response):
        # 简单请求:
        # 允许http://127.0.0.1:8001域向我发请求
        # ret['Access-Control-Allow-Origin']='http://127.0.0.1:8001'
        # 允许所有人向我发请求
        response['Access-Control-Allow-Origin'] = '*'
        if request.method == 'OPTIONS':
            # 所有的头信息都允许
            response['Access-Control-Allow-Headers'] = '*'
        return response

models.py (sqlite3Python自带数据库,不用配置默认即可)

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericRelation

class Course(models.Model):
    """专题课程"""

    # category_choices = ((0, 'go'), (1, 'Python'), (2, 'Linux'))
    # category = models.SmallIntegerField(choices=category_choices, default=1)
    # category = models.ForeignKey(to='CourseCategory', to_field='nid',null=True)

    # unique=True 唯一性约束
    name = models.CharField(max_length=128, unique=True)
    course_img = models.CharField(max_length=255)
    brief = models.TextField(verbose_name="课程概述", max_length=2048)

    level_choices = ((0, '初级'), (1, '中级'), (2, '高级'))
    # 默认值为1 ,中级
    level = models.SmallIntegerField(choices=level_choices, default=1)
    pub_date = models.DateField(verbose_name="发布日期", blank=True, null=True)
    period = models.PositiveIntegerField(verbose_name="建议学习周期(days)", default=7)
    # help_text 在admin中显示的帮助信息
    order = models.IntegerField("课程顺序", help_text="从上一个课程数字往后排")

    status_choices = ((0, '上线'), (1, '下线'), (2, '预上线'))
    status = models.SmallIntegerField(choices=status_choices, default=0)
    # 用于GenericForeignKey反向查询,不会生成表字段,切勿删除
    price_policy = GenericRelation("PricePolicy")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "专题课"

class CourseDetail(models.Model):
    """课程详情页内容"""
    course = models.OneToOneField("Course", on_delete=models.CASCADE)
    hours = models.IntegerField("课时")
    # 课程的标语 口号
    course_slogan = models.CharField(max_length=125, blank=True, null=True)
    # video_brief_link = models.CharField(verbose_name='课程介绍', max_length=255, blank=True, null=True)
    # why_study = models.TextField(verbose_name="为什么学习这门课程")
    # what_to_study_brief = models.TextField(verbose_name="我将学到哪些内容")
    # career_improvement = models.TextField(verbose_name="此项目如何有助于我的职业生涯")
    # prerequisite = models.TextField(verbose_name="课程先修要求", max_length=1024)
    # 推荐课程
    # related_name 基于对象的反向查询,用于替换表名小写_set
    recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True)
    teachers = models.ManyToManyField("Teacher", verbose_name="课程讲师")

    def __str__(self):
        return "%s" % self.course

    class Meta:
        verbose_name_plural = "课程详细"

class PricePolicy(models.Model):
    """价格与有课程效期表"""
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)  # 关联course or degree_course
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    # course = models.ForeignKey("Course")
    valid_period_choices = ((1, '1天'), (3, '3天'),
                            (7, '1周'), (14, '2周'),
                            (30, '1个月'),
                            (60, '2个月'),
                            (90, '3个月'),
                            (180, '6个月'), (210, '12个月'),
                            (540, '18个月'), (720, '24个月'),
                            )
    valid_period = models.SmallIntegerField(choices=valid_period_choices)
    price = models.FloatField()
    class Meta:
        unique_together = ("content_type", 'object_id', "valid_period")
        verbose_name_plural = "价格策略"

    def __str__(self):
        return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)

class Teacher(models.Model):
    """讲师、导师表"""
    name = models.CharField(max_length=32)
    image = models.CharField(max_length=128)
    brief = models.TextField(max_length=1024)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "讲师"

迁移数据库

makemigrations

migrate

创建超级管理员

createsuperuser

密码:123456.com

admin.py

from django.contrib import admin
from app01 import models
# Register your models here.
admin.site.register(models.Course)
admin.site.register(models.Teacher)
admin.site.register(models.CourseDetail)
admin.site.register(models.PricePolicy)

打开:http://127.0.0.1:8000/admin/

输入用户与密码:

silence

123456.com

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_02

添加三门课程

django、go、linux

例如:

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_03

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_04

添加老师两名:

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_05

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_06

添加课程详细

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_07

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_08

添加价格策略

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_09

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_10

添加完课程后,编写接口

在app01应用下创建views 目录,并在下面创建course.py与img.py,并删除自带的views.py文件

urls.py(修改)

from django.conf.urls import url
from django.contrib import admin
from app01.views import course,img
from django.views.static import serve
from django.conf import settings
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^course/', course.Course.as_view()),
    url(r'^get_imgs/', img.Img.as_view()),
    url(r'^media/(?P<path>.*)', serve,{'document_root':settings.MEDIA_ROOT}),
]

序列化组件:app01/MySer.py

from rest_framework import serializers
from app01 import models

class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Course
        fields = ['id', 'name', 'course_img']

app01/utils/commonUtils.py (目录手动创建与文件)

class MyResponse():
    def __init__(self):
        self.status = 100
        self.msg = None

    @property
    def get_dic(self):
        return self.__dict__

app01/views/course.py

from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
from app01.MySer import CourseSerializer
from app01.utils.commonUtils import MyResponse
class Course(APIView):
    def get(self, request, *args, **kwargs):
        response = MyResponse()
        course_list = models.Course.objects.all()
        course_ser = CourseSerializer(instance=course_list, many=True)
        response.msg = '查询成功'
        response.data = course_ser.data
        return Response(response.get_dic)

app01/views/img.py

from rest_framework.views import APIView
from rest_framework.response import Response

class Img(APIView):
    def get(self, request, *args, **kwargs):
        return Response(['http://127.0.0.1:8000/media/1.jpg',
                         'http://127.0.0.1:8000/media/2.jpg',
                         'http://127.0.0.1:8000/media/3.jpg'])

也需要在

media/里面添加走马灯,课程图片与老师图片等。

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_11

前端:(vue)

src/views/About.vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
</template>

src/views/Course.vue

<template>
    <div class="course">
        <h1>课程</h1>
        <el-row>
            <el-col :span="8" v-for="cou in course">
                <el-card :body-style="{ padding: '0px' }">
                    console.log(cou.course_img)
                    <img :src="cou.course_img" class="image">
                    <div style="padding: 14px;">
                        <span>{{cou.name}}</span>
                        <div class="bottom clearfix">
                            <el-button type="text" class="button">
                                <router-link to="/courseDetail">操作按钮</router-link>
                            </el-button>
                        </div>
                    </div>
                </el-card>
            </el-col>
        </el-row>
    </div>
</template>-

<script>
    export default {
        data: function () {
            return {
                course: [],
                currentDate: new Date()
            }
        },
        methods: {
            init: function () {
                let _this = this
                this.$http.request({
                    url: 'http://127.0.0.1:8000/course/',
                    method: 'get'
                }).then(function (response) {
                    // _this.course(response.data)
                    console.log(response.data)
                    _this.course = response.data.data
                    console.log(_this.course)
                }).catch(function (response) {
                    console.log(response)
                })
            },
        },
        mounted: function () {
            this.init()
        }
    }
</script>
<style>
    .time {
        font-size: 13px;
        color: #999;
    }

    .bottom {
        margin-top: 13px;
        line-height: 12px;
    }

    .button {
        padding: 0;
        float: right;
    }

    .image {
        width: 100%;
        display: block;
    }

    .clearfix:before,
    .clearfix:after {
        display: table;
        content: "";
    }

    .clearfix:after {
        clear: both
    }
</style>

src/views/CourseDetail.vue

<template>
  <div class="CourseDetail">
    <h1>This is courseDetail</h1>
  </div>
</template>

src/views/Home.vue

<template>
    <div class="home">
        <el-carousel :interval="5000" arrow="always" height="400px">
            <el-carousel-item v-for=" img in imgs">
                <img :src="img">
            </el-carousel-item>
        </el-carousel>
    </div>
</template>

<script>

    export default {
        data:function () {
            return {
                imgs:[]
            }
        },
        methods:{
            init:function () {
                let _this=this
                this.$http.request({
                    url:this.$url+'get_imgs/',
                    method:'get',
                }).then(function (response) {
                    _this.imgs=response.data
                })
            }
        },
        mounted:function () {
            this.init()
        }
    }
</script>
<style>
  .el-carousel__item h3 {
    color: #475669;
    font-size: 18px;
    opacity: 0.75;
    line-height: 300px;
    margin: 0;
  }

  .el-carousel__item:nth-child(2n) {
    background-color: #99a9bf;
  }

  .el-carousel__item:nth-child(2n+1) {
    background-color: #d3dce6;
  }
</style>

src/App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/course">课程</router-link>
    </div>
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.prototype.$http = axios
Vue.config.productionTip = false
Vue.prototype.$url = 'http://127.0.0.1:8000/'
Vue.use(ElementUI);
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

src/router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Course from './views/Course'
import CourseDetail from './views/CourseDetail'
Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    },
      {
      path: '/course',
      name: 'course',
      component: Course
    },
      {
      path: '/CourseDetail',
      name: 'CourseDetail',
      component: CourseDetail
    },
  ]
})

验证:

http://localhost:8000/course/

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_12 http://localhost:8080/course

路飞项目二:elemetu的使用,首页显示轮播图_elemetu的使用_13

三:路由跳转携带数据,观察路由的变化