zoukankan      html  css  js  c++  java
  • Django项目BBS博客论坛

    BBS 项目开发逻辑梳理

    第一步:先进行数据库设计

    数据库设计规则是:
    	1.先创建基表:用户表、站点表、文章表、标签表、分类表、文章2标签第三张关系表、点赞点踩表、评论表
        2.书写表中的基本含有的字段
        3.添加外键(一对一,一对多,多对多)
        4.第三张关系表
    注意事项:创建外键关系的时候,to='表名',不要忘记引号,null=true,并不是所有的外键都加的
    

    第二步settings配置

    一定要进行settings的相关配置:
    	1.数据库配置
        DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'bbszikao',
            'USER':'root',
            'PASSWORD': 'root',
            'HOST':'127.0.0.1',
            'PORT':3306,
            'CHARSET':'utf8'
        }
    }
    	
        2.静态文件资源配置
        STATICFILES_DIRS=[
            os.path.join(BASE_DIR,'static')
        ]
        
        3.models.py文件中,用户表继承AbstractUser类,需要对其进行settings配置
        from django.contrib.auth.models import AbstractUser
        配置auth模块的访问:
        AUTH_USER_MODEL='app01.Userinfo'
        
        4.静态图片资源settings配置+urls路由访问配置,暴露给用户查看,用户注册可以访问到默认头像
        #settings文件配置:
        MEDIA_ROOT=os.path.join(BASE_DIR,'media')
        #urls文件访问头像路由配置
        url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    

    第三步功能开发

    注册功能

    后端开发逻辑:
    分为:register函数+register.html+myform.py文件
    后端开发逻辑:
    # myform.py 文件
    	1.建立myform.py文件,利用forms表单,提交注册的数据信息
        创建class MyRegForm(forms.Form):类
            用户名,密码,确认密码,邮箱
        建立局部钩子函数校验用户名是否存在
        建立全局钩子函数校验密码是否一致
    # models.py 文件    
        2.把myform文件中的MyRegForm表单对象拿到,
        然后把form_obj对象发送给前端register.html页面
        form_obj=myform.MyRegForm()
        return render(request,'register.html',locals())
    
    后端开发逻辑如下:
        把myform文件中的MyRegForm表单对象拿到
        判断前端发送过来的请求方式是不是post请求
        定义back_dic 字典
        对用户在前端提交的post数据进行校验,生成form_obj对象
        如果数据合法:
              获取键值对
              pop掉确认密码键值对
              获取前端发送的文件请求(avatar),创建文件对象
              判断用户是否上传文件:
                  上传文件了,把avatar添加到clean_data字典对象中
              用户表创建用户(create_user)
              back_dic字典添加msg信息,注册成功
              back_dic字典添加url,login路径
        
        数据不合法:
              字典添加code=2000  
              字典添加msg=form_obj.errors
        
        返回json数据到前端,[需要导入JsonResponse模块(from django.http import JsonResponse)]
        
        然后把form_obj对象发送给前端register.html页面
    
    
    前端开发逻辑:

    上传头像文件功能,注册按钮功能

    前端开发逻辑:register.html文件,前端只整理需要整理的
    上传头像文件功能
    <script>
        //上传头像文件相关的处理
        $('#mdd').on('change',function () {
            //利用内置对象filereader完成文件的读取操作
            let MyFileReader=new FileReader();
            //获取用户上传的文件对象
            let fileobj=$(this)[0].files[0];
            //让文件阅读器读取文件,IO操作,异步
            MyFileReader.readAsDataURL(fileobj);
            //将读取之后的内容替换到img标签src属性中
            MyFileReader.onload=function () {
                $('#img').attr('src',MyFileReader.result)
            }
        });
        
        
    
            // 注册按钮
        $('#submit').click(function () {
            // 将用户输入的数据全部发送给后端     普通的键值对   文件
            let MyFormData = new FormData();
            // 不停的朝里面添加键值对
            {#MyFormData.append('','')#}
            {#console.log($('#myform').serializeArray())#}
            // 普通键值对添加完毕 (利用form标签内部有一个自动序列化普通键值对方法)
            $.each($('#myform').serializeArray(),function (index,obj) {
                MyFormData.append(obj.name,obj.value)
            });
            // 手动添加文件数据
            MyFormData.append('avatar',$('#mdd')[0].files[0]);
            // 发送ajax请求
            $.ajax({
                url:'',
                type:'post',
                data:MyFormData,
                // 发送文件一定要指定两个参数
                processData:false,  // 不要让浏览器处理你的数据
                contentType:false,  // 不要使用任何的编码  django能够识别对象自身
    
                success:function (data) {
                    if (data.code == 1000){
                        // 跳转到登录页面
                        window.location.href = data.url
                    }else{
                        $.each(data.msg,function (index,obj) {
                            {#console.log(index,obj)#} // index就是报错字段  obj就是错误信息 数组的形式
                            // 获取报错字段  手动拼接出该字段所对应的input框的id值
                            let targetId = '#id_' + index;
                            $(targetId).next().text(obj[0]).parent().addClass('has-error')
                        })
                    }
                }
            })
    
        });
        // input框获取焦点事件,---这个是鼠标放到input框上面后,错误信息消失
        $('input').focus(function () {
            $(this).next().text('').parent().removeClass('has-error')
        })
    
    </script>
    
    

    图片验证码功能

    后端开发逻辑

    1.所需要的模块
    import random
    from PIL import Image,ImageDraw,ImageFont
    from io import BytesIO,StringIO
    '''
    内存管理器模块:
    BytesIO 保存数据,并且在获取的时候,是以二进制的方式给你
    StringIO 保存数据,并且在获取的时候,是以字符串的方式给你
    
    Image       生成图片
    ImageDraw   在图片上写字
    ImageFont   控制字的字体样式
    
    '''
    #io_obj=BytesIO()    #你就将该对象看成是文件句柄即可
        '''
     什么是文件句柄???
        在文件I/O中,要从一个文件读取数据,应用程序首先
        要调用操作系统函数并传送文件名,并选一个到该文件
        的路径来打开文件。该函数取回一个顺序号,即文件句柄
        (file handle),该文件句柄对于打开的文件是唯一的
        识别依据。要从文件中读取一块数据,应用程序需要调用
        函数ReadFile,并将文件句柄在内存中的地址和要拷贝的
        字节数传送给操作系统。当完成任务后,再通过调用系统函数
        来关闭该文件。”
        '''
    2.图片验证码的开发分为两步:
    	随机取色+图片验证码
        2.1随机取色
        def get_random():
        	return random.randint(0,255),random.randint(0,255),random.randint(0,255)
        
        2.2图片验证码函数
        	图片的宽高和随机取色---生成画板对象   Image.new
            将生成好的图片对象交给ImageDraw---画笔对象   ImageDraw.Draw
            字体样式	---何种字体   ImageFont.truetype
            #随机验证码	---何种要求(大小写英文加数字,5位)
            定义code=''
            循环5次:
            	大写字母		upper_str
                小写字母		lower_str
                str(随机数)	 random_int
                
                随机选取一个,random.choice([大写,小写,str(随机数)])
                往图片上写一个验证码		img_draw.text
                存储写的字				code+=tmp
            将code存到session中,供全局函数访问			request.session['code']=code
            生成I/O文件句柄							io_obj=BytesIO()	
            图片对象调用save方法保存io_obj文件对象,png的格式进行保存								img_obj.save(io_obj,'png')
            return HttpResponse(io_obj.getvalue())
            
     --------------------------------------------------------------------------------        
    3.图片验证码代码如下:
    def get_code(request):
        # 图片的宽高和随机取色        ----画板
        img_obj=Image.new('RGB',(360,35),get_random())
        #将生成好的图片对象交给ImageDraw   ---画笔
        img_draw=ImageDraw.Draw(img_obj)
        #字体样式                       ---何种字体
        img_font=ImageFont.truetype('static/font/111.ttf',30)
        #随机验证码      ---何种要求(大小写英文加数字,5位)
        code=''
        for i in range(5):
            upper_str=chr(random.randint(65,90))
            lower_str=chr(random.randint(97,122))
            random_int=str(random.randint(0,9))
            #随机选取一个
            tmp=random.choice([upper_str,lower_str,random_int])
            #往图片上写一个验证码
            img_draw.text((i*60+60,0),tmp,get_random(),img_font)
            #存储写的字
            code+=tmp
        print(code)
        #这个验证码后面其他视图函数可能要用到,
        #找个地方存一下,并且这个地方全局的视图函数都能访问
        request.session['code']=code
        io_obj=BytesIO()    #你就将该对象看成是文件句柄即可
        '''
        在文件I/O中,要从一个文件读取数据,应用程序首先
        要调用操作系统函数并传送文件名,并选一个到该文件
        的路径来打开文件。该函数取回一个顺序号,即文件句柄
        (file handle),该文件句柄对于打开的文件是唯一的
        识别依据。要从文件中读取一块数据,应用程序需要调用
        函数ReadFile,并将文件句柄在内存中的地址和要拷贝的
        字节数传送给操作系统。当完成任务后,再通过调用系统函数
        来关闭该文件。”
        '''
        img_obj.save(io_obj,'png')
        return HttpResponse(io_obj.getvalue())
    
        
    
    
    
    

    图片验证码实时刷新功能

    前端开发逻辑

    图片验证码随机变化的逻辑其实很简单,就是:
        首先为验证码绑定点击事件,
            其次拿到img中的src属性,
            最后为src设置新的值,使得图片验证码不断的更换
    
    
    <div class="col-md-6">
    	<img src="/get_code/" alt="" width="360" height="35" id="id_img">
    </div>
    
    <script>
        //拿到img中的src,
        //然后为src设置新的值,使得图片验证码不断的更换
        $('#id_img').click(function () {
            var oldPath = $(this).attr('src');
            $(this).attr('src',oldPath+='?')
        });
    
    </script>
    
    

    登录功能

    后端开发逻辑

    urls.py文件中:
    	# 登录功能
        url(r'^login/',views.login,name='login'),
    
    views.py文件中:
    开发逻辑如下:
    
    如果请求方式是post请求:
    	定义back_dic
        获取post请求的用户名
        获取post请求的密码
        获取post请求的验证码
        #先校验验证码是否正确,忽略大小写
        #再校验用户名和密码是否正确
        如果用户输入的验证码和后端保存的验证码相等:
        	再用auth模块校验用户名和密码是否相等,生成用户对象
            如果相等:
            	利用auth模块保存用户对象的登录状态
                #就可以在任意位置通过request.user获取到当前登录对象,并且request.user.is_authenticated()判断当前用户是否登录
                back_dic字典添加msg登录成功
                back_dic字典添加url,home主页路径
            
            如果用户名和密码不相等:
            	back_dic字典添加code=2000
                back_dic字典添加msg用户名或密码错误
        
        如果验证码不相等:
        	back_dic字典添加code=3000
            back_dic字典添加msg,验证码错误
        通过JsonResponse返回字典
     返回到登录页面
    
    
    
    # 保存用户登录状态,这个不太会,对该知识点模糊要多注意了,
    # 通过auth模块的login方法将用户保存起来,就可以在任意位置通过request.user,
    # 获取到当前登录对象,并且可以通过request.user.is_authenticated()判断当前用户是否登录
    auth.login(request, user_obj)
    auth模块很重要需要多复习复习
    
    

    前端开发逻辑

    为登录按钮绑定点击事件,
    	利用ajax请求,把数据发送到后端
    	ajax的固定格式为:
    		$.ajax({
    			url:'',
    			type:'post',
    			data:{k,v键值对,'csrfmiddlewaretoken':'{{ csrf_token }}'},	
    			success:function(data){
    				//此处的data就是后端返回过来的back_dic字典对象
    				如果code=1000:
    					跳转到对应页面的url连接
    				如果不等于1000:
    					渲染错误数据信息
    					信息错误后自动刷新验证码
    		}
    
    	})
    
    提交post请求跳过csrf中间件拦截的两种方式:
    {% csrf_token %}	------- 在form表单中书写
    'csrfmiddlewaretoken':'{{ csrf_token }}'	------- 在ajax中的data字典中书写
    
    
    <div>
        <input type="button" class="btn btn-primary" value="登录" id="id_submit">
        <span style="color: red;" id="id_error"></span>  //在此处渲染页面的错误信息
    </div>
    
    <script>
    $('#id_submit').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{
                    //$('#标签名').val()是获取当前标签的值
                    'username':$('#id_username').val(),
                    'password':$('#id_password').val(),
                    'code':$('#id_code').val(),
                    'csrfmiddlewaretoken':'{{ csrf_token }}'
                },
                success:function (data) {
                    if(data.code == 1000){
                        // 跳转链接
                        window.location.href = data.url
                    }else{
                        //渲染错误数据信息
                        $('#id_error').text(data.msg);
                        //数据填写错误,提交后验证码再次刷新
                        var oldPath = $('#id_img').attr('src');
                        $('#id_img').attr('src',oldPath+='?')
    
                    }
                }
            })
        
    </script>
    
    

    首页搭建功能

    后端开发逻辑

    #home主页
    第一步:查询所有文章,生成文章queryset对象,
    第二步:把数据全部提交到home页面
    
    def home(request):
        #查询所有文章,生成文章queryset对象,
        #把数据全部提交到home页面
        article_queryset=models.Article.objects.all()
        return render(request,'home.html',locals())
    
    

    前端开发逻辑

    主页搭建共分为四块,
    	第一块,导航条
        第二块,左侧面板	2
        第三块,中间面板	8
        第四块,右侧面板	2
    
    

    退出登录功能

    后端开发逻辑

    导入auth模块,导入登录认证装饰器:
    from django.contrib import auth
    from django.shortcuts import reverse
    from django.contrib.auth.decorators import login_required
    给退出登录函数添加@login_required装饰器,装饰器不要加括号
    	利用auth模块的退出登录函数			---auth.logout(request)
        返回通过重定向反转解析到home主页	  ---redirect(reversed('home'))
    
        
    代码如下:
    @login_required
    def logout(request):
        auth.logout(request)
        return redirect(reverse('home'))		---退出登录之后跳转到home主页
        注意事项,此处是reverse,可不要写成reversed
    
    

    前端开发逻辑

    用户登录情况下:
    	展示用户名:
        	拿到用户的用户名,------超链接;通过auth模块的is_authenticated判断用户是否已经登录
            
        修改密码
        修改头像
        后台管理
        退出登录
    未登录情况下:
    	展示登录	--超链接,反向解析login,{% url 'login' %}
        展示注册	--超链接,反向解析register,{% url 'register' %}
     
    
    部分逻辑代码如下:
    {% if request.user.is_authenticated %}
    <li><a href='#'>  {{  request.user.username	}}	</a></li>
        <li><a data-target="#myModal" data-toggle="modal">修改密码</a></li>
        <li><a href="#">修改头像</a></li>
        <li><a href="#">后台管理</a></li>
        <li role="separator" class="divider"></li>
        <li><a href="{% url 'logout' %}">退出登录</a></li>
    {% else %}
        <li><a href="{% url 'login' %}">登录</a></li>
        <li><a href="{% url 'register' %}">注册</a></li>
    {% endif %}
    
    

    修改密码功能

    后端开发逻辑

    urls.py文件中开设修改密码的路由
    
    url(r'^set_password/',views.set_password,name='set_pwd')
    
    views.py文件
    from django.shortcuts import reverse
    from django.contrib import auth
    from django.contrib.auth.decorators import login_required
    首先给修改密码函数添加装饰器@login_required
    如果前端请求方式是post请求:
    	获取前端发送过来的原密码old_password
        获取前端发送过来的新密码new_password
        获取前端发送过来的确认密码confirm_password
        #利用auth模块先判断前端发送过来的原密码是否正确,
        #check_password是auth模块自带的校验密码是否相等的功能
        request.user.check_password(old_password)
        如果原密码正确:
        	如果新密码和确认密码相等:
                利用auth模块中的set_password设置新的密码
                然后利用auth模块中的save方法进行保存
                返回重定向解析到登录页面
            
            如果新密码和确认密码不相等:
            	返回文本,两次密码不一致
        
        如果原密码不正确:
        	返回文本,原密码错误
        	
    

    前端开发逻辑

    利用form表单,发送post请求
        反向解析到set_pwd路径下,{% url 'set_pwd' %}
        利用{% csrf_token	%}	跳过csrf中间件
        下面就是form表单中的5个div,分别是:
        	用户名,使用disable属性,默认展示用户名不支持修改
            原密码
            新密码
            确认密码
            取消,修改
    
    
  • 相关阅读:
    C++窗体应用程序
    C++继承方式简介及公有继承
    C++(继承的基本概念和语法)
    python(12)---科赫特雪花
    python(11)---pyinstaller
    20200914 day9 数据结构复习(一)
    20200914 day9 刷题记录
    20200913 day8模拟(二)
    20200912 day7 刷题记录
    20200912 day7 图论复习(一)
  • 原文地址:https://www.cnblogs.com/ludundun/p/12066549.html
Copyright © 2011-2022 走看看