Django---博客项目实战

Posted sanqiansi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django---博客项目实战相关的知识,希望对你有一定的参考价值。

 

 

1.urls

from django.conf.urls import url
from django.contrib import admin
from blog import views
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^login/, views.login),
    url(r^get_valid_code/, views.get_valid_code),
    url(r^register/, views.register),
    url(r^check_username/, views.check_username),
    url(r^index/, views.index),
    url(r^logout/, views.logout),
]

2.settings

"""
Django settings for BBS project.

Generated by ‘django-admin startproject‘ using Django 1.11.25.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = kujfnfd#)my=#u$o(kj__^$_opl^ro=&525*fmki1wpf2z6r2v

# SECURITY WARNING: don‘t run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,
    blog.apps.BlogConfig,
]

MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    django.middleware.csrf.CsrfViewMiddleware,
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
]

ROOT_URLCONF = BBS.urls

TEMPLATES = [
    {
        BACKEND: django.template.backends.django.DjangoTemplates,
        DIRS: [os.path.join(BASE_DIR, templates)]
        ,
        APP_DIRS: True,
        OPTIONS: {
            context_processors: [
                django.template.context_processors.debug,
                django.template.context_processors.request,
                django.contrib.auth.context_processors.auth,
                django.contrib.messages.context_processors.messages,
            ],
        },
    },
]

WSGI_APPLICATION = BBS.wsgi.application

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    default: {
        ENGINE: django.db.backends.mysql,
        NAME: bbs,
        HOST: 127.0.0.1,
        PORT: 3306,
        USER: root,
        PASSWORD: ,
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.MinimumLengthValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.CommonPasswordValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.NumericPasswordValidator,
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

# LANGUAGE_CODE = ‘en-us‘
LANGUAGE_CODE = zh-hans

TIME_ZONE = Asia/Shanghai

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, javascript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

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

AUTH_USER_MODEL = blog.UserInfo

 

3.models

from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.
# UserInfo这个表,继承AbstractUser,因为要用auth组件


class UserInfo(AbstractUser):
    nid = models.AutoField(primary_key=True)
    # blank=True 只是admin中表单提交的时候,做校验,如果设置成True,就是不校验了
    phone = models.CharField(max_length=32, null=True, blank=True)
    # upload_to需要传一个路径(文件夹自动创建)
    avatar = models.FileField(upload_to=avatar/, default=/static/img/default.png/)
    blog = models.OneToOneField(to=Blog, to_field=nid, null=True)

    class Meta:
        # admin中显示表名
        verbose_name = 用户信息表
        # 表名去掉s
        verbose_name_plural = verbose_name


class Blog(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    site_name = models.CharField(max_length=32)
    theme = models.CharField(max_length=64)

    def __str__(self):
        return self.site_name


class Category(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    blog = models.ForeignKey(to=Blog, to_field=nid, null=True)

    def __str__(self):
        return self.title


class Tag(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    blog = models.ForeignKey(to=Blog, to_field=nid, null=True)


class Article(models.Model):
    nid = models.AutoField(primary_key=True)
    # verbose_name=‘文章标题   修改admin中表单的文字显示
    title = models.CharField(max_length=64, verbose_name=文章标题)
    desc = models.CharField(max_length=255)
    # 大文本TextField()
    content = models.TextField()

    create_time = models.DateTimeField(auto_now_add=True)

    # 因为查询多,写入少,所以加这三个字段,以后不需要再连表查询了
    commit_num=models.IntegerField(default=0)
    up_num=models.IntegerField(default=0)
    down_num=models.IntegerField(default=0)

    blog = models.ForeignKey(to=Blog, to_field=nid, null=True)
    category = models.ForeignKey(to=Category, to_field=nid, null=True)
    tag = models.ManyToManyField(to=Tag, through=ArticleToTag, through_fields=(article, tag))

    def __str__(self):
        return self.title


# 手动创建第三张表
class ArticleToTag(models.Model):
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to=Article, to_field=nid)
    tag = models.ForeignKey(to=Tag, to_field=nid)


class Commit(models.Model):
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to=UserInfo, to_field=nid)
    article = models.ForeignKey(to=Article, to_field=nid)
    content = models.CharField(max_length=255)
    create_time = models.DateTimeField(auto_now_add=True)
    # 这样写是可以的
    # parent_id=models.IntegerField()
    # 自关联
    # parent_id=models.ForeignKey(to=‘Commit‘,to_field=‘nid‘)
    parent = models.ForeignKey(to=self, to_field=nid, null=True,blank=True)


class UpAndDown(models.Model):
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to=UserInfo, to_field=nid)
    article = models.ForeignKey(to=Article, to_field=nid)
    is_up = models.BooleanField()

    class Meta:
        # 联合唯一,只是为了不写脏数据
        unique_together = ((user, article),)

4.blog/myforms.py

from django import forms
from django.forms import widgets
from blog import models
from django.core.exceptions import ValidationError


class RegForm(forms.Form):
    username = forms.CharField(max_length=18, min_length=2, label="用户名",
                               widget=widgets.TextInput(attrs={class: form-control}),
                               error_messages={"max_length": 字符长度超出限制, "min_length": 字符长度不够, "required": 用户名不能为空}
                               )
    password = forms.CharField(max_length=18, min_length=2, label="密码",
                               widget=widgets.PasswordInput(attrs={class: form-control}),
                               error_messages={"max_length": 字符长度超出限制, "min_length": 字符长度不够, "required": 密码不能为空}
                               )
    re_password = forms.CharField(max_length=18, min_length=2, label="确认密码",
                                  widget=widgets.PasswordInput(attrs={class: form-control}),
                                  error_messages={"max_length": 字符长度超出限制, "min_length": 字符长度不够, "required": 密码不能为空}
                                  )
    email = forms.EmailField(label="邮箱",
                             widget=widgets.TextInput(attrs={class: form-control}),
                             error_messages={"invalid": 格式不合法, "required": 邮箱为必填}
                             )

    # 局部校验钩子函数
    def clean_username(self):
        name = self.cleaned_data.get(username)
        # 去数据库校验
        ret = models.UserInfo.objects.filter(username=name).first()
        if ret:
            raise ValidationError(用户名已存在)
        return name

    # 全局校验钩子函数
    def clean(self):
        pwd = self.cleaned_data.get(password)
        re_pwd = self.cleaned_data.get(re_password)
        if pwd and re_pwd:
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError(两次密码不一致)

5.views

from django.shortcuts import render, HttpResponse,redirect
from PIL import Image, ImageDraw, ImageFont
import random
from io import BytesIO
# https://www.cnblogs.com/liuqingzheng/articles/10023849.html
from blog import myforms
from django.contrib import auth
from django.http import JsonResponse
from blog import models


# Create your views here.
def login(request):
    if request.method == GET:
        return render(request, login.html)
    # 判断前台发送的请求是不是ajax的请求
    elif request.is_ajax():
        response = {user: None, msg: None}
        name = request.POST.get(name)
        pwd = request.POST.get(pwd)
        valid_code = request.POST.get(valid_code)
        if valid_code.upper() == request.session.get(valid_code).upper():
            user = auth.authenticate(request, username=name, password=pwd)
            if user:
                # ajax请求,不能再返回render页面,或者redirect,只能返回字符串
                # 校验通过,一定要登录
                auth.login(request, user)
                response[user] = name
                response[msg] = 登录成功
            else:
                # 用户密码错误
                response[msg] = 用户名或密码错误
        else:
            response[msg] = 验证码错误
    return JsonResponse(response)


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


def get_valid_code(request):
    # pillow是一个图形处理的模块
    # 生成一张图片,模式,大小,颜色
    # img = Image.new(‘RGB‘, (320, 35), color=get_random_color())
    # # 保存到本地
    # with open(‘valid_code.png‘, ‘wb‘) as f:
    #     img.save(f, ‘png‘)
    # with open(‘valid_code.png‘, ‘rb‘) as f:
    #     data = f.read()
    # return HttpResponse(data)

    #     在内存中生成一个空文件(把它想象成open(‘valid_code.png‘,‘wb‘)as f:
    # 一个是在硬盘上一个是在内存中
    # img = Image.new(‘RGB‘, (320, 35), color=get_random_color())
    # f=BytesIO()
    # img.save(f,‘png‘)
    # data=f.getvalue()
    # return HttpResponse(data)

    img = Image.new(RGB, (320, 35), color=get_random_color())
    img_draw = ImageDraw.Draw(img)
    font = ImageFont.truetype(static/font/ss.ttf, size=25)
    random_code = ‘‘
    for i in range(5):
        char_num = random.randint(0, 9)
        char_lower = chr(random.randint(97, 122))
        char_upper = chr(random.randint(65, 90))
        char_str = str(random.choice([char_num, char_lower, char_upper]))
        # 坐标,文字,颜色,字体
        img_draw.text((i * 30 + 12, 0), char_str, get_random_color(), font=font)
        random_code += char_str
    # 把验证码保存到session 中
    request.session[valid_code] = random_code
    f = BytesIO()
    img.save(f, png)
    data = f.getvalue()
    return HttpResponse(data)


def register(request):
    if request.method == GET:
        my_form = myforms.RegForm()
        return render(request, register.html, {my_form: my_form})
    elif request.is_ajax():
        response = {status: 100, msg: None}
        print(request.POST)
        my_form = myforms.RegForm(request.POST)
        if my_form.is_valid():
            # 存数据,返回正确信息
            # 得用create_user()
            # 定义一个字典,把清理的数据赋给它
            dic = my_form.cleaned_data
            # 移除掉确认密码字段
            dic.pop(re_password)
            # 取出上传的文件对象
            my_file = request.FILES.get(my_file)
            if my_file:
                # 放到字典中
                dic[avatar] = my_file
            user = models.UserInfo.objects.create_user(**dic)
            print(user.username)
            response[url] = /login/
        else:
            # 返回错误信息
            response[status] = 101
            response[msg] = my_form.errors
        return JsonResponse(response)


def check_username(request):
    response = {status: 100, msg: None}
    name = request.POST.get(name)
    user = models.UserInfo.objects.filter(username=name).first()
    if user:
        response[status] = 101
        response[msg] = 用户名已被占用
    return JsonResponse(response)


def index(request):
    article_list=models.Article.objects.all().order_by(-create_time)
    return render(request,index.html,{article_list:article_list})


def logout(request):
    auth.logout(request)
    return redirect(/index/)

 

6.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>

    <title>博客园</title>
    <style>
        .article_bottom span {
            margin-right: 5px;
        }
    </style>
</head>
<body>
<div class="head">
    <nav class="navbar navbar-default">
        <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="#">博客园</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="#">随笔</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    {% if request.user.is_authenticated %}
                        <li><a href="#">{{ request.user.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="#">修改密码</a></li>
                                <li><a href="#">修改头像</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="/logout/">注销</a></li>
                            </ul>
                        </li>
                    {% else %}
                        <li><a href="/login/">登录</a></li>
                        <li><a href="/register/">注册</a></li>
                    {% endif %}

                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
</div>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-default">
                <div class="panel-heading">重金求子</div>
                <div class="panel-body">
                    请联系:8888888888888888888
                </div>
            </div>

            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">交友社区</h3>
                </div>
                <div class="panel-body">
                    <a href="http://www.baidu.com">请点击</a>
                </div>
            </div>
        </div>
        <div class="col-md-7">
            {% for article in article_list %}
                <div>
                    <h4><a href="">{{ article.title }}</a></h4>
                    <div class="media">
                        <div class="media-left">
                            <a href="#">
                                <img class="media-object" src="/static/img/default.png" alt="..." height="70" width="70">
                            </a>
                        </div>
                        <div class="media-body">
                            {{ article.desc }}
                        </div>
                    </div>
                <div style="margin-top: 10px;" class="article_bottom">
                    <span><a href="">{{ article.blog.userinfo.username }}</a></span>
                    <span>发布于 {{ article.create_time|date:"Y-m-d H:i:s" }}</span>
{#                    反向查询,一对多,按表名小写_set#}
                    <span class="glyphicon glyphicon-comment"><a href="">评论({{ article.commit_num}})</a></span>
                    <span class="glyphicon glyphicon-thumbs-up"><a href="">点赞({{ article.up_num }})</a></span>
                </div>
                </div>
            {% endfor %}

        </div>
        <div class="col-md-3">
            <div class="panel panel-default">
                <div class="panel-heading">重金求子</div>
                <div class="panel-body">
                    请联系:8888888888888888888
                </div>
            </div>

            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">交友社区</h3>
                </div>
                <div class="panel-body">
                    <a href="http://www.baidu.com">请点击</a>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

7.login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>

    <title>博客园</title>
    <style>
        .article_bottom span {
            margin-right: 5px;
        }
    </style>
</head>
<body>
<div class="head">
    <nav class="navbar navbar-default">
        <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="#">博客园</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="#">随笔</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    {% if request.user.is_authenticated %}
                        <li><a href="#">{{ request.user.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="#">修改密码</a></li>
                                <li><a href="#">修改头像</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="/logout/">注销</a></li>
                            </ul>
                        </li>
                    {% else %}
                        <li><a href="/login/">登录</a></li>
                        <li><a href="/register/">注册</a></li>
                    {% endif %}

                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
</div>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-default">
                <div class="panel-heading">重金求子</div>
                <div class="panel-body">
                    请联系:8888888888888888888
                </div>
            </div>

            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">交友社区</h3>
                </div>
                <div class="panel-body">
                    <a href="http://www.baidu.com">请点击</a>
                </div>
            </div>
        </div>
        <div class="col-md-7">
            {% for article in article_list %}
                <div>
                    <h4><a href="">{{ article.title }}</a></h4>
                    <div class="media">
                        <div class="media-left">
                            <a href="#">
                                <img class="media-object" src="/static/img/default.png" alt="..." height="70" width="70">
                            </a>
                        </div>
                        <div class="media-body">
                            {{ article.desc }}
                        </div>
                    </div>
                <div style="margin-top: 10px;" class="article_bottom">
                    <span><a href="">{{ article.blog.userinfo.username }}</a></span>
                    <span>发布于 {{ article.create_time|date:"Y-m-d H:i:s" }}</span>
{#                    反向查询,一对多,按表名小写_set#}
                    <span class="glyphicon glyphicon-comment"><a href="">评论({{ article.commit_num}})</a></span>
                    <span class="glyphicon glyphicon-thumbs-up"><a href="">点赞({{ article.up_num }})</a></span>
                </div>
                </div>
            {% endfor %}

        </div>
        <div class="col-md-3">
            <div class="panel panel-default">
                <div class="panel-heading">重金求子</div>
                <div class="panel-body">
                    请联系:8888888888888888888
                </div>
            </div>

            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">交友社区</h3>
                </div>
                <div class="panel-body">
                    <a href="http://www.baidu.com">请点击</a>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

 

8.register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>注册</title>
    <style>
        #my_file {
        {#把上传文件的控件隐藏#} display: none;
        }
    </style>
    {#    <script>#}
    {#        //等文档加载完毕之后,再进行操作#}
    {#        window.onload=function () {#}
    {#            #}
    {#        }#}
    {#    </script>#}
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>注册</h1>
            <form action="" id="form">
                {% csrf_token %}
                {% for foo in my_form %}
                    <div class="form-group">
                        <label for="{{ foo.auto_id }}">{{ foo.label }}</label>
                        {{ foo }} <span class="error pull-right" style="color: red;"></span>
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="my_file">头像
                        <img src="/static/img/default.png" alt="" width="80" height="80" id="img_file">
                    </label>

                    <input accept="image/*" type="file" id="my_file">
                </div>

                <input type="button" value="注册" class="btn btn-primary" id="btn"><span class="error"></span>
            </form>

        </div>
    </div>
</div>
</body>
<script>
    //这个控件指发生变化的事件
    $("#my_file").change(function () {
        //先取出文件(图片)
        var file_obj = $("#my_file")[0].files[0];
        //通过文件阅读器,把图片放到img标签上
        //生成一个文件阅读器对象
        var filereader = new FileReader()
        //把图片对象,读到filereader对象中
        filereader.readAsDataURL(file_obj)
        //filereader.result 这是filereader对象的值
        //
        //$("#img_file").attr(‘src‘,filereader.result)
        filereader.onload = function () {
            $("#img_file").attr(src, filereader.result)
        }

    })

    $("#btn").click(function () {
        //因为要上传文件,生成formdata对象
        var formdata = new FormData()
        /*
    formdata.append(‘name‘, $("#id_name").val())
    formdata.append(‘pwd‘, $("#id_pwd").val())
    formdata.append(‘re_pwd‘, $("#id_re_pwd").val())
    formdata.append(‘email‘, $("#id_email").val())
    formdata.append(‘email‘, $("#id_email").val())
    formdata.append(‘csrfmiddlewaretoken‘, $("[name=‘csrfmiddlewaretoken‘]").val())


    //把文件放到formdata中
    formdata.append(‘my_file‘, $("#my_file")[0].files[0])

         */

        //$("#form").serializeArray()把form表单打包,转成对象(列表套字典)
        var arr = $("#form").serializeArray()
        //jquery的循环,传参数:第一个参数是要循环的对象,第二个参数是一个匿名函数
        $.each(arr, function (k, v) {
            console.log(k)
            console.log(v)
            formdata.append(v.name, v.value)
        })
        //把文件放到formdata中
        formdata.append(my_file, $("#my_file")[0].files[0])
        console.log(arr)
        $.ajax({
            url: /register/,
            type: post,
            processData: false,
            contentType: false,
            data: formdata,
            success: function (data) {
                //console.log(data)
                if (data.status == 100) {
                    //location.href=‘/login/‘
                    location.href = data.url
                } else {
                    //在之前清除
                    $(".form-group").removeClass(has-error)
                    $(".error").html("")
                    $.each(data.msg, function (key, value) {
                        console.log(key, value)
                        //根据key,通过id取出控件
                        //原来取值
                        //$("#id_username").next().html()
                        //方式一
                        //$("#id_"+key).next().html(value[0])
                        //$("#id_"+key).parent().addClass(‘has-error‘)
                        //方式二
                        //处理两次密码不一致的情况
                        if (key==__all__){
                            $("#id_re_password").next().html(value[0])
                        }
                        $("#id_" + key).next().html(value[0]).parent().addClass(has-error)
                    })
/*
                    setTimeout(function () {
                        //清除掉父div的has-error
                        //清除掉错误信息(span里的内容)
                        $(".form-group").removeClass(‘has-error‘)
                        $(".error").html("")
                    }, 3000)

 */
                }
            }
        })
    })
    
    //name失去焦点,发ajax的请求校验用户是否存在
    //校验,但是只要值不变,只校验一次
    /*
    $("#id_username").change(function () {
        
    })
     */
    //一直会校验
    $("#id_username").blur(function () {
        $.ajax({
            url: /check_username/,
            type: post,
            //name加不加引号都可以
            data: {name:$("#id_username").val(),csrfmiddlewaretoken: {{ csrf_token }} },
        success:function (data) {
            if (data.status==101){
                $("#id_username").next().html(data.msg).parent().addClass(has-error)
            }
            else {
                $("#id_username").next().html(data.msg).parent().removeClass(has-error)
            }
        }
        })
    })

</script>
</html>

 

以上是关于Django---博客项目实战的主要内容,如果未能解决你的问题,请参考以下文章

项目实战基于Python+Django+MySQL的个人博客系统(附完整源码)

实战项目之Django博客-5. 博客首页视图

python项目实战:实时博客项目 源码下载

1django实战---简单的博客系统

用Django来创建一个自己的博客(零到实战)

Django快速开发实战初识Django