首页 > 其他分享 >03后台主页模块设计,simpleui后台管理,轮播图接口,跨域问题详解,前台主页功能

03后台主页模块设计,simpleui后台管理,轮播图接口,跨域问题详解,前台主页功能

时间:2023-06-19 19:33:28浏览次数:33  
标签:03 主页 models response path 后台 import data class

1 后台主页模块设计

# 1 创建后台主页模块(一个模块一个app)
python ../../manage.py startapp home

# 2 在models中写轮播图表
	-写一个基表BaseModel
    -写轮播图表
# 3 迁移
### BaseModel##########
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='优先级')

#from django.contrib.auth.models import AbstractUser
#在这个里面找
    class Meta:
        abstract = True  # 这个表模型只用来继承,不用来在数据库中生成表
##########Banner########
from django.db import models

from utils.common_models import BaseModel
class Banner(BaseModel):
    # 1 id  img图片地址        长传时间  是否删除 是否显示 order
    # 把公共字段抽取到某个基表中,以后要使用,直接继承基表,扩写自己的字段就可以了---》用过的AbstractUser就是这个原理
    title = models.CharField(max_length=16, unique=True, verbose_name='名称')
    image = models.ImageField(upload_to='banner', verbose_name='图片')
    # 点击图片,调整到的路径
    # 前端跳转的地址: 前端路由     完整的http链接
    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

2 simpleui后台管理

#下载
pip install django-simpleui

#配置
INSTALLED_APPS = [
      'simpleui',
    。。。
 
    
MEDIA_URL = 'media/'
# 以后所有的在meida文件夹下的资源自动拼接  media/
    
#admin注册
admin.site.register(Banner)
# 录入数据

# 正常在公司中,网站分主站和后台管理

# 后台管理,主要是运营录入数据,使用simpleui

3 轮播图接口

3.1 封装自己的mixin

from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
    RetrieveModelMixin
from utils.common_response import APIResponse


class CommonListModelMixin(ListModelMixin):
    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return APIResponse(data=res.data)


class CommonCreateModelMixin(CreateModelMixin):
    def create(self, request, *args, **kwargs):
        res = super().create(request, *args, **kwargs)
        return APIResponse(data=res.data)  # {code:100,msg:成功,data:{}}


class CommonUpdateModelMixin(UpdateModelMixin):
    def update(self, request, *args, **kwargs):
        res = super(CommonUpdateModelMixin, self).update(request, *args, **kwargs)
        return APIResponse(data=res.data)


class CommonRetrieveModelMixin(RetrieveModelMixin):
    def retrieve(self, request, *args, **kwargs):
        res = super(CommonRetrieveModelMixin, self).retrieve(request, *args, **kwargs)
        return APIResponse(data=res.data)


class CommonDestroyModelMixin(DestroyModelMixin):
    def destroy(self, request, *args, **kwargs):
        res = super().destroy(request, *args, **kwargs)
        return APIResponse(msg='删除成功')

3.2 轮播图接口

视图

# 查询所有 轮播图接口
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .serialzier import BannerSerializer
from .models import Banner
from utils.common_mixin import CommonListModelMixin as ListModelMixin


class BannerView(GenericViewSet, ListModelMixin):
    queryset = Banner.objects.all().filter(is_delete=False, is_show=True).order_by('orders')
    serializer_class = BannerSerializer

路由

## 总路由
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/home/', include('home.urls')),
    # static 默认开启的,后期咱们会开启media文件夹,除此之外的其它文件夹,尽量不要开放,让外部访问
    path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),

]

# 分路由
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
from .views import BannerView

router.register('banner', BannerView, 'banner')
urlpatterns = [
    # path('admin/', admin.site.urls),

]
urlpatterns += router.urls

序列化类

from rest_framework import serializers
from .models import Banner


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

3.3 自定义配置文件

# 通过配置文件控制显示多少条轮播图
# 使用步骤
    1 在settings下新建:common_settings.py
    2 在dev.py中加入
    from .common_settings import *
    3 在轮播图接口上
    class BannerView(GenericViewSet, ListModelMixin):
        queryset = Banner.objects.all().filter(is_delete=False, is_show=True).order_by('orders')[:settings.BANNER_COUNT]
        serializer_class = BannerSerializer

3 跨域问题详解

# 以后只要前后端分离项目,都会出现跨域问题,咱们要解决

# 同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现

