曹阳的博客 仅用于学习和分享

慕学在线教育平台-慕课

2020-02-04

慕学在线教育平台项目总结

项目简介

项目描述

  1. 项目名称:慕学在线教育平台项目
  2. 架构:前后端不分离MVT
  3. 成果:在线教育平台的后台管理,包括:搜索、排序、过滤、导出、自定义页面等功能,前台功能
  4. 开发周期:2019/02/04-2020/03/30
  5. 参考链接:Django+xadmin打造在线教育平台
  6. 所用技术:
    Python3.7
    Django2.2
    MySQL5.7
    xadmin
    redis
  7. 收获:

需求分析

  1. 在线教育系统

    数据库设计

    需求分析
    django的app设计
    自定义userprofile覆盖django自带的user表
    课程相关表设计
    课程机构相关表结构设计
    用户操作相关表结构设计

    登录和注册

    图片验证码
    账号和密码登录
    手机动态验证码登录
    手机号码注册
    表单验证
    通过session和cookie讲解登录原理

    课程机构管理模块

    课程机构列表页展示
    课程机构数据分页
    课程机构筛选
    课程机构排序
    ajax+modelform实现异步数据提交
    课程机构收藏
    课程机构详情页展示
    机构经典课程展示
    热门机构推荐

    课程管理模块

    课程列表页
    课程数据分页
    课程筛选
    热门课程推荐
    课程详情页展示
    课程收藏
    相关课程推荐
    学习过该课程的同学还学习过的其他课程
    课程评论
    view的权限控制
    视频播放页面
    通过阿里云oss管理视频文件
    课程章节信息展示

    讲师管理模块

    讲师列表页
    讲师详情展示
    讲师的课程展示
    讲师分享功能

    个人中心管理模块

    个人信息展示
    个人信息修改
    头像修改
    密码修改
    手机号码修改
    学习的课程展示
    我的收藏 - 课程机构、讲师、课程
    全局消息和个人消息

    首页和全局管理模块

    首页信息展示
    首页轮播图展示
    全局搜索功能
    自定义用户验证接口
    自定义全局错误页面(404, 403, 500)

  2. 后台管理系统(xadmin)

    表的增、删、改、查和过滤的快速配置
    自定义xadmin的全局信息
    自定义xadmin的各种主题功能
    自定义详情页面的布局
    django自带的组和权限管理配置
    自定义编辑和修改页面的表单
    不同用户进入列表页面的数据过滤
    重载数据修改后的逻辑控制
    同一张表的不同数据使用不同的管理器管理
    将图片显示在列表页
    配置只读,排除和默认排序字段
    修改不同的表的图标展示
    使用inline在一个表显示多个表的数据
    让讲师可以登录后台系统并过滤数据
    集成ueditor富文本编辑功能到xadmin中
    配置xadmin的导出功能(可以只导出选择的数据)
    配置xadmin的导入功能(可以导入各种格式的数据)

开发过程

创建虚拟环境

  1. 方式1
    makevirtualenv -p C:\Users\caoyang\AppData\Local\Programs\Python\Python37\python.exe mxonline(报错)
    新建的虚拟环境默认放在C:Users/caoyang/Envs
  2. 方式2
    python -m venv mxonline
    在哪个文件夹下创建虚拟环境就在哪个文件夹下,我用的这种方式,但是后来发现上面的方式更好
  3. 安装Django
    pip install django==2.2 -i https://pypi.douban.com/simple
    Django会默认依赖一些第三方的包,如sqlparse,pytz

新建项目

  1. 直接在在pycharm中新建Django项目 在pycharm中新建Django项目

  2. 使用命令新建项目和应用
    新建项目django-admin startproject MxOnline 新建应用python manage.py startapp courses
    新建应用后需要在settings.py文件中的INSTALLED_APPS添加'apps.courses.apps.CoursesConfig',
  3. 目录结构
    目录结构

    其实最好不要最外层目录,把文档和环境直接放到项目中去,否则不能debug

  4. 包文件

     pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
    
     Django              2.2  
     mysqlclient
     pillow
    
    

配置一个HTML页面显示的步骤

  1. 配置url
  2. 配置对应的views逻辑
  3. 拆分静态文件(css,js,image)放入到static,html放到template之下
    可以放到对应的app下面static
    也可以放入全局的static(推荐这种)
  4. 配置全局的static文件访问路径

     STATICFILES_DIRS = [
         os.path.join(BASE_DIR, 'static'),
     ]
    

