BBS项目之登录页面首页

BBS项目之登录页面首页

 

 

 

  • 登录页面以及验证码

  • 首页搭建

 

登录页面以及验证码

#登录功能
def login(request):
    if request.is_ajax():
        if request.method=='POST':
            # 获取参数
            back_dic={'code':200,'msg':'登陆成功'}
            username=request.POST.get('username')
            pwd=request.POST.get('pwd')
            code=request.POST.get('code')
    #验证参数
            if not username:
                back_dic['code']=301
                back_dic['msg']='用户名未填写'
                return JsonResponse(back_dic)

            if not pwd:
                back_dic['code']=302
                back_dic['msg']='密码未填写'
                return JsonResponse(back_dic)

            if not code:
                back_dic['code']=303
                back_dic['msg']='验证码未填写'
                return JsonResponse(back_dic)

            if request.session.get('code').upper() != code.upper():
                back_dic['code']=304
                back_dic['msg']='验证码不正确'
                return JsonResponse(back_dic)




            # 业务逻辑 判断传进来的和数据库的是否一致

            import hashlib
            m = hashlib.md5()
            m.update(pwd.encode('utf-8'))
            pwd = m.hexdigest()


            user_obj=models.UserInfo.objects.filter(username=username,password=pwd).first()
            if not user_obj:
                #为了防止撞库 知道用户名或者密码错误
                back_dic['code'] = 305
                back_dic['msg'] = '用户名或密码不正确'
                return JsonResponse(back_dic)
            #保存用户信息  session 当前登录的用户
            request.session['id']=user_obj.id
            request.session['username']=user_obj.username
            #返回数据
            back_dic['url']='/home/'
            return JsonResponse(back_dic)
    return render(request,'login.html')



#验证码
"""
图片相关的模块 先下载这个pillow
    pip3 install pillow
"""
from PIL import Image, ImageDraw, ImageFont

"""
Image:生成图片
ImageDraw:能够在图片上乱涂乱画 生成空图片 在上面写东西
ImageFont:控制字体样式
"""
from io import BytesIO, StringIO

"""
内存管理器模块
BytesIO:临时帮你存储数据 返回的时候数据是二进制
StringIO:临时帮你存储数据 返回的时候数据是字符串
"""
import random


def get_random():
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)


def get_code(request):
    # 最终步骤4:写图片验证码
    img_obj = Image.new('RGB', (430, 35), get_random())
    img_draw = ImageDraw.Draw(img_obj)  # 产生一个画笔对象
    img_font = ImageFont.truetype('static/font/111.ttf', 30)  # 字体样式 大小

    # 随机验证码  五位数的随机验证码  数字 小写字母 大写字母
    code = ''
    for i in range(4):
        random_upper = chr(random.randint(65, 90))  #A--Z
        random_lower = chr(random.randint(97, 122)) #a--z
        random_int = str(random.randint(0, 9)) #0--9
        # 从上面三个里面随机选择一个
        tmp = random.choice([random_lower, random_upper, random_int])
        # 将产生的随机字符串写入到图片上
        """
        为什么一个个写而不是生成好了之后再写
        因为一个个写能够控制每个字体的间隙 而生成好之后再写的话
        间隙就没法控制了
        """
        img_draw.text((i * 60 + 60, -2), tmp, get_random(), img_font)
        # 拼接随机字符串
        code += tmp
    print(code)
    # 随机验证码在登陆的视图函数里面需要用到 要比对 所以要找地方存起来并且其他视图函数也能拿到
    request.session['code'] = code
    io_obj = BytesIO()
    img_obj.save(io_obj, 'png')
    return HttpResponse(io_obj.getvalue())

注册功能