请求的url地址,必须与浏览器上的url地址处于同域上:也就是[域名],[端口],[协议]相同.
http://127.0.0.1:8080
ftf://127.0.0.1:8080

比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据

浏览器上就会报错,个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险

请求发送,服务的执行,数据也正常返回,只是被浏览器拦截了

# 正因为同源策略的存在,咱们写前后端分离的项目,无法正常获取到数据


# 解决跨域问题:
	1  jsonp 跨域(不了解)
    2  跨域资源共享(CORS)  后端技术
    3  Nginx代理


# CORS:跨域资源共享
CORS需要浏览器和服务器同时支持,所有浏览器都支持该功能
只需要服务的处理即可:只需要在在响应头中加入固定的头就实现cors---》比如在响应头中加入Access-Control-Allow-Origin='*'---->get请求就没有跨域了---》但是put请求还会有


# cors的请求分两种
	-简单请求,浏览器直接发起
    -非简单请求,浏览器先发送要给options预检请求,服务端允许,再发送真正的请求
# 什么是简单请求,什么是非简单请求
	# 如果属于下面,就是简单请求
    1 请求方法是以下三种方法之一:
        HEAD
        GET
        POST
     2 HTTP的头信息不超出以下几种字段:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

        
# 使用cors解决跨域,就是再响应头中加入固定的一些东西,专门写个中间件
	    res['Access-Control-Allow-Headers'] = 'token'
        res['Access-Control-Allow-Methods'] = 'DELETE'
    	res['Access-Control-Allow-Origin'] = 'http://192.168.1.252:8080'





### 补充:######
前端访问的后端地址,一定要准确

3.0 自定义中间件,解决跨域问题

##### common_mideleware.py
from django.utils.deprecation import MiddlewareMixin


### 自定义中间件解决跨域问题---》以后其它框架都是这个原理---》django上有人做了
class CorsMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        if request.method == 'OPTIONS':
            response['Access-Control-Allow-Headers'] = 'token'
            response['Access-Control-Allow-Methods'] = 'DELETE'
        response['Access-Control-Allow-Origin'] = '*'
        return response
    
 ### 配置文件配置中间件
    MIDDLEWARE = [
        'utils.common_mideleware.CorsMiddleware'
    ]

3.1 django-cors-headers

####使用pip安装
pip install django-cors-headers
#####添加到setting的app中
INSTALLED_APPS = (
	...
	'corsheaders',
	...
)
#### 添加中间件
MIDDLEWARE = [  
	...
	'corsheaders.middleware.CorsMiddleware',
	...
]
#### 4、setting下面添加下面的配置
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'
)

3.2 django-cors-headers源码

# 核心代码再中间件的---》process_response  3.0.14 版本
class CorsMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        if (
            not conf.CORS_ALLOW_ALL_ORIGINS
            and not self.origin_found_in_white_lists(origin, url)
            and not self.check_signal(request)
        ):
            return response
        if conf.CORS_ALLOW_ALL_ORIGINS and not conf.CORS_ALLOW_CREDENTIALS:
            response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*"
        else:
            response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin
        if request.method == "OPTIONS":
            response[ACCESS_CONTROL_ALLOW_HEADERS] = ", ".join(conf.CORS_ALLOW_HEADERS)
            response[ACCESS_CONTROL_ALLOW_METHODS] = ", ".join(conf.CORS_ALLOW_METHODS) 
        return response

4 前台主页功能

4.1 Banner.vue

<template>
  <div>
    <el-carousel height="400px">
      <el-carousel-item v-for="item in banner_list" :key="item">
        <!--        router-link只能跳内部,不能跳外部-->

        <router-link :to="item.link" v-if="item.link.indexOf('http:')<0">
          <img :src="item.image" :alt="item.title">
        </router-link>
        <a :href="item.link" v-else>
          <img :src="item.image" :alt="item.title">
        </a>

      </el-carousel-item>
    </el-carousel>
  </div>
</template>

<script>
export default {
  name: "Banner",
  data() {
    return {banner_list: []}
  },
  created() {
    this.$axios.get(`${this.$settings.BASE_URL}home/banner/`).then(res => {
      this.banner_list = res.data.data
    })
  }
}
</script>

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


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

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

4.2 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>

4.3 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>

4.4 HomeView.vue

<template>
  <div class="home">
    <Header></Header>
    <Banner></Banner>
    <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 Banner from "@/components/Banner";
import Footer from '@/components/Footer'
import Header from "@/components/Header";

