blog开发day3+Django admin的简单使用

实例

url.py

"""cnblog_prew URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
from django.views.static import serve
from django.conf import settings


urlpatterns = [
    path('admin/', admin.site.urls),
    #使用FBV来写的格式
    path('login/', views.Login.as_view()),
    #注销用户
    path('logout/', views.logout),
    path('get_valid_pic/', views.get_valid_pic),
    path('index/', views.index),
    #极验滑动验证码 获取验证码的url
    path('pc-geetest/register/', views.get_geetest),

    #注册
    path('register/', views.register),
    # 专门用来校验用户名是否已被注册的接口
    path('check_username_exist/', views.check_username_exist),

    #media相关的路由设置
    re_path('media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),


]

views.py

from django.shortcuts import render,redirect,HttpResponse
from django.http import JsonResponse

# Create your views here.

from django.views import View
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from geetest import GeetestLib
from app01 import forms,models

#极验 登录验证码
# 请在官网申请ID使用,示例ID不可使用
pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"
def get_valid_pic(request):
    from PIL import Image,ImageDraw,ImageFont
    import random
    #生乘随机的RGB
    def random_color():
        return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    #生成随机背景色  对象
    image = Image.new("RGB",(270,37),random_color())

    #给图片添加内容
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype("static/fontAwesome/fonts/song.ttf", 28)
    temp = []
    for i in range(5):
        random_low = chr(random.randint(97,122))
        random_upper = chr(random.randint(65,90))
        random_digit = str(random.randint(0,9))
        random_choose = random.choice([random_low,random_upper,random_digit])
        draw.text((40+40*i,0),random_choose,random_color(),font=font)
        temp.append(random_choose)


    # 在内存中生成图片
    from io import BytesIO
    f = BytesIO()
    image.save(f, "png")
    data = f.getvalue()
    f.close()

    valid_str = ''.join(temp)

    request.session['valid_str'] = valid_str

    return HttpResponse(data)

class Login(View):
    def get(self, request):
        return render(request, 'login2.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')

        #获取极验滑动验证码相关的参数
        gt = GeetestLib(pc_geetest_id, pc_geetest_key)
        challenge = request.POST.get(gt.FN_CHALLENGE, '')
        validate = request.POST.get(gt.FN_VALIDATE, '')
        seccode = request.POST.get(gt.FN_SECCODE, '')
        status = request.session[gt.GT_STATUS_SESSION_KEY]
        user_id = request.session["user_id"]
        if status:
            result = gt.success_validate(challenge, validate, seccode, user_id)
        else:
            result = gt.failback_validate(challenge, validate, seccode)

        res = {'state': False, 'msg': None}
        if result:
            # 验证码正确
            # 用户认证
            user = auth.authenticate(username=username, password=password)
            auth.login(request, user)   #将登陆用户赋值给 request.user
            if user:
                res['state'] = True
            else:
                res['msg'] = '用户名密码错误!'
        else:
            res['msg'] = '验证码错误'

        return JsonResponse(res)

#这个装饰器实现的功能是,之前登录过index的可以直接登录,没登录过的就跳转到login页面
#注意要在settings.py中       LOGIN_URL = '/login/'  # 这里配置成你项目登录页面的路由
# @login_required
def index(request):
    # 查询所以的文章列表
    article_list = models.Article.objects.all()
    return render(request,'index.html',{'article_list':article_list})

# 注销
def logout(request):
    auth.logout(request)
    return redirect('/index/')


#处理极验 获取验证码
def get_geetest(request):
    user_id = 'test'
    gt = GeetestLib(pc_geetest_id, pc_geetest_key)
    status = gt.pre_process(user_id)
    request.session[gt.GT_STATUS_SESSION_KEY] = status
    request.session["user_id"] = user_id
    response_str = gt.get_response_str()
    return HttpResponse(response_str)

def register(request):
    if request.method == "POST":
        #status 是0表示 没出错  1 表示出错
        res = {"status":0,"msg":""}
        form_obj = forms.RegForm(request.POST)
        #帮我做校验
        if form_obj.is_valid():
            #验证通过
            #所以的数据都保存在form_obj.cleaned_data中  一个大字典
            form_obj.cleaned_data.pop("re_password")    #删除字典中re_password  因为数据库中没有这个属性
            #数据库中的头像数据是默认的,所以自己拿 新的
            avatar_img = request.FILES.get("avatar")
            #在数据库中创建数据
            models.UserInfo.objects.create_user(**form_obj.cleaned_data,avatar=avatar_img)
            res["msg"] = '/index/'
            return JsonResponse(res)
        else:
            #把错误信息存起来
            res["msg"] = form_obj.errors
            res["status"] = 1
            # print(res)  #类似于 {'status': 1, 'msg': {'email': ['邮箱不能为空'], 're_password': ['两次密码输入不一致']}}
            return JsonResponse(res)
    form_obj = forms.RegForm()
    return render(request,'register.html',{"form_obj":form_obj})

#校验用户名是否已被注册
def check_username_exist(request):
    res = {"status":0,"msg":""}
    username = request.GET.get("username")
    is_exist = models.UserInfo.objects.filter(username=username)
    if is_exist:
        #用户名已被注册
        res["status"] = 1
        res["msg"] = "用户名已被注册!"
    return JsonResponse(res)

settings.py

#Django用户上传的都叫media文件
MEDIA_URL = "/media/"

# media配置,用户上传的文件都默认放在这个文件夹下
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

AUTH_USER_MODEL = "app01.UserInfo"

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>index</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'fontAwesome/css/font-awesome.min.css' %}">
    <link rel="stylesheet" href="{% static 'sweetalert/sweetalert.css' %}">
    <link rel="stylesheet" href="{% static 'mystyle.css' %}">
</head>
<body>

{#导航条开始#}
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <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="#">My Blog</a>
        </div>

        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.username %}
                    {#                登陆的用户显示#}
                    <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="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/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 class="container" style=" 90%">
    <div class="row">
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">左侧广告栏一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">左侧广告栏二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-8">
            {#            文章列表 开始#}
            <div class="article-list">
                {% for article in article_list %}
                    <div class="article">
                        {#标题#}
                        <h3><a href="">{{ article.title }}</a></h3>
                        {# 简介#}
                        <div class="media">
                            <div class="media-left">
                                <a href="#">
                                    <img class="media-object author-img" src="/media/{{ article.user.avatar }}" alt="...">
                                </a>
                            </div>
                            <div class="media-body">
                                <p>{{ article.desc }}</p>
                            </div>
                        </div>
                        {#作者名#}
                        <div class="article-footer">
                            <span><a href="">{{ article.user.username }}</a></span>发布于
                            <span>{{ article.create_time|date:'Y-m-d H:i:s' }}</span>
                            {#反向查询#}
                   {#<span class="glyphicon glyphicon-comment" aria-hidden="true">评论({{ article.comment_set.all.count }})</span>#}
                            <span class="glyphicon glyphicon-comment" aria-hidden="true">评论({{ article.comment_count }})</span>
                            <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true">点赞({{ article.up_count }})</span>
                        </div>
                    </div>
                {% endfor %}

            </div>
            {#            文章列表 结束#}
        </div>
        <div class="col-md-2">
            <div class="panel panel-primary">
                <div class="panel-heading">右侧广告栏一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">右侧广告栏二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
    </div>
</div>
{#主页面结束#}


<script src="{% static 'jquery-3.2.1.min.js' %}"></script>
<script src="{% static 'setupajax.js' %}"></script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</body>
</html>

models.py中Article修改:

class Article(models.Model):
    """
    文章
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=50)  # 文章标题
    desc = models.CharField(max_length=255)  # 文章描述
    create_time = models.DateTimeField()  # 创建时间

    #评论数
    comment_count = models.IntegerField(verbose_name="评论数",default=0)
    #点赞数
    up_count = models.IntegerField(verbose_name="点赞数",default=0)
    #踩
    down_count = models.IntegerField(verbose_name="差评数",default=0)

    category = models.ForeignKey(to="Category", to_field="nid", null=True,on_delete=models.CASCADE)
    user = models.ForeignKey(to="UserInfo", to_field="nid",on_delete=models.CASCADE,default=None)
    tags = models.ManyToManyField(  # 中介模型
        to="Tag",
        through="Article2Tag",
        through_fields=("article", "tag"),  # 注意顺序!!!
    )

    def __str__(self):
        return self.title

 注意:

要注意这里面的media的配置

先在settings.py中添加:

#Django用户上传的都叫media文件
MEDIA_URL = "/media/"

# media配置,用户上传的文件都默认放在这个文件夹下
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

后再urls.py中添加:

from django.views.static import serve
from django.conf import settings
#media相关的路由设置 re_path('media/(?P
<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),

Django admin高级拓展

django admin高级拓展知识------点击

原文地址:https://www.cnblogs.com/liujie12/p/12745122.html