#注册功能
def register(request):
    if request.method == 'POST':
        # 提前定义一个json格式的字典类型 ajax一般返回json格式
        back_dic = {'code': 200, 'msg': '注册成功'}
        ####1.接受参数
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        re_pwd = request.POST.get('re_pwd')
        email = request.POST.get('email')
        avatar = request.FILES.get('myfile')

        #2.验证参数 前端验证可有可无   先验证不符合条件的
        if not username:
            back_dic['code']=201
            back_dic['msg']='用户名必须填写'
            return JsonResponse(back_dic)

        if not pwd:
            back_dic['code'] = 202
            back_dic['msg'] = '密码必须填写'
            return JsonResponse(back_dic)

        if not pwd == re_pwd:
            back_dic['code'] = 203
            back_dic['msg'] = '两次密码输入不一致'
            return JsonResponse(back_dic)

        if not email:
            back_dic['code'] = 204
            back_dic['msg'] = '邮箱未填写'
            return JsonResponse(back_dic)

        #3.查询数据库是不是有这个用户名 是否重复
        res=models.UserInfo.objects.filter(username=username).first()
        if res:
            back_dic['code'] = 205
            back_dic['msg'] = '用户已存在'
            return JsonResponse(back_dic)

        #4.头像是否上传   业务逻辑
        data_dic={}
        if avatar:
            data_dic['avatar']=avatar
        data_dic['username'] = username
        import hashlib
        m=hashlib.md5()
        m.update(pwd.encode('utf-8'))
        pwd=m.hexdigest()

        data_dic['password'] = pwd
        data_dic['email'] = email

        #5.入库  **字典打散成关键字参数
        models.UserInfo.objects.create(**data_dic)
        back_dic['url']='/login/'

        return JsonResponse(back_dic)  #返回格式化后的数据



    return render(request, 'register.html')

修改密码

