Django高级扩展

Django高级扩展

静态文件

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]
{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <link rel="stylesheet" type="text/css" href="{% static 'myApp/css/style.css' %}"/>
    <script type="text/javascript" src="/static/myApp/js/jquery-3.1.1.min.js"></script>
    <script type="text/javascript" src="/static/myApp/js/sunck.js"></script>
</head>
<body>
    <h1>sunck is a good man</h1>
    <img src="/static/myApp/img/2.png"/>
    <img src="{% static 'myApp/img/2.png' %}"/>
</body>
</html>

中间件

-概述 - 一个轻量级、底层的插件,可以介入Django的请求和响应

  • 本质
    • 一个Python类
  • 方法
    • init
      • 不需要传参数,服务器响应第一个请求的时候自动调用,用于确定是否启用该中间件
    • process_request(self,request)
      • 在执行视图之前被调用(分配url匹配视图之前),每个请求上都会调用,返回None或者HttpResponse对象
    • process_view(self,request,view_func,view_args,view_kwargs)
      • 调用视图之前执行,每个请求都会调用,返回None或者HttpResponse对象
    • process_template_response(self,request,response)
      • 在视图刚好执行完后调用,每个请求都会调用,返回None或者HttpResponse对象 使用render
    • process_response(self,request,response)
      • 所有响应返回浏览器之前调用,每个请求都会调用,返回HttpResponse对象
    • process_exception(self,request,exception)
      • 当视图跑出异常时调用,返回HttpResponse对象 执行位置

自定义中间件

- 工程目录下middleware目录下创建myApp目录
		创建一个python文件
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
from backweb.models import User


class AuthMiddleWare(MiddlewareMixin):
#重写process_request方法
    def process_request(self,request):
        #获得页面
        path = request.path
        #放过登录页面
        if path == '/backweb/my_login/':
            return None
        #获得页面cookie中的session_id
        #(页面cookie中的session_id是登录时产生的随机数,将其付给cookie同时在数据库中存储该值。
        #用户访问页面时间就拿cookie中的session_id 与数据库做对比,有就说明用户是登录状态,用户退出时将数据库清空)
        session_id = request.COOKIES.get('session_id')
        
        #cookie中没有session说明没有登录
        if not session_id:
            return HttpResponseRedirect(reverse('backweb:my_login'))
        #获的cookie中有session_id同时获取其数据库模型对象,没有对象说明这个人不是网站的注册用户重新返回登录页面
        user = User.objects.filter(session_id=session_id)
        #
        if not user:
            return HttpResponseRedirect(reverse('backweb:my_login'))
        return None


  • 使用自定义中间件
    • 配置settings.py文件
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',
    #添加自定义中间件
    'utils.UserAuthMiddleware.AuthMiddleWare',
]

app/views.py



def my_login(request, rando=None):
    if request.method == 'GET':
        return render(request, 'backweb/login.html')
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        #验证用户信息
        user = User.objects.filter(username=username,password=password).first()
        if user:
            #确定跳转重定向
            res = HttpResponseRedirect(reverse('backweb:index'))
            #写随机数字符串生成cookie
            s = 'qazwsxedcrfvtgbyhnujmikolpQZWXEDCRFVTGBYHNUJMIKOLP1234567890'
            #给cookie定名字
            session_id = ''
            #循环写cookie
            for i in range(20):
                session_id += random.choice(s)
            #创建cookie过期时限默认(一天)
            out_time = datetime.now() + timedelta(days=1)
            #为用户(服务器客户端添加)添加cookie,用来判断用户是否登录。没有登录的用户没有cookie值无法直接进网站
            res.set_cookie('session_id',session_id, expires=out_time)
            #为服务器添加进数据库
            user.session_id = session_id
            user.out_time = out_time
            user.save()
            #执行跳转
            return res
        #找不到对应数据库数据用户提供信息错误
        else:
            error = '用户名或密码错误'
            return render(request, 'backweb/login.html')
            
            