数据库相关操作

  1. 新建数据库mxonline
    字符集utf8 -- UTF-8 Unicode
    排序规则utf8_general_ci
  2. 配置mysql引擎

     DATABASES = {
         'default': {
             'ENGINE': 'django.db.backends.mysql',
             'NAME': "mxonline",
             'USER': "root",
             'PASSWORD': "Mm123456",
             'HOST': "localhost"
         }
     }
    
  3. 安装mysql驱动
    访问Unofficial Windows Binaries for Python Extension Packagesmysqlclient,下载python3.7 64位版本(这个版本是python的版本,不是操作系统的版本)
    进入下载目录,进入虚拟环境pip install mysqlclient-1.4.2-cp37-cp37m-win_amd64.whl(其实可以直接安)
  4. 生成Django自带的表
    makemigration迁移文件
    migrate生成数据表
    只要models.py改了就要重新迁移
  5. 在models.py设计表
    __str__()函数是当我们print这个类的对象的时候,字符串的描述是什么,return的值必须是存在的
    像性别这种可选范围的可以使用choices参数
    upload_to="course/%Y/%m"参数可以设置文件保存路径
    设置默认当前时间default=datetime.now,now后面一定不能有括号,否则就直接调用了
    所有表中都有的字段可以放到BaseModel(放在最底层users的model类中)中去,为了不让BaseModel生成一张表,要在它的Meta中设置abstract = True
    时长要精确到分钟数
    外键必须指明on_delete,on_delete=models.CASCADE级联删除,on_delete=models.SET_NULL设为空值(必须有null=True,blank=True)
    from django.contrib.auth import get_user_model可以得到UserProfile来自哪一个class(自定义的还是Django自带的)
    多对多关系先设计成一对多的
  6. 数据库操作
    queryset:1.进行for循环 2.进行切片
    queryset本身并没有执行SQL操作,delete进行删除操作
    print(查询结果.query)可以查对应的SQL语句
    get()方法返回的是一个对象,不是queryset,进行数据操作,数据不存在或有多条数据存在会抛出异常xxx matching query dose not exist
    save()存在则更新,不存在则保存
  7. 从前端提取数据并保存到数据库中

     <form action="" method="post">
         <input type="text" name="message">
         <input type="submit" class="button" value="提交"/>
         { %  c s r f _ t o k e n  % }
     </form>
    
     if request.method == "POST":
         message_text = request.POST.get("message","")  # message是表单里的name
         message = Message()  # message是数据库对象,变量名不能与对象名重复
         message.message = message_text  # 第二个message是数据库中的字段
         message.save()
         return render(request,"message_form.html",{
             "message":message
         })
    
  8. Django的template数据展示

     if request.method == "GET":
         var_dict = {}
         all_messages = Message.objects.filter()
         if all_messages:
             message = all_messages[0]
             var_dict = {
                 "message":message
             }
         return render(request,"message_form.html",var_dict)
    

后台开发

自定义UserProfile覆盖Django默认的user表

  1. from django.contrib.auth.models import AbstractUser导入django自带的user类
  2. 在settings.py文件中设置AUTH_USER_MODEL="users.UserProfile",此时还需要安装
  3. pip install pillow

通过admin搭建后台管理系统

  1. settings.py的INSTALLED_APPS中一定要有'django.contrib.admin',
  2. 总路由中的urlpatterns中加入path('admin/', admin.site.urls),
  3. 修改语言设置

     LANGUAGE_CODE = 'zh-Hans'
     TIME_ZONE = 'Asia/Shanghai'
     USE_I18N = True
     USE_L10N = True
     USE_TZ = False
    
  4. 在users的admin.py中注册表

     from django.contrib import admin
     from django.contrib.auth.admin import UserAdmin  # 密码加密用的
     from apps.users.models import UserProfile
    
     class UserProfileAdmin(admin.ModelAdmin):
         pass
     #用户表和用户管理表关联注册
     #admin.site.register(UserProfile, UserAdmin)
    
  5. 在users的apps.py中把app的名称改成中文

     from django.apps import AppConfig
    
     class UsersConfig(AppConfig):
         name = 'apps.users'
         verbose_name = "用户"
    

