ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luffy之前端页面,后端接口,CORS跨域请求

2022-02-18 22:33:39  阅读:176  来源: 互联网

标签:跨域 models 请求 luffy url CORS import path name


复习

# django 项目目录调整
	-想把app都统一放到一个文件夹下
    	-apps文件夹:切换到该文件夹执行 python ../../manage.py startapp app名字
        -配置文件有多个:开发环境,上线环境
        	-settings文件夹,创建 dev.py(原来的settings)   pro.py
            -django项目的启动,基于配置文件(配置文件中不能乱导入,可能会报错)
            -manage.py 中修改
            os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.dev')
        	-wsgi.py  中修改
            os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.pro')
        -libs文件夹:第三方模块,自己写的模块
        -utils文件夹:工具
        	-日志,全局异常,响应对象
        -项目根路径 scripts 文件夹,测试脚本
        -项目根路径 logs 文件夹,日志(日志要记录到文件中)
        -在配置文件中,想直接注册app名字就可以使用了(前提需要配置到环境变量里)
        	-配置到环境变量之后就可以,所以可以直接写
            -把apps路径加入到环境变量,小luffy路径也加入了
            -以后在py文件中,导入模块,选择有很多---》一般以最短路径导入
            -pycharm中,导入爆红,其实不错,把文件夹组成source root
            
# 配置日志
	-配置文件(字典),放到dev.py中
    -utils/logging---》
    	import logging
    	logger=getLogger('django')
    -以后要用,直接导入logger对象,对象.info或者对象.error
# 处理全局异常
	-drf的全局异常:统一返回格式
    -写一个函数common_exception_handler(exc, context)
    -exc:异常对象,context内会有request对象,view对象
    -执行一下原来的
    -一定要加日志:
     logger.error('系统错误:请求地址是:%s,请求的试图类是:%s,错误原因是:%s' % (path, view_name,str(exc)))
    -配置文件中配置
    
    
# 封装Response
	-以后返回对象时,咱们使用自己封装的(简化代码)
    -return APIResponse(token='')



# 前端配置
	-vue create luffy_front
    -app.vue ---》<router-view/>
   	-全局css,清除原有标签的格式---》main.js中引入
    -写了一个setting.js--->后端地址---》main.js
        import settings from "./assets/js/settings";
        Vue.prototype.$settings=settings
        
    -axios--->安装---》放到原型中
        import axios from "axios";
        Vue.prototype.$axios=axios
    -使用
    	this.$axios.get(this.$settings.base_url+'/home/')



# 魔法方法
	- __init__和__new__的区别
    	init:实例化类时候调用
        new:创建对象时调用  在init之前执行

今日内容

1 前台使用elementui,bootstrap,jQuery

# 使用饿了么UI
	-cnpm i element-ui -S
    -main.js中写入
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    Vue.use(ElementUI);
    
    
# bootstrap
    
    -cnpm install bootstrap@3
    -main.js中
    import 'bootstrap'
	import 'bootstrap/dist/css/bootstrap.min.css'
    
 # jq
	-cnpm install jquery
    -在项目根路径下新建:vue.config.js
    const webpack = require("webpack");
    module.exports = {
        configureWebpack: {
            plugins: [
                new webpack.ProvidePlugin({
                    $: "jquery",
                    jQuery: "jquery",
                    "window.jQuery": "jquery",
                    "window.$": "jquery",
                    Popper: ["popper.js", "default"]
                })
            ]
        }
    };
    -一定要重启

2 后台User模块,User表

# 补充:软件开发模式
	-bbs项目:瀑布开发模式
    	瀑布开发模式就好比是火箭发射,工作和任务是预先计划好的,启动之后调整和返回难度很大。
    -路飞项目:敏捷开发
		敏捷开发模式就像是汽车驾驶,有很多条路可以到达目的地,可以随时根据导航反馈的路况进行及时调整。这个调整过程称为“开发—测量—认知”的反馈循环。

# 用户表:使用auth 的user表,自定义user表
# 咱们用了auth的user表----》扩写一些字段
# 创建一个app   user 
	python ../../manage.py startapp user