def my_logout(request):
    if request.method == 'GET':
        session_id = request.COOKIES.get('session_id')
        user = request.user
        user.session_id = ''
        user.save()

        res = HttpResponseRedirect(reverse("backweb:my_login"))
        res.delete_cookie('session_id')
        return res            
            

login.html


<body>
<dl class="admin_login">
    <dt>
        <strong>站点后台管理登录</strong>
        <em>Management System</em>
    </dt>
    <form action="" method="post">
         {% csrf_token %}
        <dd >
            <input type="text" name="username" placeholder="账号" />
        </dd>
        <dd>
            <input type="password" name="password" placeholder="密码"/>
        </dd>
        <dd>
            <input type="submit" value="立即登录" class="submit_btn"/>
        </dd>
    </form>
</dl>
</body>


上传图片

  • 概述
    • 文件上传时,文件数据存储在request.FILES属性中
    • 注意:form表单要上传文件需要加enctype="multipart/form-data"
    • 注意:上传文件必须是post请求
    • 需要安装pip install pillwo

网页

	<body>
    <form method="post" action="/savefile/" enctype="multipart/form-data">
        {%csrf_token%}
        <input type="file" name="filename"/>
        <input type="submit" value="上传"/>
    </form>
		

项目/setting.py

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

app/models.py

class Article(models.Model):
    image = models.ImageField(upload_to='',null=True)

项目/urls.py

from django.contrib.staticfiles.urls import static
from blogger import settings
urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
# 添加media为静态文件像static一样可以{% load xxx %}调用
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

app/views.py

def add(request):
    if request.method == 'GET':
        return render(request, 'backweb/add.html')
    if request.method == 'POST':
        filename = request.FILES['filename']
        Article.objects.create( image=filename, )
        return HttpResponseRedirect(reverse('backweb:index'))