xadmin的配置步骤

  1. 下载xadmin源码,放到项目根目录之下
  2. 在settings的INSTALLED_APPS中添加crispy_formsxadmin.apps.XAdminConfig
  3. 安装xadmin的依赖包(在xadmin的requirements.txt里面)
  4. 通过migrate生成xadmin需要的表
  5. 在urls中配置访问地址path('xadmin/', xadmin.site.urls),

xadmin的使用

  1. xadmin的全局配置

     class GlobalSettings(object):
         site_title = "慕学后台管理系统"
         site_footer = "慕学在线网"
         #menu_style = "accordion"  # 侧边栏收起
    		
     class BaseSettings(object):
         #切换换主题的
         enable_themes = True
         use_bootswatch = True
    		
     xadmin.site.register(xadmin.views.CommAdminView, GlobalSettings)
     xadmin.site.register(xadmin.views.BaseAdminView, BaseSettings)
    
  2. xadmin搭建后台管理系统

     import xadmin
     from apps.courses.models import Course
     from xadmin.layout import Fieldset, Main, Side, Row
    	
     class LessonInline(object):
         model = Lesson  #章节表
         style = "tab"  #左右切换
         extra = 0  #不自动新建
         exclude = ["add_time"]  #去除
    	
     class CourseResourceInline(object):
         model = CourseResource
         style = "tab"
         extra = 1  #自动新建一个tab
    		
     #自定义课程,还需要在INSTALLED_APPS中加入import_export,把xadmin/plugins/__init__.py中的'export'注释掉
     from import_export import resources
     class MyResource(resources.ModelResource):
         class Meta:
             model = Course
             #fields = ('name', 'description',)
             #exclude = ()
    	
     class NewCourseAdmin(object):
         #设置列表页样式
         import_export_args = {'import_resource_class': MyResource, 'export_resource_class': MyResource}  #数据的导入和导出
         list_display = ["name", "desc", "show_image", "go_to", "detail", "degree", "learn_times", "students"]  #列表页显示的字段
         search_fields = ["name", "desc", "detail", "degree", "students"]  #搜索字段
         list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]  #过滤字段,对于外键的过滤用双下划线
         list_editable = ["desc", "degree"]  #列表页可编辑字段
         readonly_fields = ["click_nums", "students", "add_time"]  # 只读字段
         #exclude = [ "fav_nums"]  # 去除字段,和其他字段不要冲突
         ordering = ["-click_nums"]  # 列表页默认排序
         model_icon = 'fa fa-paper-plane'  # 图标去http://www.fontawesome.com.cn/faicons/
         inlines = [LessonInline, CourseResourceInline]  #新增课程,下面可直接新增章节和资源
         style_fields = {
             "detail":"ueditor"
         }
    
         #只返回当前用户的数据
         #在Teacher表中添加一个字段
         #from apps.users.models import UserProfile
         #class Teacher(BaseModel):
         #	user = models.OneToOneField(UserProfile,on_delete=models.SET_NULL,null=True,blank=True,verbose_name="用户")
         def queryset(self):
             qs = super().queryset()  #默认所有数据
             if not self.request.user.is_superuser:
                 qs = qs.filter(teacher=self.request.user.teacher)
             return qs
    
         #自定义页面布局
         def get_form_layout(self):
             if self.org_obj:  # 设置编辑页面是自定义样式,新增是默认的
                 self.form_layout = (
                     Main(
                         #一个Fieldset就是一块
                         Fieldset("讲师信息",
                                  'teacher', 'course_org',
                                  css_class='unsort no_title'
                                  ),
                         Fieldset("基本信息",
                                  'name', 'desc',
                                  Row('learn_times', 'degree'),
                                  Row('category', 'tag'),
                                  'youneed_know', 'teacher_tell', 'detail'
                                  ),
                     ),
                     Side(
                         Fieldset("访问信息",
                                  'fav_nums', 'click_nums', 'students', 'add_time'
                                  )
                     ),
                     Side(
                         Fieldset("选择信息",
                                  'is_banner', 'is_classics'
                                  )
                     ),
                 )
             return super(NewCourseAdmin, self).get_form_layout()
    			
     xadmin.site.register(Course, NewCourseAdmin)
    
  3. 重载save_models方法控制保存和修改数据的逻辑

     class UserCourseAdmin(object):
         list_display = ["user", "course", "add_time"]
         search_fields = ["user", "course"]
         list_filter = ["user", "course", "add_time"]
    
         #用户学习一门课程,课程的学习人数加一
         def save_models(self):
             obj = self.new_obj  #新增一条记录是会生成一个对象,当前并没有保存到数据库中
             if not obj.id:  #没有id的时候是新增
                 obj.save()
                 course = obj.course
                 course.students += 1
                 course.save()
    
  4. 同一张表的不同数据使用不同的管理器进行管理

     #在models.py中新建轮播课程的model类
     class BannerCourse(Course):
         class Meta:
             verbose_name = "轮播课程"
             verbose_name_plural = verbose_name
             proxy = True  # 多个管理器管理一张表,不新增一张表
    			
     #在adminx.py中管理轮播课程
     from apps.courses.models import BannerCourse
    	
     class BannerCourseAdmin(object):
         list_display = ["name", "desc", "detail", "degree", "learn_times", "students"]
         search_fields = ["name", "desc", "detail", "degree", "students"]
         list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]
         list_editable = ["desc", "degree"]
    
         def queryset(self):
             qs = super().queryset()
             qs = qs.filter(is_banner=True)
             return qs
    			
     xadmin.site.register(BannerCourse, BannerCourseAdmin)
    
  5. 通过在model中定义方法将图片显示在列表页

     #显示图片而不是路径,list_display中加入show_image
     def show_image(self):
         from django.utils.safestring import mark_safe
         return mark_safe("<img src='{}'>".format(self.image.url))
     show_image.short_description = "图片"
    
     #添加链接,list_display中加入go_to
     def go_to(self):
         from django.utils.safestring import mark_safe
         return mark_safe("<a href='/course/{}'>跳转</a>".format(self.id))
     go_to.short_description = "跳转"
    

