zoukankan      html  css  js  c++  java
  • Web框架开发-BBS(表、登录、注册、文件上传)

    一、博客系统表关系

     

     models.py

    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    # Create your models here.
    
    
    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_name = models.CharField(verbose_name='站点名称', max_length=64)
        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='创建时间', auto_now_add=True)
        content = models.TextField()
    
        comment_count = models.IntegerField(default=0)
        up_count = models.IntegerField(default=0)
        down_count = models.IntegerField(default=0)
    
        user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
        category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
        tags = models.ManyToManyField(
            to="Tag",
            through='Article2Tag',
            through_fields=('article', 'tag'),
        )
    
        def __str__(self):
            return self.title
    
    
    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)
        user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
        article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
        content = models.CharField(verbose_name='评论时间', max_length=255)
    
        parent_comment = models.ForeignKey("self", null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.content
    

      

    同步数据库:

    python manage.py makemigrations

    python manage.py migrate

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

    登录页面

     验证码获取:

    方式一:

    def get_valid_code_img(request):
    
        # 方式1:
        with open("lufei.jpg","rb") as f:
            data=f.read()
        return HttpResponse(data)
    

      

    方式二:

    from PIL import Image
        img = Image.new("RGB", (270, 40),color=get_random_color())
    
        with open("validCode.png", "wb") as f:
            img.save(f,"png")
    
        with open("validCode.png", "rb") as f:
            data = f.read()
        return HttpResponse(data)
    

      

    方式三:

    from PIL import Image
        from io import BytesIO
    
        img = Image.new("RGB", (270, 40), color=get_random_color())
        f = BytesIO()
        img.save(f, "png")
        data=f.getvalue()
        return HttpResponse(data)
    

      

    方式四:

      img = Image.new("RGB", (270, 40), color=get_random_color())
    
        draw = ImageDraw.Draw(img)
    
        kumo_font = ImageFont.truetype("static/font/KumoFont.ttf", size=20)
    
        valid_code_str = ""
        for i in range(5):
            random_num = str(random.randint(0, 9))
            random_low_alpha = chr(random.randint(95, 122))
            random_upper_alpha = chr(random.randint(65, 90))
            random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
            draw.text((20 + i * 50, 15), random_char, get_random_color(), font=kumo_font)
    
            # 保存验证码字符串
            valid_code_str += random_char
    
        # width = 270
        # height = 40
        # for i in range(5):
        #     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(10):
        #     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+4, y+4), 0, 90, fill=get_random_color())
    
        print("valid_code_str", valid_code_str)
        request.session["valid_code_str"] = valid_code_str
    
        f = BytesIO()
        img.save(f, "png")
        data = f.getvalue()
    
        return data
    

      

    验证码正确,并登录之后

    <li><a href="#"><span id="user_icon"
                                              class="glyphicon glyphicon-user"></span>{{ request.user.username }} </a> </li>
    

      

    登录验证

    <script src="/static/jquery-3.3.1.js"></script>
    <script>
        // 刷新验证码
        $("#valid_code_img").click(function () {
            $(this)[0].src += "?"
    
        });
    
        // 登录验证
        $(".login_btn").click(function () {
    
            $.ajax({
                url: "",
                type: "post",
                data: {
                    user: $("#user").val(),
                    pwd: $("#pwd").val(),
                    valid_code: $("#valid_code").val(),
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                },
                success: function (data) {
                    console.log(data);
    
                    if (data.user){
                        if (location.search){
                            location.href = location.search.slice(6)
                        }
                        else {
                            location.href = "/index/"
                        }
                    }
                    else {
                        $(".error").text(data.msg).css({"color": "red", "margin-left": "10px"});
                        setTimeout(function () {
                            $(".error").text("");
    
                        }, 1000)
                    }
    
                }
            })
    
        })
    

      

    完整的示例:

      1 from django.contrib.auth.models import AbstractUser
      2 from django.db import models
      3 
      4 # Create your models here.
      5 
      6 
      7 class UserInfo(AbstractUser):
      8     """
      9     用户信息
     10     """
     11     nid = models.AutoField(primary_key=True)
     12     telephone = models.CharField(max_length=11, null=True, unique=True)
     13     avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
     14     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     15 
     16     blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)
     17 
     18     def __str__(self):
     19         return self.username
     20 
     21 
     22 class Blog(models.Model):
     23     """
     24     博客信息表(站点表)
     25     """
     26     nid = models.AutoField(primary_key=True)
     27     title = models.CharField(verbose_name='个人博客标题', max_length=64)
     28     site_name = models.CharField(verbose_name='站点名称', max_length=64)
     29     theme = models.CharField(verbose_name='博客主题', max_length=32)
     30 
     31     def __str__(self):
     32         return self.title
     33 
     34 
     35 class Category(models.Model):
     36     """
     37     博主个人文章分类表
     38     """
     39     nid = models.AutoField(primary_key=True)
     40     title = models.CharField(verbose_name='分类标题', max_length=32)
     41     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
     42 
     43     def __str__(self):
     44         return self.title
     45 
     46 
     47 class Tag(models.Model):
     48     nid = models.AutoField(primary_key=True)
     49     title = models.CharField(verbose_name='标签名称', max_length=32)
     50     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
     51 
     52     def __str__(self):
     53         return self.title
     54 
     55 
     56 class Article(models.Model):
     57     nid = models.AutoField(primary_key=True)
     58     title = models.CharField(max_length=50, verbose_name='文章标题')
     59     desc = models.CharField(max_length=255, verbose_name='文章描述')
     60     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     61     content = models.TextField()
     62 
     63     comment_count = models.IntegerField(default=0)
     64     up_count = models.IntegerField(default=0)
     65     down_count = models.IntegerField(default=0)
     66 
     67     user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
     68     category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
     69     tags = models.ManyToManyField(
     70         to="Tag",
     71         through='Article2Tag',
     72         through_fields=('article', 'tag'),
     73     )
     74 
     75     def __str__(self):
     76         return self.title
     77 
     78 
     79 class Article2Tag(models.Model):
     80     nid = models.AutoField(primary_key=True)
     81     article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE)
     82     tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE)
     83 
     84     class Meta:
     85         unique_together = [
     86             ('article', 'tag'),
     87         ]
     88 
     89     def __str__(self):
     90         v = self.article.title + "---" + self.tag.title
     91         return v
     92 
     93 
     94 class ArticleUpDown(models.Model):
     95     """
     96     点赞表
     97     """
     98     nid = models.AutoField(primary_key=True)
     99     user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)
    100     article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
    101     is_up = models.BooleanField(default=True)
    102 
    103     class Meta:
    104         unique_together = [
    105             ('article', 'user')
    106         ]
    107 
    108 
    109 class Comment(models.Model):
    110     """
    111     评论表
    112     """
    113     nid = models.AutoField(primary_key=True)
    114     user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    115     article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
    116     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    117     content = models.CharField(verbose_name='评论时间', max_length=255)
    118 
    119     parent_comment = models.ForeignKey("self", null=True, on_delete=models.CASCADE)
    120 
    121     def __str__(self):
    122         return self.content
    models.py
      1 from django.contrib import auth
      2 from django.http import JsonResponse, HttpResponse
      3 from django.shortcuts import render
      4 
      5 # Create your views here.
      6 from blog import models
      7 from blog.Myforms import UserForm
      8 from blog.models import UserInfo
      9 from blog.utils import validCode
     10 
     11 
     12 def login(request):
     13     """
     14     登录视图函数
     15         get请求响应页面
     16         post(Ajax)请求响应字典
     17     :param request:
     18     :return
     19     """
     20     if request.method == "POST":
     21         response = {"user": None, "msg": None}
     22         user = request.POST.get("user")
     23         pwd = request.POST.get("pwd")
     24         valid_code = request.POST.get("valid_code")
     25 
     26         valid_code_str = request.session.get("valid_code_str")
     27         if valid_code.upper() == valid_code_str.upper():
     28             user = auth.authenticate(username=user, password=pwd)
     29             if user:
     30                 auth.login(request, user)
     31                 response["user"] = user.username
     32             else:
     33                 response["msg"] = "用户名或密码错误"
     34 
     35         else:
     36             response["msg"] = "验证码错误!"
     37 
     38         return JsonResponse(response)
     39     return render(request, "login.html")
     40 
     41 
     42 def index(request):
     43     """
     44     系统首页
     45     :param request:
     46     :return:
     47     """
     48     article_list = models.Article.objects.all()
     49     return render(request, "index.html", {"article_list": article_list})
     50 
     51 
     52 def get_valid_code_img(request):
     53     """
     54     基于PIL模块动态生成响应状态码图片
     55     :param request:
     56     :return:
     57     """
     58     img_data = validCode.get_valid_code_img(request)
     59     return HttpResponse(img_data)
     60 
     61 
     62 def register(request):
     63     """
     64     注册视图函数:
     65         get请求响应注册页面
     66         POst(Ajax)请求,校验字段,响应字典
     67     :param request:
     68     :return:
     69     """
     70     if request.is_ajax():
     71         print(request.POST)
     72         form = UserForm(request.POST)
     73 
     74         response = {"user": None, "msg": None}
     75         if form.is_valid():
     76             response["user"] = form.cleaned_data.get("user")
     77 
     78             # 生成一条用户记录
     79             user = form.cleaned_data.get("user")
     80             print("user", user)
     81             pwd = form.cleaned_data.get("pwd")
     82             email = form.cleaned_data.get("email")
     83             avatar_obj = request.FILES.get("avater")
     84 
     85             extra = {}
     86             if avatar_obj:
     87                 extra["avatar"] = avatar_obj
     88             UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
     89 
     90         else:
     91             print(form.cleaned_data)
     92             print(form.errors)
     93             response["msg"] = form.errors
     94 
     95         return JsonResponse(response)
     96 
     97     form = UserForm()
     98     return render(request, "register.html", {"form": form})
     99 
    100 
    101     return render(request, "register.html")
    views.py
     1 # -*- encoding: utf-8 -*-
     2 # @Time    : 2018-09-24 20:52
     3 # @Author  : mike.liu
     4 # @File    : validCode.py
     5 import random
     6 from io import BytesIO
     7 
     8 from PIL import Image, ImageDraw, ImageFont
     9 
    10 
    11 def get_random_color():
    12     return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    13 
    14 
    15 def get_valid_code_img(request):
    16     # 方式1:
    17     # with open("lufei.jpg", "rb") as f:
    18     #     data = f.read()
    19 
    20     # 方式2: # pip install pillow
    21 
    22     # from PIL import Image
    23     # img = Image.new("RGB", (270, 40),color=get_random_color())
    24     #
    25     # with open("validCode.png", "wb") as f:
    26     #     img.save(f,"png")
    27     #
    28     # with open("validCode.png", "rb") as f:
    29     #     data = f.read()
    30 
    31     # 方式3:
    32 
    33     # from PIL import Image
    34     # from io import BytesIO
    35     #
    36     # img = Image.new("RGB", (270, 40), color=get_random_color())
    37     # f = BytesIO()
    38     # img.save(f, "png")
    39     # data=f.getvalue()
    40 
    41     # 方式4:
    42 
    43     img = Image.new("RGB", (270, 40), color=get_random_color())
    44 
    45     draw = ImageDraw.Draw(img)
    46 
    47     kumo_font = ImageFont.truetype("static/font/KumoFont.ttf", size=20)
    48 
    49     valid_code_str = ""
    50     for i in range(5):
    51         random_num = str(random.randint(0, 9))
    52         random_low_alpha = chr(random.randint(95, 122))
    53         random_upper_alpha = chr(random.randint(65, 90))
    54         random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
    55         draw.text((20 + i * 50, 15), random_char, get_random_color(), font=kumo_font)
    56 
    57         # 保存验证码字符串
    58         valid_code_str += random_char
    59 
    60     # width = 270
    61     # height = 40
    62     # for i in range(5):
    63     #     x1 = random.randint(0, width)
    64     #     x2 = random.randint(0, width)
    65     #     y1 = random.randint(0, height)
    66     #     y2 = random.randint(0, height)
    67     #     draw.line((x1, y1, x2, y2), fill=get_random_color())
    68     #
    69     # for i in range(10):
    70     #     draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
    71     #     x = random.randint(0, width)
    72     #     y = random.randint(0, height)
    73     #     draw.arc((x, y, x+4, y+4), 0, 90, fill=get_random_color())
    74 
    75     print("valid_code_str", valid_code_str)
    76     request.session["valid_code_str"] = valid_code_str
    77 
    78     f = BytesIO()
    79     img.save(f, "png")
    80     data = f.getvalue()
    81 
    82     return data
    validCode.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>登录页面</title>
     6     <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
     7 </head>
     8 <body>
     9 <h3>登录页面</h3>
    10 <div class="container">
    11     <div class="row">
    12         <div class="col-md-push-6 col-lg-offset-3">
    13              <form>
    14                  {% csrf_token %}
    15                  <div class="form-group">
    16                      <label for="user">用户名</label>
    17                      <input type="text" id="user" class="form-control">
    18                  </div>
    19                  <div class="form-group">
    20                      <label for="pwd">密码</label>
    21                      <input type="password" id="pwd" class="form-control">
    22                  </div>
    23 
    24                  <div class="form-group">
    25                      <label for="pwd">验证码</label>
    26                      <div class="row">
    27                          <div class="col-md-6">
    28                              <input type="text" class="form-control" id="valid_code">
    29                          </div>
    30                          <div class="col-md-6">
    31                              <img width="270" height="36" id="valid_code_img" src="/get_validCode_img/" alt="">
    32                          </div>
    33                      </div>
    34                  </div>
    35                  <input type="button" class="btn btn-default login_btn" value="登录"><span class="error"></span>
    36                  <a href="/register/" class="btn btn-success pull-right">注册</a>
    37              </form>
    38         </div>
    39     </div>
    40 </div>
    41 <script src="/static/jquery-3.3.1.js"></script>
    42 <script>
    43     // 刷新验证码
    44     $("#valid_code_img").click(function () {
    45         $(this)[0].src += "?"
    46 
    47     });
    48 
    49     // 登录验证
    50     $(".login_btn").click(function () {
    51 
    52         $.ajax({
    53             url: "",
    54             type: "post",
    55             data: {
    56                 user: $("#user").val(),
    57                 pwd: $("#pwd").val(),
    58                 valid_code: $("#valid_code").val(),
    59                 csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
    60             },
    61             success: function (data) {
    62                 console.log(data);
    63 
    64                 if (data.user){
    65                     if (location.search){
    66                         location.href = location.search.slice(6)
    67                     }
    68                     else {
    69                         location.href = "/index/"
    70                     }
    71                 }
    72                 else {
    73                     $(".error").text(data.msg).css({"color": "red", "margin-left": "10px"});
    74                     setTimeout(function () {
    75                         $(".error").text("");
    76 
    77                     }, 1000)
    78                 }
    79 
    80             }
    81         })
    82 
    83     })
    84 </script>
    85 
    86 </body>
    87 </html>
    login.html

    三、form表单、Ajax文件上传

    基于form表单提交数据:

    [27/Sep/2018 12:27:42] "GET /upload/ HTTP/1.1" 200 487
    <QueryDict: {'csrfmiddlewaretoken': ['0XhktJJdewNa5wfoRonIbGzlltmBMCASk8wG0IVb7EyR0XBQRcksDfEde3OEkrvB'], 'user': ['']}>
    <MultiValueDict: {'avatar': [<InMemoryUploadedFile: 106.jpeg (image/jpeg)>]}>
    [27/Sep/2018 12:29:03] "POST /upload/ HTTP/1.1" 200 2

    基于Ajax提交数据:

    <QueryDict: {'user': ['mike'], 'csrfmiddlewaretoken': ['jmCZMYoTXSx01aIFnQtmaBFRCz33vMlgDxRljXARQ0iHWB47nEq6CaKJv9v63BgZ']}>
    <MultiValueDict: {'avatar': [<InMemoryUploadedFile: 100.jpeg (image/jpeg)>]}>
    [28/Sep/2018 00:22:46] "POST /upload/ HTTP/1.1" 200 2

    四、form表单的注册页面

    图片预览:

    头像默认图片

      .avatar_img {
                60px;
                height:60px;
                margin-left: 20px;
            }
            #avatar {
                display: none;
            }
    

      

    <div class="form-group">
                        <label for="avatar">
                            头像
                            <img class="avatar_img"  src="../static/blog/img/default.png" alt="">
                        </label>
                        <input type="file" id="avatar" name="avatar">
                    </div>
    

      图像预览

      // 头像预览
        $("#avatar").change(function () {
    
            // 获取用户选中的文件对象
            var file_obj = $(this)[0].files[0];
            // 获取文件对象的路径
            var reader = new FileReader();
            reader.readAsDataURL(file_obj);
            // 修改img的src属性, src= 文件对象的路径
            reader.onload = function () {
                $(".avatar_img").attr("src", reader.result)
    
            };
    
        });
    

      

    注意:

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

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

    Ajax注册:

      

    class UserForm(forms.Form):
    
        user = forms.CharField(max_length=32,
                               error_messages={"required": "该字段不能为空!"},
                               label="用户名",
                               widget=widgets.TextInput(attrs={"class": "form-control"},)
                               )
        pwd = forms.CharField(max_length=32,
                              error_messages={"required": "该字段不能为空!"},
                              label="密码",
                              widget=widgets.PasswordInput(attrs={"class": "form-control"},)
                              )
        re_pwd = forms.CharField(max_length=32,
                                 error_messages={"required": "该字段不能为空!"},
                                 label="确认密码",
                                 widget=widgets.PasswordInput(attrs={"class": "form-control"},)
                                 )
        email = forms.EmailField(max_length=32,
                                 error_messages={"required": "该字段不能为空!"},
                                 label="邮箱",
                                 widget=widgets.EmailInput(attrs={"class": "form-control"},)
                                 )
        # 局部钩子
        def clean_user(self):
            val = self.cleaned_data.get("user")
    
            user = UserInfo.objects.filter(username=val).first()
            if not user:
                return val
            else:
                raise ValidationError("该用户已注册!")
    
        # 校验局部钩子的时候,没有办法拿到所有的数据
        # 任何校验两个字段?全局钩子
        
        # 全局钩子得到任何一个干净的数据
    
        def clean(self):
            pwd = self.cleaned_data.get("pwd")
            re_pwd = self.cleaned_data.get("re_pwd")
    
            if pwd and re_pwd:
                if pwd == re_pwd:
                    return self.cleaned_data
                else:
                    raise ValidationError("两次密码不一致!")
            else:
                return self.cleaned_data
    

      

    def register(request):
        """
        注册视图函数:
            get请求响应注册页面
            POst(Ajax)请求,校验字段,响应字典
        :param request:
        :return:
        """
        if request.is_ajax():
            print(request.POST)
            form = UserForm(request.POST)
    
            response = {"user": None, "msg": None}
            if form.is_valid():
                response["user"] = form.cleaned_data.get("user")
    
                # 生成一条用户记录
                user = form.cleaned_data.get("user")
                print("user", user)
                pwd = form.cleaned_data.get("pwd")
                email = form.cleaned_data.get("email")
                avatar_obj = request.FILES.get("avater")
    
                extra = {}
                if avatar_obj:
                    extra["avatar"] = avatar_obj
                UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
    
            else:
                print(form.cleaned_data)
                print(form.errors)
                response["msg"] = form.errors
    
            return JsonResponse(response)
    
        form = UserForm()
        return render(request, "register.html", {"form": form})
    
    
        return render(request, "register.html")
    

      

     // 基于ajax提交数据
        $(".reg_btn").click(function () {
            // console.log($("#form").serializeArrray());
            var formdata = new FormData();
            var request_data = $("#form").serializeArray();
            $.each(request_data, function (index, data) {
                formdata.append(data.name, data.value)
    
            });
            formdata.append("avatar", $("#avatar")[0].files[0]);
            $.ajax({
                url:"",
                type: "post",
                contentType: false,
                processData: false,
                data: formdata,
                success: function (data) {
    
                    if(data.user){
                        // 注册成功
                        location.href="/login/"
                    }
                    else {
                        // 注册失败
                        //console.log(data.msg)
                        // 清空错误信息
                        $("span.error").html("");
                        $(".form-group").removeClass("has-error");
    
                        // 展示本次提交的错误信息
                        $.each(data.msg, function (field, error_list) {
                            console.log(field, error_list);
                            if (field=="__all__"){
                                $("#id_re_pwd").next().html(error_list[0]).parent().addClass("has-error");
    
                            }
                            $("#id_" + field).next().html(error_list[0]);
                            $("#id_" + field).parent().addClass("has-error");
    
                        })
                    }
    
                }
            })
    
        })
    

      

    注意:

    1、局部钩子 与 全局钩子

    def clean_user(self): pass  局部钩子只能校验某一个字段
    def clean(self):    可以校验两个不同的字段,全局钩子,能得到任何一个干净的数据
    
    局部钩子得源码:
    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、上传文件

     var formdata = new FormData();
            var request_data = $("#form").serializeArray();
            $.each(request_data, function (index, data) {
                formdata.append(data.name, data.value)
    
            });
            formdata.append("avatar", $("#avatar")[0].files[0]);    // 文件对象
            $.ajax({
                url:"",
                type: "post",
                contentType: false,
                processData: false,
                data: formdata,
                success: function (data) {
    

      3、Ajax的局部刷新:

    注册失败:

    1、清空错误信息
                        $("span.error").html("");
                        $(".form-group").removeClass("has-error");
    
                        
    2、加载错误信息
            // 展示本次提交的错误信息
                        $.each(data.msg, function (field, error_list) {
                            console.log(field, error_list);
                            // 全局的错误信息
                            if (field=="__all__"){
                                $("#id_re_pwd").next().html(error_list[0]).parent().addClass("has-error");
    
                            }
                            $("#id_" + field).next().html(error_list[0]);
                            $("#id_" + field).parent().addClass("has-error");
    
                        })    
    

      

    4、上传文件的存放地址:media配置

    前端:
    formdata.append("avatar", $("#avatar")[0].files[0]);    // 文件对象
    
    
    后台:
            extra = {}
                if avatar_obj:
                    extra["avatar"] = avatar_obj
                UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
        
    

      

    知识点:

      静态文件/static/css..js..img.. 用户可直接URL访问得到

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

      用户文件:

      settings里面配置:

      # 与用户上传相关的配置

      MEDIA_ROOT=os.path.join(BASE_DIR,"media")
      MEDIA_URL="/media/"

      路由配置:urls.py

    # media配置:
        re_path(r"media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT})
    

      

      media配置之后:

        用户可以直接访问

    数据库的文件保存还是相对路径:

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册页面</title>
        <link rel="stylesheet" href="../static/bootstrap-3.3.7/css/bootstrap.css">
        <script src="../static/jquery-3.3.1.js"></script>
    
        <style>
            .avatar_img {
                width:60px;
                height:60px;
                margin-left: 20px;
            }
            #avatar {
                display: none;
            }
            .error {
                color: red;
            }
        </style>
    </head>
    <body>
    <h3>注册页面</h3>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
    
                <form id="form">
                    {% csrf_token %}
    
                    {% for field in form %}
                        <div class="form-group">
                            <label for="{{ field.auto_id }}">{{ field.label }}</label>
                            {{ field }} <span class="error pull-right"></span>
                        </div>
                    {% endfor %}
    
                    <div class="form-group">
                        <label for="avatar">
                            头像
                            <img class="avatar_img"  src="/static/blog/img/default.png" alt="">
                        </label>
                        <input type="file" id="avatar" name="avatar">
                    </div>
                    <input type="button" class="btn btn-default reg_btn" value="提交"> <span class="error"></span>
                </form>
            </div>
        </div>
    </div>
    
    <script>
        // 头像预览
        $("#avatar").change(function () {
    
            // 获取用户选中的文件对象
            var file_obj = $(this)[0].files[0];
            // 获取文件对象的路径
            var reader = new FileReader();
            reader.readAsDataURL(file_obj);
            // 修改img的src属性, src= 文件对象的路径
            reader.onload = function () {
                $(".avatar_img").attr("src", reader.result)
    
            };
    
        });
    
        // 基于ajax提交数据
        $(".reg_btn").click(function () {
            // console.log($("#form").serializeArrray());
            var formdata = new FormData();
            var request_data = $("#form").serializeArray();
            $.each(request_data, function (index, data) {
                formdata.append(data.name, data.value)
    
            });
            formdata.append("avatar", $("#avatar")[0].files[0]);    // 文件对象
            $.ajax({
                url:"",
                type: "post",
                contentType: false,
                processData: false,
                data: formdata,
                success: function (data) {
    
                    if(data.user){
                        // 注册成功
                        location.href="/login/"
                    }
                    else {
                        // 注册失败
                        //console.log(data.msg)
                        // 清空错误信息
                        $("span.error").html("");
                        $(".form-group").removeClass("has-error");
    
                        // 展示本次提交的错误信息
                        $.each(data.msg, function (field, error_list) {
                            console.log(field, error_list);
                            // 全局的错误信息
                            if (field=="__all__"){
                                $("#id_re_pwd").next().html(error_list[0]).parent().addClass("has-error");
    
                            }
                            $("#id_" + field).next().html(error_list[0]);
                            $("#id_" + field).parent().addClass("has-error");
    
                        })
                    }
    
                }
            })
    
        })
    </script>
    </body>
    </html>
    register.html
     1 def register(request):
     2     """
     3     注册视图函数:
     4         get请求响应注册页面
     5         POst(Ajax)请求,校验字段,响应字典
     6     :param request:
     7     :return:
     8     """
     9     if request.is_ajax():
    10         print(request.POST)
    11         form = UserForm(request.POST)
    12 
    13         response = {"user": None, "msg": None}
    14         if form.is_valid():
    15             response["user"] = form.cleaned_data.get("user")
    16 
    17             # 生成一条用户记录
    18             user = form.cleaned_data.get("user")
    19             print("user", user)
    20             pwd = form.cleaned_data.get("pwd")
    21             email = form.cleaned_data.get("email")
    22             avatar_obj = request.FILES.get("avatar")
    23 
    24             extra = {}
    25             if avatar_obj:
    26                 extra["avatar"] = avatar_obj
    27             UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
    28 
    29         else:
    30             print(form.cleaned_data)
    31             print(form.errors)
    32             response["msg"] = form.errors
    33 
    34         return JsonResponse(response)
    35 
    36     form = UserForm()
    37     return render(request, "register.html", {"form": form})
    38 
    39 
    40     return render(request, "register.html")
    views.py

      

  • 相关阅读:
    使用NPOI读取Excel表格内容并进行修改
    JSON.parse()和JSON.stringify()
    切图时图片的选择:JPG、PNG、GIF的区别
    用js把数据从一个页面传到另一个页面
    iframe中positioin:fixed失效问题
    YUV格式&像素
    JS中插入节点的方法appendChild和insertBefore的应用
    CSS的相对定位和就对定位
    CSS中的相对定位和绝对定位
    POJ-1734
  • 原文地址:https://www.cnblogs.com/mike-liu/p/9703325.html
Copyright © 2011-2022 走看看