# user  app的models中写表
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    mobile = models.CharField(max_length=11, unique=True)  # 唯一
    # 需要pillow包的支持
    icon = models.ImageField(upload_to='icon', default='icon/default.png')

    class Meta:
        db_table = 'luffy_user'  # 如果不配它,表名是  app名字_类名小写
        verbose_name = '用户表'  # 在admin中显示的表名
        verbose_name_plural = verbose_name  # 在admin中显示的表名,不配它会加个s

    def __str__(self):  # print(对象) 的时候,触发它的执行
        return self.username
    
 # 在配置文件中配置
	AUTH_USER_MODEL = "app名.表名"
	AUTH_USER_MODEL='user.user'
 # 迁移数据库
	python manage.py makemigrations
    python manage.py migrate
    
    
    
#### 注意:
	-如果是空项目,之前数据库没有表,这么做完全没问题
    -但如果你之前迁移过数据库,这样就不行了
    	-因为user表已经存在了
        -第一步:删库
        -第二部:删除迁移文件(所有app的迁移文件)
        -第三步:删除django内置app的迁移文件(auth和admin这个app下migrations)
        -第四步:从新迁移数据库
        python manage.py makemigrations
    	python manage.py migrate

        
        
# 进行media的配置 图片的配置
	##1 dev.py中
        MEDIA_URL = '/media/'  #luffy下的/media文件夹
        MEDIA_ROOT = os.path.join(BASE_DIR, 'media') #拼接上
    ## 2 开路由
    from django.views.static import serve
    from django.conf import settings    #用django的settings他会反射到自己写的MEDIA_ROOT
    urlpatterns = [
        #有名分组 
        path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT})
    ]

3 前台首页设计

组件化开发  写三个组件 分别是导航栏 轮播图 尾部 写在components
						Header Footer Banner

Header.vue

<template>
    <div class="header">
        <div class="slogan">
            <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p>
        </div>
        <div class="nav">
            <ul class="left-part">
                <li class="logo">
                    <router-link to="/">
                        <img src="../assets/img/head-logo.svg" alt="">
                    </router-link>
                </li>
                <li class="ele">
                    <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span>
                </li>
                <li class="ele">
                    <span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span>
                </li>
                <li class="ele">
                    <span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span>
                </li>
            </ul>

            <div class="right-part">
                <div>
                    <span>登录</span>
                    <span class="line">|</span>
                    <span>注册</span>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Header",
        data() {
            return {
                url_path: sessionStorage.url_path || '/',
            }
        },
        methods: {
            goPage(url_path) {
                // 已经是当前路由就没有必要重新跳转
                if (this.url_path !== url_path) {
                    this.$router.push(url_path);
                }
                sessionStorage.url_path = url_path;
            },
        },
        created() {
            sessionStorage.url_path = this.$route.path;
            this.url_path = this.$route.path;
        }
    }
</script>

<style scoped>

    .header {
        background-color: white;
        box-shadow: 0 0 5px 0 #aaa;
    }

    .header:after {
        content: "";
        display: block;
        clear: both;
    }

    .slogan {
        background-color: #eee;
        height: 40px;
    }

    .slogan p {
        width: 1200px;
        margin: 0 auto;
        color: #aaa;
        font-size: 13px;
        line-height: 40px;
    }

    .nav {
        background-color: white;
        user-select: none;
        width: 1200px;
        margin: 0 auto;

    }

    .nav ul {
        padding: 15px 0;
        float: left;
    }

    .nav ul:after {
        clear: both;
        content: '';
        display: block;
    }

    .nav ul li {
        float: left;
    }

    .logo {
        margin-right: 20px;
    }

    .ele {
        margin: 0 20px;
    }

    .ele span {
        display: block;
        font: 15px/36px '微软雅黑';
        border-bottom: 2px solid transparent;
        cursor: pointer;
    }

    .ele span:hover {
        border-bottom-color: orange;
    }

    .ele span.active {
        color: orange;
        border-bottom-color: orange;
    }

    .right-part {
        float: right;
    }

    .right-part .line {
        margin: 0 10px;
    }

    .right-part span {
        line-height: 68px;
        cursor: pointer;
    }