展示.html

  {# 图片 #}
     <td ><img src="/media/{{set.image}}" width="50" height="50"/></td>

分页

  • Paginator对象

    • 创建对象

      • 格式Paginator(列表, 整数)
      • 返回值返回的分页对象
      • 属性
        • count对象总数
        • num_pages页面总数 -page_range页码列表[1,2,3,4,5]页码从1开始
    • 方法 -page(num)获得一个Page对象,如果提供的页码不存在会抛出"InvalidPage"异常

      -InvalidPage当向page()传递的是一个无效的页码时抛出 -PageNotAnInteger当向page()传递的不是一个整数时抛出 -EmptyPage当向page()传递一个有效值,但是该页面时没有数据时抛出

    • Page对象

      • 创建对象Paginator对象的page()方法返回得到Page对象不需要手动创建
      • 属性
        • object_list当前页上所有的数据(对象)列表
        • number当前页的页码值
        • paginator当前page对象关联的paginator对象
      • 方法
        • has_next()判断是否有下一页,如果有返回True
        • has_previous()判断是否有上一页,如果有返回True
        • has_other_pages()判断是否有上一页或下一页,如果有返回True
        • next_page_number()返回下一页的页码,如果下一页不存在抛出InvalidPage异常
        • previous_page_number()返回上一页的页码,如果上一页不存在抛出InvalidPage异常
        • len()返回当前页的数据(对象)个数 Paginator对象与Page对象的关系
  • views.py


def pagetitle(request, pageid):
    if request.method == 'GET':
    #拿到所欲数据
        sets = Article.objects.all()
        #确定每个页面展示2条数据
        paginator = Paginator(sets,1)
        #拿到对应页面的id
        page = paginator.page(pageid)
        return render(request, 'backweb/pagetitle.html', {'sets':page})

pagetitle.html

        {# 分页 #}
        <aside class="paging">
            <a href="/backweb/pagetitle/1">第一页</a>

            {% if sets.has_previous %}
                  <a href="/backweb/pagetitle/{{ sets.previous_page_number }}">上一页</a>
            {% endif %}

            {# 上一页码页码 #}
            {% if sets.has_previous %}
                <a href="/backweb/pagetitle/{{ sets.previous_page_number }}">{{ sets.previous_page_number }}</a>
            {% endif %}
                {# 本页页码(在本页面,那么该页面的页码就不能点击) #}
                 <a style="color:black;" href="#">{{ sets.number }}</a>
                 {# 下一页页码 #}
            {% if sets.has_next %}
                  <a href="/backweb/pagetitle/{{ sets.next_page_number }}">{{ sets.next_page_number }}</a>
            {% endif %}

            {# 下一页 #}
            {% if sets.has_next %}
                  <a href="/backweb/pagetitle/{{ sets.next_page_number }}">下一页</a>
            {% endif %}
            {# 最后一页 #}
            <a href="/backweb/pagetitle/{{ sets.paginator.num_pages }}">最后一页</a>

  • 使用接口前后分离
  • html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>add</title>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
    function add_students() {
        var name = $('#name').val()
        var age = $('#age').val()
        var sex = $('#sex').val()
        var csrf = $('input[name="csrfmiddlewaretoken"]').val()
        $.ajax({
            url:'/app/student/',
            type:'POST',
            dataType:'json',
            data:{'s_name':name,'s_age':age,'s_sex':sex},
            headers:{'X-CSRFToken':csrf},
            success:function (data) {
                   alert('成功')
               },
            error: function (data) {
                    alert('失败')
                }
        })
    }


</script>
</head>
<body>

<span>姓名</span><input id="name" type="text" name="s_name">

<span>年龄</span><input id="age" type="text" name="s_age">

<select name="s_sex" id="sex">
    <option value="0">男</option>
    <option value="1">女</option>
</select>
</body>
<br/>
<input type="button" value="提交" onclick="add_students()">



</body>
</html>

-views

from django.shortcuts import render
from django.http import HttpResponse
from rest_framework import mixins, viewsets
from rest_framework.response import Response

from app.app_filter import StudentFilter
from app.app_serializers import StudentSerializer
from app.models import Student


class StudentSoure(mixins.ListModelMixin,
                   mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   viewsets.GenericViewSet):
    #查询资源的所有数据
    queryset = Student.objects.all().filter(is_delete=1)
    #序列化
    serializer_class = StudentSerializer
    #过滤
    # filter_class = StudentFilter

    def get_queryset(self):
        queryset = self.queryset
        queryset.filter(s_name__contains='小')
        return queryset



    def get_object(self):
        pass
  

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.is_delete:
            serializer = self.get_serializer(instance)
        else:
            serializer = self.get_serializer()
        return Response(serializer.data)

    def retrieve(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
        except:
            data = {
                'code': 1001,
                'msg': '数据不存在'
            }
        return Response(data)


-app/urls

from django.conf.urls import url

from rest_framework.routers import SimpleRouter

from app import views

router = SimpleRouter()
router.register('student',views.StudentSoure)

urlpatterns = [


]
urlpatterns += router.urls
  • app/app_filter
import django_filters

from rest_framework import filters

from app.models import Student


class StudentFilter(filters.FilterSet):
    # 过滤s_name参数,精确过滤
    s_name = django_filters.CharFilter('s_name', lookup_expr='contains')
    s_age_gt = django_filters.NumberFilter('s_age', lookup_expr='gt')
    s_age_lt = django_filters.NumericRangeFilter('s_age', lookup_expr='lt')

    class Meta:
        model = Student
        fields = ['s_name', 's_age', 's_age', ]

  • app/app_serializers
from rest_framework import serializers

from app.models import Student


class StudentSerializer(serializers.ModelSerializer):

    class Meta:
        model = Student
        fields = ['id', 's_name', 's_age', 's_sex']

    def to_representation(self, instance):
        #拿到系列化结果
        data = super().to_representation(instance)
        #添加参数
        data['address'] = 'hgj '
        return instance

猜你喜欢

转载自blog.csdn.net/qq_32389821/article/details/82496232