DjangoUediter富文本编辑器

  1. 将djangoueditor源码拷贝到项目根目录下
  2. INSTALLED_APPS 中配置 ‘DjangoUeditor’
  3. 配置相关的url:
    url(r’^ueditor/’,include(‘DjangoUeditor.urls’)),
  4. 修改相关models.py
    detail = UEditorField(verbose_name="课程详情", width=600, height=300, imagePath="courses/ueditor/images/",filePath="courses/ueditor/files/", default="")
  5. 下载ueditor插件并放置到xadmin源码的plugins目录下
  6. 将editor文件名配置到plugins目录下的__init__.py文件的PLUGINS变量中
  7. 在对应的model的管理器adminx.py中配置:

     style_fields = {
         "detail":"ueditor"
     }
    

    detail表示model中富文本的字段

  8. 前端接收时用{ % autoescape off % }{ { course.detail } }{ % endautoescape % }
  9. 文档看 https://github.com/zhangfisher/DjangoUeditor

前台开发

通过Django内置的login和logout完成账号登录和退出登录

  1. 登录逻辑

    账号登录

  2. views.py代码实现

     from django.shortcuts import render  #返回HTML页面
     from django.views.generic.base import View  #所有视图函数都继承View
     from django.contrib.auth import authenticate, login, logout  #authenticate判断用户是否存在
     from django.http import HttpResponseRedirect, JsonResponse  #返回HTML页面
     from django.urls import reverse  #重定向
     from apps.users.forms import LoginForm  #登录注册表单验证
    
     #退出登录
     class LogoutView(View):
         def get(self, request, *args, **kwargs):
             logout(request)
             return HttpResponseRedirect(reverse("index"))
    
     class LoginView(View):	
         def get(self, request, *args, **kwargs):
             #判断用户是否登录
             if request.user.is_authenticated:
                 return HttpResponseRedirect(reverse("index"))
             next = request.GET.get("next", "")
    			
         def post(self, request, *args, **kwargs):
             #表单验证,实例化LoginForm
             login_form = LoginForm(request.POST)
             banners = Banner.objects.all()[:3]
             if login_form.is_valid():
                 #获取用户名和密码
                 #user_name = request.POST.get("username", "")
                 #password = request.POST.get("password", "")
                 #验证字段,放到forms.py中避免代码冗余
                 user_name = login_form.cleaned_data["username"]
                 password = login_form.cleaned_data["password"]
                 #用于通过用户名和密码查询用户是否存在
                 user = authenticate(username=user_name, password=password)
                 #1.只通过用户名查找用户不对,还得密码校验
                 #2.需要先加密再通过加密后的密码查询,扩展性不好
                 #from apps.users.models import UserProfile
                 #user = UserProfile.objects.get(username=user_name, password=password)
    
                 if user is not None:
                     #查询到用户
                     login(request, user)
                     #登录成功之后应该怎么返回页面
                     next = request.GET.get("next", "")
                     if next:
                         return HttpResponseRedirect(next)
                     return HttpResponseRedirect(reverse("index")) #reverse重定向,如果用render的话路由还是login
                 else:
                     #未查询到用户
                     return render(request, "login.html", {"msg": "用户名或密码错误", "login_form": login_form, "banners": banners})
             else:
                 return render(request, "login.html", {"login_form": login_form, "banners": banners})
    
  3. forms.py代码实现

     from django import forms #所有表单都需要继承form里的Form类
    
     class LoginForm(forms.Form):
         #账号密码登录
         #required=True是否为必填字段,字段名必须与input的name属性保持一致
         username = forms.CharField(required=True, min_length=2)
         password = forms.CharField(required=True, min_length=3)
    