#修改密码 加登录装饰器
def set_pwd(request):
    if request.is_ajax():
        if request.method=='POST':
            back_dic = {'code': 200, 'msg': '修改密码成功'}
            old_pwd=request.POST.get('old_pwd')
            new_pwd=request.POST.get('new_pwd')
            re_pwd=request.POST.get('re_pwd')

            #先验证旧密码是否正确
            old_pwd=hash_pwd(old_pwd)


            res=models.UserInfo.objects.filter(username=request.session.get('username'),password=old_pwd).first()

            if not res:
                back_dic['code']=1001
                back_dic['msg']='原密码不正确'
                return JsonResponse(back_dic)

            if new_pwd !=re_pwd:
                back_dic['code'] = 1002
                back_dic['msg'] = '两次密码输入不一致'
                return JsonResponse(back_dic)

            new_pwd=hash_pwd(new_pwd)

            #写入数据库
            models.UserInfo.objects.filter(pk=request.session.get('id')).update(password=new_pwd)
            for i in back_dic:
                print(i,back_dic[i])
            return JsonResponse(back_dic)
  • 注册页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        {% load static %}
        <script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
    {#    <script src="{% static 'js/mysetup.js' %}"></script>#}
    
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <h1 class="text-center">注册页面</h1>
            <div class="col-md-8 col-md-offset-2">
                <form action="">
                    {#                {% csrf_token %}#}
                    <div class="form-group">
                        <label for="username">用户名</label>
                        <input type="text" id="username" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="pwd">密码</label>
                        <input type="password" id="pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="re_pwd">确认密码</label>
                        <input type="password" id="re_pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="email">邮箱</label>
                        <input type="email" id="email" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="myfile">头像
                            {% load static %}
                            <img src="{% static 'img/default.jpg' %}" id="myimg" alt="" width="112"
                                 style="margin-left: 30px">
                        </label>
                        <input type="file" id="myfile" class="form-control" style="display: none">
                    </div>
    
                    <input type="button" class="btn btn-success btn-block pull-right" value="注册">
    
                </form>
            </div>
    
        </div>
    
    </div>
    <script>
        //头像实时展示 借助于文件阅读器
        $('#myfile').change(function () {
            //1.创建文件阅读器对象
            var myFileReadobj = new FileReader();
            //2.获取图片数据
            var myImgObj = $('#myfile')[0].files[0];
    
            //3.图片数据交给文件阅读器读取
            myFileReadobj.readAsDataURL(myImgObj)  //这句是异步操作(不等他的结果)  io操作
            //放在onload 方法 等外面代码执行完 在读取里面的
            myFileReadobj.onload = function () {
                //4.改变img的src attr拿某个标签的内部属性
                $('#myimg').attr('src', myFileReadobj.result)
            }
    
    
        })
    
    
        $('.btn').click(function () {
            //前端验证
            var username = $('#username').val();
            var pwd = $('#pwd').val();
            var re_pwd = $('#re_pwd').val();
            var email = $('#email').val();
    
            if (!username) {
                layer.msg('请输入用户名')
                return
            }
            if (!pwd) {
                layer.msg('请输入密码')
                return
            }
            if (!re_pwd) {
                layer.msg('确认密码未输入')
                return
            }
            if (!email) {
                layer.msg('请输入邮箱')
                return
            }
    
    
            var formDataObj = new FormData()
            formDataObj.append('username', username);
            formDataObj.append('pwd', pwd);
            formDataObj.append('re_pwd', re_pwd);
            formDataObj.append('email', email);
            //添加文件数据
            formDataObj.append('myfile', $('#myfile')[0].files[0]);
    
            $.ajax({
                url: '',
                type: 'post',
                //用formdata提交需要指定
                contentType: false,
                processData: false,
                data: formDataObj,
                success: function (args) {
    
                    if (args.code == 200) {
                        layer.msg(args.msg, {icon: 1}, function () {
                            location.href = args.url
                        })
                    } else {
                        layer.msg(args.msg)
                    }
                }
            })
        })
    
    
    </script>
    </body>
    </html>
    
  • 登录页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        {% load static %}
        <script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
    {#    <script src="{% static 'js/mysetup.js' %}"></script>#}
    
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <h1 class="text-center">登录界面</h1>
            <div class="col-md-8 col-md-offset-2">
                <form action="">
                    <div class="form-group">
                        <label for="">用户名:</label>
                        <input type="text" id="username" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="">密码:</label>
                        <input type="text" id="pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="">验证码:</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" id="code" class="form-control">
                            </div>
                            <div class="col-md-6">
                                <img src="/get_code/" id="id_img" alt="" style="width: 475px;height: 33px;">
                            </div>
                            
                        </div>
                    </div>
                    <input type="button" class="btn btn-primary btn-block" value="登录">
                </form>
            </div>
    
        </div>
    
    </div>
    <script>
        $('#id_img').click(function () {
            var old=$(this).attr('src')
            $(this).attr('src',old += '?')
        })
    
        $('.btn').click(function () {
            var username=$('#username').val()
            var pwd=$('#pwd').val()
            var code=$('#code').val()
    
            //验证参数
            if (!username){
                layer.msg('请输入用户名')
                return
            }
            if (!pwd){
                layer.msg('请输入密码')
                return
            }
            if (!code){
                layer.msg('请输入验证码')
                return
            }
    
            $.ajax({
                url:'',
                type:'post',
                data:{'username':username,'pwd':pwd,'code':code},
                success:function (res) {
    
                    if (res.code==200){
                        layer.msg(res.msg,{icon: 1},function () {
                            location.href=res.url;
                        });
    
                    }else {
                        layer.msg(res.msg,{icon: 2});
                    }
    
                }
            })
        })
    </script>
    </body>
    </html>
    
  • 主界面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
        {% load static %}
        <script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
    
        {#    <script src="{% static 'js/mysetup.js' %}"></script>#}
    </head>
    <body>
    <nav class="navbar navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">BBS</a>
            </div>
    
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">博客 <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Search">
                    </div>
                    <button type="submit" class="btn btn-default">Submit</button>
                </form>
                <ul class="nav navbar-nav navbar-right">
                    {% if request.session.username %}
                        <li><a href="#">{{ request.session.username }}</a></li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                               aria-expanded="false">设置 <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="#" data-toggle="modal" data-target="#myModal">修改密码</a></li>
                                <li><a href="#">账号管理</a></li>
                                <li><a href="/loginout/">退出登录</a></li>
    
                            </ul>
                        </li>
                    {% else %}
                        <li><a href="/register/">注册</a></li>
                        <li><a href="/login/">登录</a></li>
                    {% endif %}
    
    
                    <!-- Modal -->
                    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
                        <div class="modal-dialog" role="document">
                            <div class="modal-content">
                                <div class="modal-header">
                                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                                            aria-hidden="true">&times;</span></button>
                                    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
                                </div>
                                <div class="modal-body">
                                    <div class="row">
                                        <div class="form-group">
                                            <label for="">原密码</label>
                                            <input type="" id="old_pwd" class="form-control">
    
                                        </div>
                                        <div class="form-group">
                                            <label for="">新密码</label>
                                            <input type="text" id="new_pwd" class="form-control">
                                        </div>
                                        <div class="form-group">
                                            <label for="">确认密码</label>
                                            <input type="text" id="re_pwd" class="form-control">
                                        </div>
    
                                    </div>
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                                    <button type="button" class="btn btn-primary commit">确认</button>
                                </div>
                            </div>
                        </div>
                    </div>
    
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="container-fluid">
        <div class="col-md-2">
            <div class="panel panel-primary ">
                <div class=" panel-body ">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
    
        </div>
    
    
        <div class="col-md-8">
            {% for aritcle in aritcle_list %}
                <ul class="media-list">
                    <li class="media">
                        <h4 class="media-heading"><a href="">{{ aritcle.title }}</a></h4>
                        <div class="media-left">
                            <a href="#">
                                <img class="media-object" src="/static/img/default.jpg" alt="..." width="100px" height="100px">
                            </a>
                        </div>
                        <div class="media-body">
                            {{ aritcle.desc }}
    
                        </div>
                        <br>
                        <div>
                            <span><a href="">{{ aritcle.blog.userinfo.username }}&nbsp;&nbsp;</a></span>
                            <span>{{ aritcle.create_time|date:'Y-m-d ' }}&nbsp;&nbsp;</span>
                            <span><span class="glyphicon glyphicon-thumbs-up"></span>({{ aritcle.up_num }})&nbsp;&nbsp;</span>
                            <span><span class="glyphicon glyphicon-thumbs-down"></span>({{ aritcle.down_num }})&nbsp;&nbsp;</span>
                            <span><span class="glyphicon glyphicon-comment"></span>({{ aritcle.comment_num }})&nbsp;&nbsp;</span>
                        </div>
                    </li>
                    <hr>
                </ul>
    
            {% endfor %}
    
    
        </div>
    
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
    
        </div>
    
    </div>
    <script>
        $('.commit').click(function () {
            var old_pwd = $('#old_pwd').val();
            var new_pwd = $('#new_pwd').val();
            var re_pwd = $('#re_pwd').val();
    
            //验证参数
            if (!old_pwd) {
                layer.msg('请输入旧密码')
                return
            }
            if (!new_pwd) {
                layer.msg('请输入新密码')
                return
            }
            if (!re_pwd) {
                layer.msg('请再次输入密码')
                return
            }
    
            $.ajax({
                url: '/set_pwd/',
                type: 'post',
                data: {'old_pwd': old_pwd, 'new_pwd': new_pwd, 're_pwd': re_pwd},
                success: function (res) {
    
                    if (res.code == 200) {
    
                        layer.msg(res.msg, {icon: 1}, function () {
                            location.reload();
    
                        });
                    } else {
                        layer.msg(res.msg, {icon: 2});
                    }
    
    
                }
            })
        })
    </script>
    </body>
    </html>
    
  • admin

from django.contrib import admin

# Register your models here.
from app01 import models
#想在django自带的后台管理系统管理数据,就要在这个里面注册

#注册了之后 自带后端页面显示这个userinfo
admin.site.register(models.UserInfo)
admin.site.register(models.Blog)
admin.site.register(models.Article)
admin.site.register(models.Category)
admin.site.register(models.Tag)
admin.site.register(models.Comment)
admin.site.register(models.UpAndDown)
admin.site.register(models.Article2Tag)

models

from django.db import models


from django.contrib.auth.models import AbstractUser

#用户表
class UserInfo(AbstractUser):
                                                    #前面这个限制数据库,后面这个前端也限制
    phone=models.BigIntegerField(verbose_name='手机号',null=True,blank=True)
    avatar=models.FileField(upload_to='static/img',default='static/img/default.jpg')
    '''
            以后用户上传头像会直接上传到'static/img'路径下
            如果没有上传,使用默认的:static/img/default.png
    '''
    create_time=models.DateTimeField(auto_now_add=True)
    #外键字段 一对一
    blog=models.OneToOneField(to='Blog',null=True)

    #让他后台管理显示中文标示
    class Meta:
        verbose_name_plural='用户表'

#站点表
class Blog(models.Model):
    site_name=models.CharField(verbose_name='站点名称',max_length=32)
    site_title=models.CharField(verbose_name='站点标题',max_length=32)
    #存css或者js文件的路径
    site_theme=models.CharField(verbose_name='站点样式',max_length=64)
    class Meta:
        verbose_name_plural='站点表'

    def __str__(self):
        return self.site_name


#标签表
class Tag(models.Model):
    name=models.CharField(verbose_name='文章标签',max_length=32)
    #外键字段 一对多
    blog=models.ForeignKey(to='Blog',null=True)
    class Meta:
        verbose_name_plural='标签表'
    def __str__(self):
        return self.name

#分类表
class Category(models.Model):
    name=models.CharField(verbose_name='文章分类',max_length=32)
    # 外键字段 一对多
    blog = models.ForeignKey(to='Blog', null=True)
    class Meta:
        verbose_name_plural='分类表'
    def __str__(self):
        return self.name


#文章表
class Article(models.Model):
    title=models.CharField(verbose_name='文章标题',max_length=64)
    desc=models.CharField(verbose_name='文章简介',max_length=255)
    #文章内容比较多一般使用 TextField
    content=models.TextField(verbose_name='文章内容')
    create_time=models.DateField(auto_now_add=True)
    #数据库优化字段
    up_num=models.BigIntegerField(verbose_name='点赞数',default=0)
    down_num=models.BigIntegerField(verbose_name='点踩数',default=0)
    comment_num=models.BigIntegerField(verbose_name='评论数',default=0)

    #外键字段
    blog=models.ForeignKey(to='Blog',null=True)#一对多 文章和站点
    category=models.ForeignKey(to='Category',null=True)#一对多 文章和分类表
    tags=models.ManyToManyField(to='Tag',
                                through='Article2Tag',
                                through_fields=('article','tag')
                                )#多对多 文章和标签表
    class Meta:
        verbose_name_plural='文章表'

    def __str__(self):
        return self.title

#第三种关系表 manytomany
class Article2Tag(models.Model):
    article=models.ForeignKey(to='Article')
    tag=models.ForeignKey(to='Tag')




#点赞点踩表
class UpAndDown(models.Model):
    user = models.ForeignKey(to='UserInfo')
    article = models.ForeignKey(to='Article')
    is_up = models.BooleanField()  #传布尔值  存0/1

    class Meta:
        verbose_name_plural='点赞点踩表'
#评论表
class Comment(models.Model):
    user = models.ForeignKey(to='UserInfo')
    article = models.ForeignKey(to='Article')
    content= models.CharField(verbose_name='评论内容',max_length=512)
    comment_time=models.DateTimeField(verbose_name='评论时间',auto_now_add=True)
    #加null等于True 是因为有些评论就是跟评论,他没有子评论
    parent = models.ForeignKey(to='self', null=True)
    class Meta:
        verbose_name_plural='评论表'

posted @ 2021-12-10 21:01  迪迦张  阅读(77)  评论(0编辑  收藏  举报