初识Django-前后端不分离(二)

上下文管理器

作用:每个view里面都需要用到的操作也就是公共的东西,就可以放到你自己定义的上下文管理器中查,这样在views.py里就不用重复写了

执行的顺序:每一个视图请求完后都会再请求一次上下文管理器

如何使用上下文管理器: 

  1. 首先定义一个上下文管理器:process_context.py
  2. 在上下文管理器中定义的函数,函数必须有一个参数,是request
  3. 这个函数要返回一个字典(这里额外介绍一个函数locals(),locals作用是把当前这个函数里所有的局部变量变成一个字典。下方有例子)
  4. 在这里创建的函数,需要在settings.py里的TEMPLATES->OPTIONS->context_processors下配置,每一个函数都需要配置一下。
#上下文管理器process_context.py
from . import models

def category_process(request):
    print('category_process.....')
    catagories = models.Category.objects.filter(is_delete=False)
    return {'nav':catagories}

def site_process(request):
    site_name='塔塔的博客'
    desc='今天是周天,明天是周一'
    return locals()  #locals作用是把当前这个函数里所有的局部变量变成一个字典。这一行等同于下面一行,
    # return {'site_name': site_name,'desc':desc}


settings.py
TEMPLATES
= [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'user.process_context.category_process', #这里配置创建的函数 'user.process_context.site_process' ], }, }, ]

模版继承 

不同的html文件中也会有一些公用的内容,我们同样可以把他们抽离出来,单独放到一个html文件中,我们把这种叫做模版继承。

如何使用模版继承

  1. 首先创建一个base.html,用于存放公用的内容
  2. base.html中需要变化的内容用block标记。格式如下(注意css和js有时候也是需要变得,所以在base.html中一般也会预留出css和js的口)

            {% block content %} 中间是变化的内容  {% endblock %}   #content这是用来标识变化的内容的,是可变的,如果是css则替换成css即可

       3. 公共的内容抽离出去里后,原有的html中需要指定继承哪个公共的html里的内容(这里就是继承base.html)。

           {% extends 'base.html' %}

        4. 原有的html中还要指定可变的内容是什么,{% block content%} 中间是可变的内容 {% endblock %}

 

 

分页

需导入django自带的分页的类:from django.core.paginator import Paginator

后端分页相关知识:
from
django.core.paginator import Paginator l=range(1,51) page_obj=Paginator(l,10) #10个分一页 # page_obj = Paginator(Article.objects.all(),2) #从数据库查文章表数据,2个一页 print(list(page_obj.page(1))) print(page_obj.page(1)) #取某一页的数据,显示的结果是这种<Page 1 of 2>,表示一共多少页现在在哪一页 print(list(page_obj.page(1))) #转成list就能展示出取某一页的数据了 print(page_obj.count) #总共多少条 print(page_obj.num_pages) #总共分了多少页 print(page_obj.page_range) #分页的范围 cur_page = page_obj.page(1) #当前在那一页 print(cur_page.has_previous()) #判断是否有上一页,要先指定当前在那一页 # print(cur_page.previous_page_number()) #取上一页的分页号码 print(cur_page.has_next())#判断是否有下一页 print(cur_page.next_page_number()) #取下一页的分页号 print(cur_page.has_other_pages()) #判断是否有其他页 print(cur_page.paginator) #相当于page_obj
前端实现代码:
 {% if articles.has_other_pages %}
      <div class="pagelist">
          {% if articles.has_previous %}
          <a href="/index?page={{ articles.previous_page_number }}&limit=10"><b>上一页</b></a>&nbsp;&nbsp;
              {% endif %}

          {% for page_num in articles.paginator.page_range %}
          <a href="/index?page={{ page_num }}&limit=10" >{{ page_num }}</a>&nbsp;&nbsp;
          {% endfor %}

          {% if articles.has_next %}
          <a href="/index?page={{ articles.next_page_number }}&limit=10">下一页</a>

          {% endif %}
      </div>
      {% endif %}

 

丰富Django管理后台

  • 美化Django管理后台样式
    1. 首先安装pip install simpleui
    2. 其次在settings.py->INSTALLED_APPS下添加'simpleui'
  • 丰富Django管理后台某数据库页面操作项
在子项目下的admin.py文件中进行配置

from
django.contrib import admin # Register your models here. from . import models #配置如下class类,可以丰富页面的操作项,对应下方操作页面的admin.site.register里也要增加类名 class ArticleAdmin(admin.ModelAdmin): list_display = ['title', 'category', 'create_time', 'update_time'] #显示哪些字段 search_fields = ['title'] #指定按哪写字段搜索,不要写外键的字段 list_filter = ['category','is_delete'] #根据哪个字段筛选 list_per_page = 10 #每页显示多少条 admin.site.register(models.Article,ArticleAdmin) #这里增加ArticleAdmin

 

前后端不分离的流程

urls.py里面匹配url,找到对应的url里面的函数,读取函数里的内容将数据和html交给render,render在templates里找对应的html,找到后读取该html里的内容映射到页面

前后端分离

跨域问题:安装pip install django-cors-headers 后即允许跨域

 

有一些文章显示内容太多会截断用....展示,这需要如何操作呢?

  1. 自定义tag标签

          在子项目下创建一个templatetags文件夹(注:文件夹名必须固定叫templatetags,文件夹下要有个__init__.py文件),在templatetags文件夹中建一个my_tag.py的文件,在这里自定义我们需要的函数,前端可以直接调用 (注:my_tag.py中的register变量名是固定不可变的)

my_tag.py

from django import template

register=template.Library() # register固定的变量名,不能改

@register.filter #filter最多有2个参数,前端使用时首先{% load my_tag %},其次在用的地方加上|+函数名,如果是两个参数需要用到:,如{{ article.desc | test:10}}
def abc(s,length=10): #判断字符串大于10就截断以...显示
    if len(s)>length:
        s=s[:11]+'.....'
    return s


@register.simple_tag #simple_tag 不限制参数,如果参数很多用这个
def abc2(s,length=10):
    if len(s)>length:
        s = s[:11]+'....'
    return s

2. 在前端调用我们自定义的函数

第一步:在对应的html中load我们创建的python文件my_tag
{% load my_tag %}

第二步:在具体的内容处引用

第一种自定义filter最多有2个参数
一个参数的用法
<p>{{ article.desc | abc}}</p>  
二个参数的用法
<p>{{ article.desc | abc:10}}</p> 

第二种自定义simple_tag不限制传参个数用法
<p>{% abc2 article.desc 10 %}</p> 

 

Django自带的过滤器

{% load my_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="/static/style.css" rel="stylesheet">
</head>
<body>
    欢迎《{{name}}》登录,今天是 === {{time}} ===

    {{ stus.0 }}
    <br>
    {{ stus |length  }}
    <br>
    {{ stus |slice:"0:2"  }}
    <br>
    {{ stus |join:"-"  }}
    <br>
    {{ name |default:"admin"  }}
    <br>
    {{ cur_time |date:"Y-m-d H:i:s"  }}
    <br>
    {{ h1_str |safe  }}
{#    #xss注入,加safe表示安全#}
    <br>
    {{ h1_str   }}
    <br>
    {{ words | truncatechars:20   }}
    <br>
    {{ age | add:2   }}
    <br>
    {{ name | add:"先生"   }}
    <br>
    {{ english_name | upper   }}
    <br>
    {{ english_name | lower   }}
    <br>
    {{ article_content|mingan }}
    <br>
    {{ article_content|mingan2:"金正恩" }}
    <br>
    {% mingan3 say "213" "sb" "傻x" %}

{#    <ul>#}
{#        {% for stu in stus %}#}
{#        <li>{{stu}}</li>#}
{#        {% endfor%}#}
{#    </ul>#}
</body>
</html>

 

CSRF TOKEN

csrf token的作用:为了防止重复提交的。

django默认post请求都需要加csrf token,如果不加请求不成功,报禁止访问(403) CSRF验证失败,请求被中断

两种解决方法:

1. 在settings.py->MIDDLEWARE里把csrf的校验注释掉(注释掉就会有重复提交的风险)

 

 2. 如果不注释掉,就在html的form表单中写{% csrf_token %}

 

 

cvb和fvb

函数写法的方式是fvb ,在urls.py里配置链接时是:path('add_article/', add_article),

类写法的方式是cvb,cvb在配置url时,需导入ArticleView,写法:path('add_article/', ArticleView.as_view()),

#fvb  :用函数是需要判断是get还是post请求
def add_article(request):
    if request.method=='GET':
        categories = Category.objects.all()
        return render(request,'form.html',locals())
    else:
        title = request.POST.get('title')
        desc = request.POST.get('desc')
        category = request.POST.get('category')
        content = request.POST.get('content')
        article = Article(title=title,desc=desc,category_id=category,content=content)
        article.save()
        return HttpResponseRedirect('/index') # HttpResponseRedirect表示重定向


#cvb  :不需要判断直接定义2个方法,一个get一个post即可
#导入View
from django.views import View
class ArticleView(View):

    def get(self,request):
        print('get请求...')
        categories = Category.objects.all()
        return render(request, 'form.html', locals())

    def post(self,request):
        print('post请求...')
        title = request.POST.get('title')
        desc = request.POST.get('desc')
        category = request.POST.get('category')
        content = request.POST.get('content')
        article = Article(title=title, desc=desc, category_id=category, content=content)
        article.save()
        return HttpResponseRedirect('/index')  # 重定向

嗯。。

posted @ 2020-01-05 23:59  塔塔~  阅读(739)  评论(0编辑  收藏  举报