动态验证码登录

常见web攻击

SQL注入攻击

  1. SQL注入攻击的危害 非法读取、篡改、删除数据库中的数据
    盗取用户的各类敏感信息,获取利益
    通过修改数据库来修改网页上的内容
    注入木马
  2. SQL注入攻击与防范示例

     import MySQLdb
    
     username = "' OR 1=1 #"  #井号在SQL语句中是注释的意思,相当于username='' or 1=1,所以无论密码是什么都可以查到数据
     password = "pbkdf2_sha256$150000$rHVW33UGSs2H$Ld3gPBExyTeglCWFxTbDYlNs0E98Dp8jStusgZQak1s="
     conn = MySQLdb.connect(host="127.0.0.1", user="root", passwd="Mm123456", db="mxonline", charset="utf8")  #建立连接
     cursor = conn.cursor()
     sql = "select * from users_userprofile where username='{}' and password='{}'".format(username,password)
     #print(sql)
     cursor.execute(sql)  #执行SQL语句
     for row in cursor.fetchall():
         print(row)
    
  3. 防护措施
    表单验证
    查询用户的逻辑
    django的orm会对特殊字符转义, orm会确保用户输入数据的安全性

xss攻击原理及防范

  1. xss跨站脚本攻击(Cross Site Scripting)的危害
    盗用各类用户账号,如用户网银账号/各类管理员账号
    盗窃企业重要的具有商业价值的资料
    非法转账
    控制受害者机器向其他网站发起攻击,注入木马等
  2. xss攻击的流程

    csrf攻击原理 csrf攻击原理

  3. 防护措施
    首先代码里对用户输入的地方和变量都需要仔细检查长度和对<>;'等支付做过滤
    避免直接在cookie中泄露用户隐私,例如email/密码登,通过是cookie和系统IP绑定来降低cookie泄露后的危险
    尽量采用POST而非GET提交表单

csrf攻击与防范

  1. csrf跨站请求伪造(Cross-site request forgery)的危害
    以你名义发送邮件
    盗用你的账号
    购买商品
    虚拟货币转账
  2. csrf攻击原理

    csrf攻击原理

  3. 防护措施:在form里加上{ % c s r f _ t o k e n % }

难点

  1. 数据库设计,避免循环引用 分层设计:上层可以引用下一层,下层不能引用上一层,层级之间可以互相引用

    分层设计

    ER图

