zoukankan      html  css  js  c++  java
  • BBS

    一、博客系统得表关系

    models.py

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    
    class UserInfo(AbstractUser):
        """
        用户信息
        """
        nid = models.AutoField(primary_key=True)
        telephone = models.CharField(max_length=11, null=True, unique=True)
        avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png')
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    
        blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.username
    
    
    class Blog(models.Model):
        """
        博客信息
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='个人博客标题', max_length=64)
        site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True)
        theme = models.CharField(verbose_name='博客主题', max_length=32)
    
        def __str__(self):
            return self.title
    
    
    class Category(models.Model):
        """
        博主个人文章分类表
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='分类标题', max_length=32)
        blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
    
        def __str__(self):
            return self.title
    
    
    class Tag(models.Model):
        """
        博主个人文章标签表
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='标签名称', max_length=32)
        blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
    
        def __str__(self):
            return self.title
    
    
    class Article(models.Model):
        """
        文章信息
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=50, verbose_name='文章标题')
        desc = models.CharField(max_length=255, verbose_name='文章描述')
        create_time = models.DateTimeField(verbose_name='创建时间')
        category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
        user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    
        tags = models.ManyToManyField(
            to='Tag',
            through='Article2Tag',
            through_fields=('article','tag'),
        )
    
        def __str__(self):
            return self.title
    
    
    class ArticleDetail(models.Model):
        """
        文章详细表
        """
        nid = models.AutoField(primary_key=True)
        content = models.TextField()
        article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE)
    
    
    class Article2Tag(models.Model):
        """
        多对多,文章、标签得第三张表
        """
        nid = models.AutoField(primary_key=True)
        article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE)
        tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid', on_delete=models.CASCADE)
    
        class Meta:
            unique_together = [
                ('article', 'tag'),
            ]
    
        def __str__(self):
            v = self.article.title + '--' + self.tag.title
            return v
    
    
    class ArticleUpDown(models.Model):
        """
        点赞,踩灭表
        """
        nid = models.AutoField(primary_key=True)
        user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE)
        article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
        is_up = models.BooleanField(default=True)
    
        class Meta:
            unique_together = [
                ('article','user'),
            ]
    
    
    class Comment(models.Model):
        """
        评论表
        """
        nid = models.AutoField(primary_key=True)
        article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
        user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
        content = models.CharField(verbose_name='评论内容', max_length=255)
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    
        parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.content

    操作配置:

    AUTH_USER_MODEL = "blog.UserInfo"    
    
    create database cnblog;
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'cnblog',
            'USER': 'root',
            'PASSWORD': '123',
            'HOST': '127.0.0.1',
            'PORT': 3306,
        }
    }
    
    import pymysql
    pymysql.install_as_MySQLdb()
    
    Tools/Run manage.py Task
    makemigrations
    migrate

    。。。

    结果:

    二、基于Ajax和用户登录验证

    验证码得获取:

    方式一:

     <img width="260" height="35" src="/get_valid_img/" alt="">
    def get_valid_img(request):
        # 方式一
        with open('girl.jpg','rb') as f:
            data = f.read()
    
        return HttpResponse(data)

    方式二:

    def get_valid_img(request):
        # 方式二
        """
        pip install pillow
        """
        import PIL
        from PIL import Image
    
        import random
    
        def get_random_color():
            return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    
        image = Image.new('RGB',(260,35),get_random_color())
    
        f = open('valid_code.png','wb')  # 存在磁盘上
        image.save(f,'png')
    
        f = open('valid_code.png','rb')
        data = f.read()
        f.close()
    
        return HttpResponse(data)

       

    方式三:

    def get_valid_img(request):
        # 方式三
        import PIL
        from PIL import Image
    
        import random
    
        def get_random_color():
            return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    
        image = Image.new('RGB',(260,35),get_random_color())
    
        from io import BytesIO
        f = BytesIO()   # 在内存中创建一张图片 直接返回
        image.save(f,'png')
    
        data = f.getvalue()
    
        return HttpResponse(data)

      

    方式四:

    kumo.ttf

    def get_valid_img(request):
        # 方式四
        import PIL
        from PIL import Image,ImageDraw,ImageFont
    
        import random
    
        def get_random_color():
            return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    
        image = Image.new('RGB',(260,35),get_random_color())
    
        draw = ImageDraw.Draw(image)
    
        font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32)
    
        temp = []
        # 生成5个随机字符
        for i in range(5):
            random_num = str(random.randint(0,9))
            random_low_alpha = chr(random.randint(97,122))
            random_upper_alpha = chr(random.randint(65,90))
    
            random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
            draw.text((24+i*36,0),random_char,get_random_color(),font=font)
    
            # 保存随机数
            temp.append(random_char)
    
        # 造点 造线 造圆
        width = 210
        height = 35
        for i in range(2):
            x1 = random.randint(0,width)
            x2 = random.randint(0,width)
            y1 = random.randint(0,height)
            y2 = random.randint(0,height)
            draw.line((x1,y1,x2,y2),fill=get_random_color())
        for i in range(2):
            draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color())
            x = random.randint(0,width)
            y = random.randint(0,height)
            draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color())
    
        # 在内存中生成图片
        from io import BytesIO
        f = BytesIO()
        image.save(f,'png')
        data = f.getvalue()
        f.close()
    
        valid_str = ''.join(temp)
        print('valid_str:',valid_str)
    
        request.session['valid_str'] = valid_str
    
        return HttpResponse(data)

    登录验证:

        

    <body>
    <h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3>
    </body>
    <input type="button" class="btn btn-default login-btn" value="提交">
    <span class="error" style="color: red; margin-left: 10px;"></span>
    <script src="/static/js/jquery-3.2.1.min.js"></script>
        <script type="text/javascript">
            $('.login-btn').click(function () {
                $.ajax({
                    url:'',
                    type:'post',
                    data:{
                        csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
                        user:$('#user').val(),
                        pwd:$('#pwd').val(),
                        valid_code:$('#valid_code').val()
                    },
                    success:function (data) {
                        if(data.state){
                            location.href = '/index/'
                        }else{
                            $('.error').text(data.msg)
    
                        }
                    }
                    
                })
            })
    from django.shortcuts import render,HttpResponse,redirect
    
    from django.http import JsonResponse
    from django.contrib import auth
    
    
    def login(request):
        if request.is_ajax():
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            valid_code = request.POST.get('valid_code')
    
            valid_str = request.session.get('valid_str')
    
            res = {"state": False, "msg": None}
            if valid_code.upper() == valid_str.upper():
                user = auth.authenticate(username = user,password = pwd)
                if user:
                    res["state"] = True
                    auth.login(request, user)
                else:
                    res["msg"] = "username or pwd error"
            else:
                res["msg"] = "验证码错误"
    
            return JsonResponse(res)
    
        return render(request,'login.html')
    
    
    def index(request):
        if not request.user.username:
            return redirect('/login/')
    
        return render(request,'index.html')

    验证码点击刷新:

     <img id="valid_img" width="260" height="35" src="/get_valid_img/" alt="">
    //验证码点击刷新
    $('#valid_img').click(function () {
        $(this)[0].src += '?'
    })    

    示例:

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    
    class UserInfo(AbstractUser):
        """
        用户信息
        """
        nid = models.AutoField(primary_key=True)
        telephone = models.CharField(max_length=11, null=True, unique=True)
        avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png')
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    
        blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.username
    
    
    class Blog(models.Model):
        """
        博客信息
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='个人博客标题', max_length=64)
        site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True)
        theme = models.CharField(verbose_name='博客主题', max_length=32)
    
        def __str__(self):
            return self.title
    
    
    class Category(models.Model):
        """
        博主个人文章分类表
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='分类标题', max_length=32)
        blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
    
        def __str__(self):
            return self.title
    
    
    class Tag(models.Model):
        """
        博主个人文章标签表
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='标签名称', max_length=32)
        blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
    
        def __str__(self):
            return self.title
    
    
    class Article(models.Model):
        """
        文章信息
        """
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=50, verbose_name='文章标题')
        desc = models.CharField(max_length=255, verbose_name='文章描述')
        create_time = models.DateTimeField(verbose_name='创建时间')
        category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
        user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    
        tags = models.ManyToManyField(
            to='Tag',
            through='Article2Tag',
            through_fields=('article','tag'),
        )
    
        def __str__(self):
            return self.title
    
    
    class ArticleDetail(models.Model):
        """
        文章详细表
        """
        nid = models.AutoField(primary_key=True)
        content = models.TextField()
        article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE)
    
    
    class Article2Tag(models.Model):
        """
        多对多,文章、标签得第三张表
        """
        nid = models.AutoField(primary_key=True)
        article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE)
        tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid', on_delete=models.CASCADE)
    
        class Meta:
            unique_together = [
                ('article', 'tag'),
            ]
    
        def __str__(self):
            v = self.article.title + '--' + self.tag.title
            return v
    
    
    class ArticleUpDown(models.Model):
        """
        点赞,踩灭表
        """
        nid = models.AutoField(primary_key=True)
        user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE)
        article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
        is_up = models.BooleanField(default=True)
    
        class Meta:
            unique_together = [
                ('article','user'),
            ]
    
    
    class Comment(models.Model):
        """
        评论表
        """
        nid = models.AutoField(primary_key=True)
        article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
        user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
        content = models.CharField(verbose_name='评论内容', max_length=255)
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    
        parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.content
    models.py
    from django.shortcuts import render,HttpResponse,redirect
    
    from django.http import JsonResponse
    from django.contrib import auth
    
    
    def login(request):
        if request.is_ajax():
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            valid_code = request.POST.get('valid_code')
    
            valid_str = request.session.get('valid_str')
    
            res = {"state": False, "msg": None}
            if valid_code.upper() == valid_str.upper():
                user = auth.authenticate(username = user,password = pwd)
                if user:
                    res["state"] = True
                    auth.login(request, user)
                else:
                    res["msg"] = "username or pwd error"
            else:
                res["msg"] = "验证码错误"
    
            return JsonResponse(res)
    
        return render(request,'login.html')
    
    
    def index(request):
        if not request.user.username:
            return redirect('/login/')
    
        return render(request,'index.html')
    
    
    def get_valid_img(request):
        # 方式四
        import PIL
        from PIL import Image,ImageDraw,ImageFont
    
        import random
    
        def get_random_color():
            return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    
        image = Image.new('RGB',(260,35),get_random_color())
    
        draw = ImageDraw.Draw(image)
    
        font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32)
    
        temp = []
        # 生成5个随机字符
        for i in range(5):
            random_num = str(random.randint(0,9))
            random_low_alpha = chr(random.randint(97,122))
            random_upper_alpha = chr(random.randint(65,90))
    
            random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
            draw.text((24+i*36,0),random_char,get_random_color(),font=font)
    
            # 保存随机数
            temp.append(random_char)
    
        # 造点 造线 造圆
        width = 210
        height = 35
        for i in range(2):
            x1 = random.randint(0,width)
            x2 = random.randint(0,width)
            y1 = random.randint(0,height)
            y2 = random.randint(0,height)
            draw.line((x1,y1,x2,y2),fill=get_random_color())
        for i in range(2):
            draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color())
            x = random.randint(0,width)
            y = random.randint(0,height)
            draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color())
    
        # 在内存中生成图片
        from io import BytesIO
        f = BytesIO()
        image.save(f,'png')
        data = f.getvalue()
        f.close()
    
        valid_str = ''.join(temp)
        print('valid_str:',valid_str)
    
        request.session['valid_str'] = valid_str
    
        return HttpResponse(data)
    
    
        # 方式三
        # import PIL
        # from PIL import Image
        #
        # import random
        #
        # def get_random_color():
        #     return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
        #
        # image = Image.new('RGB',(260,35),get_random_color())
        #
        # from io import BytesIO
        # f = BytesIO()   # 在内存中创建一张图片 直接返回
        # image.save(f,'png')
        #
        # data = f.getvalue()
        #
        # return HttpResponse(data)
    
    
        # 方式二
        # """
        # pip install pillow
        # """
        # import PIL
        # from PIL import Image
        #
        # import random
        #
        # def get_random_color():
        #     return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
        #
        # image = Image.new('RGB',(260,35),get_random_color())
        #
        # f = open('valid_code.png','wb')  # 存在磁盘上
        # image.save(f,'png')
        #
        # f = open('valid_code.png','rb')
        # data = f.read()
        # f.close()
        #
        # return HttpResponse(data)
    
    
        # 方式一
        # with open('girl.jpg','rb') as f:
        #     data = f.read()
        #
        # return HttpResponse(data)
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
    </head>
    <body>
    <h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3>
    </body>
    </html>
    index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>login</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
        <style type="text/css">
            .container{ margin-top: 100px;}
        </style>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3">
                    <form>
                        {% csrf_token %}
                        <div class="form-group">
                            <label for="user">用户名</label>
                            <input type="text" class="form-control" id="user" placeholder="Username">
                        </div>
                        
                        <div class="form-group">
                            <label for="pwd">密码</label>
                            <input type="password" class="form-control" id="pwd" placeholder="Password">
                        </div>
    
                        <div class="form-group">
                            <label for="pwd">验证码</label>
                            <div class="row">
    
                                <div class="col-md-6">
                                    <input type="text" class="form-control" id="valid_code">
                                </div>
    
                                <div class="col-md-6">
                                    <img id="valid_img" width="260" height="35" src="/get_valid_img/" alt="">
                                </div>
                            </div>
                        </div>
    
                        <input type="button" class="btn btn-default login-btn" value="提交">
                        <span class="error" style="color: red; margin-left: 10px;"></span>
                    </form>
                </div>
            </div>
        </div>
    
    
        <script src="/static/js/jquery-3.2.1.min.js"></script>
        <script type="text/javascript">
            //提交
            $('.login-btn').click(function () {
                $.ajax({
                    url:'',
                    type:'post',
                    data:{
                        csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
                        user:$('#user').val(),
                        pwd:$('#pwd').val(),
                        valid_code:$('#valid_code').val()
                    },
                    success:function (data) {
                        if(data.state){
                            location.href = '/index/'
                        }else{
                            $('.error').text(data.msg)
    
                        }
                    }
                    
                })
            });
    
            //验证码点击刷新
            $('#valid_img').click(function () {
                $(this)[0].src += '?'
            })
            
        </script>
    </body>
    </html>
    login.html

    注:

     css js 静态文件
    css js 存在静态文件中 修改之后,client(浏览器)如果没有修改;
    需设置一些 浏览器得setting Disable cache

    三、form表单、ajax文件上传

    django-ajax   http://www.cnblogs.com/yuanchenqi/articles/7638956.html

      


    基于form表单提交数据:
    默认值:Content—Type = urlencoded
    <form action="" method="post" enctype="application/x-www-form-urlencoded">
    print(request.POST)
    <QueryDict: {'csrfmiddlewaretoken': ['azZWQlmRhdPPXxtRf9e04B31VZLyVJN8Dc1eAuWEMIxnWShqNP5IyxbozXVRjx8A'],
    'user': ['alex'],
    'avatar': ['girl.jpg']}> # 其实文件并没有传上来,只是个名称!
    print(request.FILES)
    <MultiValueDict: {}>

    涉及到上传文件时:Content—Type = form-data
    <form action="" method="post" enctype="multipart/form-data">
    print(request.POST)
    <QueryDict: {'csrfmiddlewaretoken': ['gsAIE42u5Io47YttQO9ExBEFuZiVZ965J5C0odChAd6C6jh2ou0m1xM28XsenXrx'],
    'user': ['alex']}>
    print(request.FILES)
    <MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}>

    基于Ajax提交数据:
    $('#btn').click(function () {
    $.ajax({
    url:'',
    type:'get',
    data:{name:'alex',pwd:'123'},
    success:function (data) {
    console.log(data)
    }

    })
    })

    涉及到上传文件时:
    <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script type="text/javascript">
    $('#btn').click(function () {
    formdate = new FormData(); // 加var 局部, 不加var就是 全局.
    formdate.append("user",$('#user').val());
    formdate.append("avatar",$('#avatar')[0].files[0]);
    formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());

    $.ajax({
    url:'',
    type:'post',
    data:formdate,
    contentType:false,
    processData:false,
    success:function (data) {
    console.log(data)
    }

    })
    })

    </script>

    <QueryDict: {'user': ['alice'], 'csrfmiddlewaretoken': ['9ipnZT2GROgz1BFiCZzsYTE32MCBPXKWCVrFJ2CtmjY70WtRaFqasPMqGKMUdL5o']}>
    <MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}>


    def upload(request):
        if request.method == 'POST':
            print(request.POST)
            print(request.FILES)
            obj = request.FILES.get('avatar')
    
            with open(obj.name,'wb') as f:
                for line in obj:
                    f.write(line)
            return HttpResponse('OK')
    
        return render(request,'upload.html')

    upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <h3>基于form表单提交数据</h3>
    {#<form action="" method="post" enctype="application/x-www-form-urlencoded">#}
    <form action="" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p>用户名 <input type="text" name="user"></p>
        <p>头像 <input type="file" name="avatar"></p>
        <input type="submit">
    
    </form>
    
    <hr>
    <h3>基于Ajax提交文件数据</h3>
    <form>
        {% csrf_token %}
        <p>用户名 <input type="text" id="user"></p>
        <p>头像 <input type="file" id="avatar"></p>
        <input type="button" value="submit" id="btn">
    </form>
    
    <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script type="text/javascript">
        $('#btn').click(function () {
            formdate = new FormData();  // 加var 局部, 不加var就是 全局.
            formdate.append("user",$('#user').val());
            formdate.append("avatar",$('#avatar')[0].files[0]);
            formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
    
            $.ajax({
                url:'',
                type:'post',
                data:formdate,
                contentType:false,
                processData:false,
                success:function (data) {
                    console.log(data)
                }
    
            })
        })
    
    </script>
    </body>
    </html>

    四、form表单得注册页面

              

    头像默认图片

    #avatar{ display: none}
    .avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;}
    <div class="form-group">
        <label for="avatar">头像
            <img class="avatar" src="/static/img/default.png" alt="">
        </label>
    
        <input type="file" id="avatar">
    </div>

    图像预览

    //图像预览
    $('#avatar').change(function () {
        var choose_file = $(this)[0].files[0];  //文件对象
    
        var reader = new FileReader();  // 阅读器对象
        reader.readAsDataURL(choose_file);
    
        reader.onload = function (ev) {
             $('.avatar').attr('src',reader.result)
        };
    
        {#$('.avatar').attr('src',reader.result)  // 还没读完,就执行了这句了 出问题了!!#}
        //解决办法   reader.onload
    
    });

     注意:

    为什么   src="/static/img/default.png"    可访问到 ? 

    因为:  settings   配置了   STATIC_URL = '/static/'   

    STATIC_URL = '/static/' 
    /static/... 对外得文件可以直接访问

    Ajax 注册:

    from django import forms
    from django.forms import widgets,ValidationError
    
    from app01.models import UserInfo
    
    class RegForm(forms.Form):
        user = forms.CharField(max_length=8,label='用户名',
                            widget=widgets.TextInput(attrs={'class':'form-control'}))
        pwd = forms.CharField(min_length=4,label='密码',
                              widget=widgets.PasswordInput(attrs={'class':'form-control'}))
        repeat_pwd = forms.CharField(min_length=4,label='确认密码',
                              widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        email = forms.EmailField(label='邮箱',
                             widget=widgets.EmailInput(attrs={'class': 'form-control'}))
    
        # 局部钩子
        def clean_user(self):
            val = self.cleaned_data.get('user')
    
            ret = UserInfo.objects.filter(username = val)
            if not ret:
                return val
            else:
                raise ValidationError('该用户已存在')
    
        # 校验局部钩子得时候 没有办法 拿到 所有得干净数据,
        # 如何 校验 两个 字段呢! 全局钩子
    
        # 全局钩子 能得到 任何一个干净得 数据   def clean(self):return self.cleaned_data
        def clean(self):
            if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
    
    
    from django.http import JsonResponse
    
    def reg(request):
        if request.method == 'POST':
            res = {'user':None,'error_dict':None}
            form = RegForm(request.POST)
    
            if form.is_valid():
                print("clean:",form.cleaned_data)  # {"user":'yuan','pwd':"123"}
                print(request.FILES)
    
                user = form.cleaned_data.get('user')
                pwd = form.cleaned_data.get('pwd')
                email = form.cleaned_data.get('email')
                avatar = request.FILES.get('avatar')
                if avatar:
                    # 接受文件对象  将avatar文件对象下载到avatar字段对应的upload_to指定路径 没指定在 根目录下
                    user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
                else:
                    user = UserInfo.objects.create_user(username=user, password=pwd, email=email)
    
                res['user'] = user.username
    
            else:
                print('error:',form.errors)  #{"repear_pwd":['',''],"email":['',''],}
                res['error_dict'] = form.errors
    
            return JsonResponse(res)
    
        form = RegForm()
        return render(request,'reg.html',locals())
    // 注册事件
    $('.reg_btn').click(function () {
        formdata = new FormData();
        formdata.append("user",$('#id_user').val());
        formdata.append("pwd",$('#id_pwd').val());
        formdata.append("repeat_pwd",$('#id_repeat_pwd').val());
        formdata.append("email",$('#id_email').val());
        formdata.append("avatar",$('#avatar')[0].files[0]);
        formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
    
        $.ajax({
            url:'',
            type:'post',
            contentType:false,
            processData:false,
            data:formdata,
            success:function (data) {
                if(data.user){
                    //注册成功
                    location.href = "/login/"
                }else{
                    //注册失败
                    //清空错误信息
                    $('form span').html("");
                    $('form .form-group').removeClass('has-error');
                    // 加载错误信息
                    $.each(data.error_dict,function (field,error_list) {
                        // 全局
                        if(field == "__all__"){
                            $('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
                            $('#id_repeat_pwd').parent().addClass('has-error')
                        }
                        $('#id_'+field).next().text(error_list[0]).css('color','red');
                        $('#id_'+field).parent().addClass('has-error')
                    })
                }
            }
    
        })
    
    })

    注意点:

    1. 局部钩子 与 全局钩子:

    def clean_user(self): pass   局部钩子 只能校验某一个字段
    def clean(self): pass        可以校验两个不同得字段,全局钩子,能得到任何一个干净得数据!!
    局部钩子得源码:
    try
    : if isinstance(field, FileField): initial = self.get_initial_for_field(field, name) value = field.clean(value, initial) else: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e)
    全局钩子得源码:
    try
    : cleaned_data = self.clean() except ValidationError as e: self.add_error(None, e) else: if cleaned_data is not None: self.cleaned_data = cleaned_data

    2. 上传文件:

     formdata = new FormData();
    formdata.append("avatar",$('#avatar')[0].files[0]); # 文件对象 formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
     contentType:false,
     processData:false,
     data:formdata,
    。。。

    3. ajax得局部刷新:

    注册失败:

    
    
    1. 清空错误信息 
      $('form span').html("");
      $('form .form-group').removeClass('has-error');

    2. 加载错误信息 each
      $.each(data.error_dict,function (field,error_list) {
           // 全局  全局得错误信息 field == '__all__'
           if(field == "__all__"){ 
             $('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
               $('#id_repeat_pwd').parent().addClass('has-error')
            }
            $('#id_'+field).next().text(error_list[0]).css('color','red');
            $('#id_'+field).parent().addClass('has-error')
        })

    4.上传文件 得存放地址:media 配置

     avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
     FileField  ImgField  传什么数据呢?  文件对象

    前端:
    formdata.append("avatar",$('#avatar')[0].files[0]); # 文件对象

    后台:
    avatar = request.FILES.get('avatar') # 文件对象
    if avatar:
    # 接收文件对象 将avatar文件对象下载到avatar字段对应的upload_to(upload_to='avatars/')指定路径下
    user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
    else:
    user = UserInfo.objects.create_user(username=user, password=pwd, email=email)

    真实文件:
    upload_to='' 存在项目得根目录下 girl.jpg
    upload_to='avatars/' 存在项目得根目录下 /avatars/girl.jpg 注意: 相对路径 不是绝对路径,如果upload_to='/avatars/'会报错!!

    userinfo:
    库里存得是 相对路径!! avatars/girl.jpg

    BUT:
    用户个人得文件 不应该存在项目得根目录下: ??

    知识点:
    静态文件 /static/css..js..img.. 用户可直接 url 访问得到
    因为:settings 配置 STATIC_URL = '/static/'

    用户文件:存用户得个人信息 头像 简历。。。 存在哪里呢???
    media 配置 存用户信息 针对用户上传得文件
    avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
            settings

    1.MEDIA_ROOT = os.path.join(BASE_DIR,'app01','media') # 针对 upload_to 得相对位置得!!

    2.MEDIA_URL = '/media/'                 # 针对 用户通过 url 访问得!!

    3.urls.py
    from django.views.static import serve
    from bbs import settings
    re_path(r'media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}) # 针对 用户通过 url 访问得!!

    media 配置之后
    用户可直接访问类似于访问/static/img/...


    upload_to='avatars/' 用户上传得文件就会存在 /media/avatars/girl.jpg 库里存得是,相对路径! avatars/girl.jpg

      

     
    注意:
    # avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
    # 如果用户没有上传图片,使用默认得!!avatar 不需要传!!

    avatar = request.FILES.get('avatar')
    if avatar:
    user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
    else:
    user = UserInfo.objects.create_user(username=user, password=pwd, email=email)

     示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>reg</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
        <style type="text/css">
            .container{ margin-top: 100px;}
            #avatar{ display: none}
            .avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;}
        </style>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3">
                    <form action="">
                        {% for field in form %}
                            <div class="form-group">
                                <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                                {{ field }} <span class="error pull-right"></span>
                            </div>
                        {% endfor %}
                        
                        <div class="form-group">
                            <label for="avatar">头像
                                <img class="avatar" src="/static/img/default.png" alt="">
                            </label>
    
                            <input type="file" id="avatar">
                        </div>
                    
    
                        <input type="button" class="btn btn-default login-btn reg_btn pull-right" value="提交">
                    </form>
                </div>
            </div>
        </div>
        {% csrf_token %}
    
    
        <script src="/static/js/jquery-3.2.1.min.js"></script>
        <script type="text/javascript">
            //图像预览
            $('#avatar').change(function () {
                var choose_file = $(this)[0].files[0];  //文件对象
    
                var reader = new FileReader();  // 阅读器对象
                reader.readAsDataURL(choose_file);
    
                reader.onload = function (ev) {
                     $('.avatar').attr('src',reader.result)
                };
    
                {#$('.avatar').attr('src',reader.result)  // 还没读完,就执行了这句了 出问题了!!#}
                //解决办法   reader.onload
    
            });
    
            // 注册事件
            $('.reg_btn').click(function () {
                formdata = new FormData();
                formdata.append("user",$('#id_user').val());
                formdata.append("pwd",$('#id_pwd').val());
                formdata.append("repeat_pwd",$('#id_repeat_pwd').val());
                formdata.append("email",$('#id_email').val());
                formdata.append("avatar",$('#avatar')[0].files[0]);
                formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
    
                $.ajax({
                    url:'',
                    type:'post',
                    contentType:false,
                    processData:false,
                    data:formdata,
                    success:function (data) {
                        if(data.user){
                            //注册成功
                            location.href = "/login/"
                        }else{
                            //注册失败
                            //清空错误信息
                            $('form span').html("");
                            $('form .form-group').removeClass('has-error');
                            // 加载错误信息
                            $.each(data.error_dict,function (field,error_list) {
                                // 全局
                                if(field == "__all__"){
                                    $('#id_repeat_pwd').next().text(error_list[0]).css('color','red');
                                    $('#id_repeat_pwd').parent().addClass('has-error')
                                }
                                $('#id_'+field).next().text(error_list[0]).css('color','red');
                                $('#id_'+field).parent().addClass('has-error')
                            })
                        }
                    }
    
                })
    
            })
            
    
        </script>
    </body>
    </html>
    reg.html
    from django import forms
    from django.forms import widgets,ValidationError
    
    from app01.models import UserInfo
    
    class RegForm(forms.Form):
        user = forms.CharField(max_length=8,label='用户名',
                            widget=widgets.TextInput(attrs={'class':'form-control'}))
        pwd = forms.CharField(min_length=4,label='密码',
                              widget=widgets.PasswordInput(attrs={'class':'form-control'}))
        repeat_pwd = forms.CharField(min_length=4,label='确认密码',
                              widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        email = forms.EmailField(label='邮箱',
                             widget=widgets.EmailInput(attrs={'class': 'form-control'}))
    
        # 局部钩子
        def clean_user(self):
            val = self.cleaned_data.get('user')
    
            ret = UserInfo.objects.filter(username = val)
            if not ret:
                return val
            else:
                raise ValidationError('该用户已存在')
    
        # 校验局部钩子得时候 没有办法 拿到 所有得干净数据,
        # 如何 校验 两个 字段呢! 全局钩子
    
        # 全局钩子 能得到 任何一个干净得 数据   def clean(self):return self.cleaned_data
        def clean(self):
            if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
    
    
    from django.http import JsonResponse
    
    def reg(request):
        if request.method == 'POST':
            res = {'user':None,'error_dict':None}
            form = RegForm(request.POST)
    
            if form.is_valid():
                print("clean:",form.cleaned_data)  # {"user":'yuan','pwd':"123"}
                print(request.FILES)
    
                user = form.cleaned_data.get('user')
                pwd = form.cleaned_data.get('pwd')
                email = form.cleaned_data.get('email')
                avatar = request.FILES.get('avatar')
                if avatar:
                    # 接受文件对象  将avatar文件对象下载到avatar字段对应的upload_to指定路径 没指定在 根目录下
                    user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
                else:
                    user = UserInfo.objects.create_user(username=user, password=pwd, email=email)
    
                res['user'] = user.username
    
            else:
                print('error:',form.errors)  #{"repear_pwd":['',''],"email":['',''],}
                res['error_dict'] = form.errors
    
            return JsonResponse(res)
    
        form = RegForm()
        return render(request,'reg.html',locals())
    views.py
    知识点1:
                 jquery对象[0]
    jquery对象------------------>DOM
              <------------------
                   $(DOM)
    知识点2:
        请求形式:
            form   get
            form   post
            ajax   get
            ajax   post
            a标签  get
            地址栏 get
        注意:
            form只有 get post
            ajax 有  get post put delete ...
                查看 get  修改 post  (增 post 删 delete 更新 put)
    
    知识点3:                                   url_encoded
        http请求协议:{"user":"alex","pwd":123}-------------->"user=alex&pwd=123"
                                                   form-data
                      {"user":"alex","avatar":obj}----------->
    
        "GET HTTP1.1 /upload/
     content—type='url_encoded'
    
    user=alex&pwd=123"
    
        请求头:
            Content—Type:告诉服务器这次请求数据的格式,默认值:url_encoded
            if 上传文件:Content—Type=form-data
    
    知识点4:
        form对象渲染样式:
              #方式1:
                  {{form.as_p}}
              #方式2:
                  {{form.user}}
              #方式3:
                   {% for field in form %}
                   <div>
                       <label for="">{{ field.label }}</label>
                       <div>
                           {{ field }}
                       </div>
                   </div>
                   {% endfor %}
    
    博客系统的登录
        ---- 基于PIL模块实现的验证码图片
        ---- 基于session保存验证码
        ---- 刷新验证码
    
    博客系统的注册
        基于ajax和form组件实现注册
    
        ---设计注册页面
    
    
        self.fields:{"字段":字段规则}
        form.is_valid():
             self.errors={}
             self.clean_data={}
    
        UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
    
        将avatar文件对象下载到avatar字段对应的upload_to指定路径
    
    
    (1)    media配置:
        针对:
            avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
            avatar = models.ImageField(upload_to='avatars/', default="/avatars/default.png")
        MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media")
    
    
    (2) MEDIA_URL="/media/"
        # media 配置
        url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
    笔记
  • 相关阅读:
    RequireJS进阶(二)
    JavaScript判断元素为数字的奇异写法
    RequireJS进阶(三)
    RequireJS进阶(一)
    读Ext之十四(Ext元素)
    JavaScript中__proto__与prototype的关系
    工作流术语
    一个例子(Hello World)
    无题
    再谈调用子流程(1)
  • 原文地址:https://www.cnblogs.com/alice-bj/p/9124336.html
Copyright © 2011-2022 走看看