export default {
  name: 'HomeView',
  // created() {
  //
  //   this.$axios.get('http://127.0.0.1:8000/api/v1/home/test/', {
  //     headers: {
  //       token: 'sdfafasdf'
  //     }
  //
  //   }).then(res => {
  //     console.log(res.data.data)
  //   })
  // }

  components: {
    Header, Footer, Banner
  }

}
</script>

补充

# 表模型继承    ModelMixin  所有表模型都有to_dict,序列化用的
# 以后拿到表模型对象  序列化后的数据=banner.to_dict(a=['id','name'])
# 参照开源项目:https://gitee.com/openspug/spug

标签:03,主页,models,response,path,后台,import,data,class
From: https://www.cnblogs.com/whxx/p/17491997.html

相关文章

  • 智能风扇语音控制新方案,高品质语音识别芯片NRK3303
    随着人工智能技术的发展,人们可以使用语音助手随时随地进行语音控制电子设备。而针对风扇这种家居电器,智能语音控制的方案相对成熟,受到了越来越多用户的青睐。为了更好地提升用户体验,新一代智能风扇方案引进了语音识别芯片技术,使得用户可以更加方便地进行语音控制。语音识别芯片技......
  • 'utf-8' codec can't decode byte 0xbc in position 1182: invalid start byte
    2.如果是字符集出现错误,建议多选择几种字符集测试一下:选择的经验是:如果是爬取到的网页文件,可以查看网页文件的meta标签下的charset属性值。例如:<metacharset="UTF-8">1也可以使用notepad++打开,查看下右下角的部位,会指示该文件是那种编码。 用一个例子来演示会更加清晰......
  • centos下nginx使用Let's Encrypt 申请免费 SSL 证书
    应用场景:想使用https,但是又不想花钱购买证书,也不是阿里和腾讯的可以免费申请以下是具体操作步骤:1.配置DNS记录在申请二级域名SSL证书之前,需要先将该二级域名解析到您的服务器IP地址。2.安装Certbot:Certbot是Let’sEncrypt官方提供的工具,可用于自动化SSL证书的获......
  • Error creating bean with name 'sqlSessionFactory' defined in class path resource
    项目启动报错原因分析背景:system模块一个月未重启过,今天重启报数据源问题原因:这里报错的原因是数据源配置问题解决:数据源配置在nacos中,拿该模块的nacos数据源配置与项目启动成功的模块的数据源配置进行对比,检查出不同,改为一样即可......
  • 算法与数据结构Day03——平衡二叉树的根
    #include<stdio.h>#include<stdlib.h>typedefstructnode*AVLTree;structnode{intData;AVLTreeLeft;AVLTreeRight;};intHigh(AVLTreeT){if(!T)return0;intleft=High(T->Left)+1;intright=High(T->......
  • 20230308 java.util.ArrayList
    简介java.util.ArrayListList接口的可调整大小的数组实现。源码中对数组的操作非常精彩,值得学习数组一旦初始化长度就不可以发生改变数组结构特点增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置。查询快:由于数组在内存中是一块连续空间,因此可以根据地址......
  • itext生成PDF文件报错“Font 'STSong-Light' with 'UniGB-UCS2-H' is not recognized.
    最近需要写一个抽取表结构的工具,类似于powerdesigner中的表图,其中有一步用到了itext这个第三方jar包来生成pdf文件,碰到了一个问题,记录于此。问题描述:工程使用maven构建,pom.xml中对于jar包的定义如下:<dependency><groupId>com.lowagie</groupId><artifactId>itext</artifact......
  • 商城后台管理系统
    文件链接:https://files.cnblogs.com/files/blogs/738670/java.zip?t=1687147279&download=true    ......
  • Windows服务器定时重启设置教程 103.216.155.x
    Windows系统的任务计划程序,可以添加计划任务,设置任务开始时间及执行的间隔,实现应用的自动执行。例如:实现定时重启、关机等常见的功能。如何使用参考以下步骤1、新建一个文本文件,将文件后缀改为bat,然后添加如下代码shutdown-r-f-t 0该命令的作用是立即强制重启机器。在文件中单......
  • [AGC034E] Complete Compress
    [AGC034E]CompleteCompress考虑这道题之前,我们先想一个经典问题:对于一颗有根树,每个节点上可能放一颗棋子,且不同子树上的棋子可以相互抵消。那么,我们设maxson为最大子树包含的棋子数,sun【root】为root的所有子树的棋子总数,很容易得到,如果sum【root】-maxson>=maxson,那么它们一......