常识

  1. xadmin中方法前有个@filter_hook的都可以重载
  2. 文件重命名时选中Search for references其他引用的地方都会相应修改
  3. from django.views.generic import TemplateView,调用它的as_view()方法可以不用写后台的方法直接返回页面

     from django.urls import path
     from django.views.generic import TemplateView  # 不用写后台方法的类
     urlpatterns = [
         #所有的View类都有一个as_view()方法,调用这个方法之后就会产生一个def,就像我们自己定义的方法, 想返回一个HTML的话就配置个template_name="index.html"参数
         path('', TemplateView.as_view(template_name="index.html"), name="index"),
    
  4. 配置静态文件

     #在settings.py中配置
     STATIC_URL = '/static/'
     #自定义 不能和STATIC_ROOT同时存在
     STATICFILES_DIRS = [
         os.path.join(BASE_DIR, 'static'),
     ]
     #上传文件都放到media里
     MEDIA_URL = "/media/"
     MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
     #STATIC_ROOT = os.path.join(BASE_DIR, 'static') #上线时取消注释
    	
     #一定要配置总路由
     from Mxonline.settings import MEDIA_ROOT
     from django.views.static import serve
     urlpatterns = [
         # 配置上传文件的访问url
         url(r'^media/(?P<path>.*)$', serve, {"document_root": MEDIA_ROOT}),
     ]
    	
     在HTML文件中导入静态文件用`"{ % static 'css/style.css' % }"`或`"/static/css/style.css"`,推荐第一种  
     导入服务器上传的静态文件用`{ { course.image.url } }`或`{ { MEDIA_URL } }{ { course.image } }`,推荐第一种
    
  5. { % if user.is_authenticated % }判断用户是否已经登录
    settings.py中TEMPLATES -> ‘OPTIONS’ -> ‘context_processors’里面是所有页面中都应传入的全局变量,所以HTML中可以直接拿到request和user等
    通过看有没有sessionid判断登录状态

bug

Django版本问题

批注掉就完了


django2.2/mysql ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3


django报错:render() got an unexpected keyword argument ‘renderer’

注销模型

错误原因:UserProfile模型跟系统的冲突了,但是我自定义了显示的列,所以就要重新关联,关联之前要把系统的注销掉,如果类内部用默认的可以不用注册

解决方案:‘The model %s is already registered’ % model.name) xadmin.sites.AlreadyRegistered: The model Us

import xadmin
from .models import UserProfile
#xadmin中这里是继承object,不再是继承admin
class UserProfileAdmin(object):
    '''
    管理员信息
    '''
    #显示的列
    list_display = ['nick_name', 'birthday', 'gender', 'address','mobile','image','add_time']
    #搜索的字段,不要添加时间搜索
    search_fields = ['nick_name', 'birthday', 'gender', 'address','mobile']
    #过滤
    list_filter = ['nick_name', 'birthday', 'gender', 'address','mobile']

#将管理器与model进行注册关联
xadmin.site.unregister(UserProfile)
xadmin.site.register(UserProfile, UserProfileAdmin)

安装mysql驱动

解决“raise ValueError(“Dependency on app with no migrations: %s” % key[0]) ValueError: Dependency on ”

windows系统Django字符集错误

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xa6 in position 9737: ill….

admin密码是明文

注册的时候加个它from django.contrib.auth.admin import UserAdmin # 密码加密用的,然后用户表和用户管理表关联注册admin.site.register(UserProfile, UserAdmin)

get方法访问对象报xxx matching query dose not exist

原因:数据不存在或有多条数据
解决方法:
try: message = Message.objects.get(name="bobby1") except Message.DoesNotExist as e: pass except Message.MultipleObjectsReturned as e: pass

The view xxx didn’t return an HttpResponse object.’

view中任何一个代码分支下都要render一个页面,POST方法也得返回

新增用户报错Duplicate entry ‘’ for key ‘mobile’

原因: django自带的新增用户只有用户名,密码和确认密码,但是用户表里mobile列设置了唯一约束,默认为空,创建超级用户的时候手机号默认为空了,后面再创建用户手机号就不能为空了
解决方法:把唯一约束去掉,或者修改django源码(不推荐)

导入静态文件路径static前必须有/

<link rel="stylesheet" type="text/css" href="/static/css/style.css">
/staticsettings.py文件中的STATIC_URL = '/static/'是对应的

如果不加/,浏览器就会把/static/css/style.css当成路由去解析成http://127.0.0.1:8000/static/css/style.css就会报404

图片验证码

GitHub搜django simple captcha

Redis缓存

去GitHub上搜redis Windows

下载redis-latest.zip后解压,进入文件夹运行redis-server.exe启动服务,再打开一个命令行运行redis-cli.exe连接服务

redis驱动

redis.exceptions.ConnectionError: Error 10061 connecting to 127.0.0.1:6379. 由于目标计算机积极拒绝,无法连接。 Redis服务没开

不能根据add_time排序

add_time统一写到user的models.py里面了,需要导入并继承BaseModel

视频播放不了

可能是因为model类中视频路径字段长度不够,给截断了

405错误

浏览器请求的方法错误,检查视图函数中get方法和post方法使用是否正确

其他错误

Django Xadmin站点管理配置

Django使用Ueditor

Django2.2.4安装xadmin步骤

解决“raise ValueError(“Dependency on app with no migrations: %s” % key[0]) ValueError: Dependency on ”

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xa6 in position 9737: ill….

“CSRF token missing or incorrect.”的解决方法.

分页


Similar Posts

下一篇 疫情地图

Content