</style>

Footer.vue

<template>
    <div class="footer">
        <ul>
            <li>关于我们</li>
            <li>联系我们</li>
            <li>商务合作</li>
            <li>帮助中心</li>
            <li>意见反馈</li>
            <li>新手指南</li>
        </ul>
        <p>Copyright © luffycity.com版权所有 | 京ICP备17072161号-1</p>
    </div>
</template>

<script>
    export default {
        name: "Footer"
    }
</script>

<style scoped>

    .footer {
        width: 100%;
        height: 128px;
        background: #25292e;
        color: #fff;
    }

    .footer ul {
        margin: 0 auto 16px;
        padding-top: 38px;
        width: 810px;
    }

    .footer ul li {
        float: left;
        width: 112px;
        margin: 0 10px;
        text-align: center;
        font-size: 14px;
    }

    .footer ul::after {
        content: "";
        display: block;
        clear: both;
    }

    .footer p {
        text-align: center;
        font-size: 12px;
    }
</style>

Banner.vue

<template>
    <el-carousel :interval="4000" type="card" height="400px">
        <el-carousel-item v-for="item in 4" :key="item">
            <!--            <h3 class="medium">{{ item }}</h3>-->
            <img src="../assets/image/banner1.png" alt="">
        </el-carousel-item>
    </el-carousel>
</template>

<script>
    export default {
        name: "Banner",
        data() {

        },
        created() {

        }
    }
</script>

<style scoped>
    .el-carousel__item h3 {
        color: #475669;
        font-size: 14px;
        opacity: 0.75;
        line-height: 200px;
        margin: 0;
    }

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

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

    .el-carousel__item {
        height: 400px;
        /*min-width: 1200px;*/
    }

    .el-carousel__item img {
        height: 400px;
        margin-left: calc(50% - 1920px / 2);
    }
</style>

Home.vue

<template>
    <div class="home">
        <Header></Header>
        <Banner></Banner>
        <div class="course">
            <el-row>
                <el-col :span="6" v-for="(o, index) in 8" :key="o">
                    <el-card :body-style="{ padding: '0px' }" class="card">
                        <img src="https://img0.baidu.com/it/u=1396426037,2146632168&fm=253&fmt=auto&app=138&f=JPEG?w=631&h=500"
                             class="image">
                        <div style="padding: 14px;">
                            <span>崽种,瞅我</span>
                            <div class="bottom clearfix">
                                <time class="time">{{ currentDate }}</time>
                                <el-button type="text" class="button">别TM点</el-button>
                            </div>
                        </div>
                    </el-card>
                </el-col>
            </el-row>

        </div>
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
        <Footer></Footer>
    </div>
</template>

<script>
    import Header from "../components/Header";
    import Footer from "../components/Footer";
    import Banner from "../components/Banner";

    export default {
        name: 'Home',
        created() {
            // this.$axios.get(this.$settings.base_url + '/home/test2/').then(res => {
            //     console.log(res.data)
            // })

        },
        data() {
            return{
                currentDate: new Date()
            };

        },
        methods: {

        },
        components: {
            Header, Footer, Banner
        }

    }
</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
    }

    .course {
        margin-left: 20px;
        margin-right: 20px;
    }

    .card {
        margin: 30px;
    }
</style>

4 后台首页相关接口(轮播图图片的接口)

# 创建公共表 utils/nodels
from django.db import models

# 公共表
class BaseModel(models.Model):
    created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_time = models.DateTimeField(auto_now=True, verbose_name='最后更新时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    is_show = models.BooleanField(default=True, verbose_name='是否上架')
    orders = models.IntegerField(verbose_name='优先级')

    # 不让他在数据库创建表 ,不写这个迁移就会创建表
    class Meta:
        abstract = True  #写了这个虚拟表不生成
#创建home下的banner表,并添加自己的字段
from django.db import models

# Create your models here.


from utils.models import BaseModel


class Banner(BaseModel):
    title = models.CharField(max_length=16, unique=True, verbose_name='名称')
    image = models.ImageField(upload_to='banner', verbose_name='图片')
    link = models.CharField(max_length=64, verbose_name='跳转链接')  # 跳转地址
    info = models.TextField(verbose_name='详情')  # 也可以用详情表,宽高出处
    class Meta:
        db_table = 'luffy_banner'
        verbose_name_plural = '轮播图表'
    def __str__(self):
        return self.title
    
# 写一个方法
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner
from .Serializer import BannerSerializer
class BannerView(GenericViewSet,ListModelMixin):
    serializer_class =BannerSerializer
    queryset = Banner.objects.all().filter(is_delete=False,is_show=True)

#序列化类也要写
from .models import Banner
from rest_framework import serializers


class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ['title','image','link']

 #自动生成路由
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('banner', views.BannerView, 'banner')


urlpatterns += router.urls


5 跨域请求详解(重要)

# 如何保证自己的接口不被第三方调用


# 浏览器的安全策略:同源策略
	-请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
    -如果不一样浏览器上就会报错,这个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险
    -请求,服务的执行了,数据返回了,但是浏览器拦截掉了
    
    
# 解决同源策略导致的数据不能正常加载

# csrf 跨站请求伪造
# xss  跨站脚本攻击
# CORS:跨域资源共享---》后端技术(后端代码中加东西)---》通过它,就可以解决跨域问题
	-CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能
    
    -浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)
    	-如果请求满足以下两种情况,就是简单请求,否则就是非简单请求
        (1) 请求方法是以下三种方法之一:
            HEAD
            GET
            POST
        (2)HTTP的头信息不超出以下几种字段:
            Accept
            Accept-Language
            Content-Language
            Last-Event-ID
            Content-Type:只限于三个值urlencoded、form-data、text/plain
            
      	-简单请求发送一次请求,数据拿回来,但是被浏览器同源策略拦截了
        -非简单请求发送两次,一次options请求,如果允许再发真正的请求,如果不允许就不发了
        
     -通过跨域资源共享解决跨域
    	-简单请求解决:其实就是在响应头中加一些东西
            res=HttpResponse('ok')
            #请求头加参数
            res['Access-Control-Allow-Origin']='*'
            return res
        -非简单请求的解决,也是在响应头中加东西,中间件记得注释csrf   如果用drf不用
        	if request.method == 'OPTIONS':
                # res['Access-Control-Allow-Methods'] = 'DELETE,'
                res['Access-Control-Allow-Headers'] = 'Content-Type'
                
      -最好:写一个中间件,
        from django.utils.deprecation import MiddlewareMixin
        class CORSMiddle(MiddlewareMixin):
            def process_response(self, request, response):
                #逻辑判断
                if request.method == 'OPTIONS':
                    response['Access-Control-Allow-Methods'] = 'DELETE,'
                    response['Access-Control-Allow-Headers'] = 'Content-Type'
                response['Access-Control-Allow-Origin'] = '*'
                return response
            
       -配置在配置文件中 配置在中间件
            MIDDLEWARE = [
                'home.middleware.CORSMiddle'
            ]
    	
    
    
    
    
   # 使用第三方解决:
		1.-安装
		pip install django-cors-headers
        2.-注册:添加到setting的app中
        INSTALLED_APPS = (
                ...
                'corsheaders',
                ...
            )
        -加入到中间件
        'corsheaders.middleware.CorsMiddleware',
       	-配置文件配置
        #允许所有域
        CORS_ORIGIN_ALLOW_ALL = True
        CORS_ALLOW_METHODS = (
            'DELETE',
            'GET',
            'OPTIONS',
            'PATCH',
            'POST',
            'PUT',
            'VIEW',
        )
		#允许请求头多的东西
        CORS_ALLOW_HEADERS = (
            'XMLHttpRequest',
            'X_FILENAME',
            'accept-encoding',
            'authorization',
            'content-type',
            'dnt',
            'origin',
            'user-agent',
            'x-csrftoken',
            'x-requested-with',
            'Pragma',
            'token',
        )

标签:跨域,models,请求,luffy,url,CORS,import,path,name
来源: https://www.cnblogs.com/zhangshihu/p/15911475.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有