Django扩展

Django扩展

一、验证码

1、简介
1. 为什么要使用验证码:
		在form中常用的一个组件,目的是为了更好地保障请求的合法性,防止恶意、无效的访问,恶意注册,暴力破解等
	
2. 验证码实现原理:	
		在服务器端,生成一个随机的码"DNC1",将随机码画到一张图片中(加噪点),再图片显示在页面上。
		
3. 第三方包:pillow
		pip install pillow  - 是一个关于图片的第三方模块
2、使用步骤
  • 从验证码的原始文件中,将captcha的包导入自己的项目的app目录下
  • 写一个视图函数,生成验证码
def get_captcha(request):
    # 1. 声明一个图片验证码对象
    image = ImageCaptcha()
    # 2. 生成随机码
    code = random.sample(string.ascii_letters+string.digits,4)
    code = ''.join(code)
    # 3. 将码写入图片中
    data = image.generate(code) # 返回:二进制数据
    print(code)
    return HttpResponse(data,'image/png')
  • 在html中加入验证码
<form action="">
    用户名:<input type="text" name="username"> <br>
    密码:<input type="password" name="password"> <br>
    验证码:<input type="text" name="captcha">
    <!-- 加入验证码 -->
    <img src="{% url 'captcha:get_captcha' %}" alt="" width="80"> <br>
    <input type="submit" value="注册">
</form>
  • 看不清,换一张
<script>
    function changeCaptcha() {
        var img = document.getElementsByTagName('img')[0]
        img.src = "{% url 'captcha:get_captcha' %}" + "?"+new Date().getTime()
    }
</script>


<a href="javascript:void(0)" onclick="changeCaptcha()">看不清,换一张</a>
  • 验证是否正确
# def get_captcha(request):
	# 在随机产生码后,将码存入session中,以便后续验证的时候使用
    # request.session['code'] = code 

def register_logic(request):
    captcha = request.POST.get('captcha')
    if captcha.lower() == request.session.get('code').lower():
        # ...
        return HttpResponse('验证码正确')
    return HttpResponse('验证码错误')

二、文件上传

1、简介
1. 在django中要实现文件或图片的上传,直接使用FileField和ImageField字段即可。而ImageField是继承之FileField.

2. 如果要给某个用户上传一个头像:
	class User(models.Model):
		name = models.CharField(max_length=20)
		age = models.SmallIntegerField()
		picture = models.ImageField(upload_to='pics')
		
3. 在使用ImageField字段之前,需要安装一个第三方模块:pillow		

4. 在数据库中并不会直接存储图片/文件本身,存储的是图片的路径-字符串

5. 需要在settings.py文件中,配置头像/文件的实际存储位置:
	   	MEDIA_ROOT = os.path.join(BASE_DIR,'media')
2、案例:为用户上传头像
  • 配置头像的存储位置并安装pillow
# settings.py中
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

# 在terminal中
pip install pillow
  • 定义model类
class User(models.Model):
    name = models.CharField(max_length=20)
    age = models.SmallIntegerField()
    salary = models.DecimalField(max_digits=7, decimal_places=2)
    birthday = models.DateTimeField()
    head_picture = models.ImageField(upload_to='pics')
    
# 记得执行迁移操作     
  • 定义form表单
<!-- form表单提交文件时,必须加enctype属性 值为 multipart/form-data --><form action="{% url 'uploadapp:register_logic' %}" method="post" enctype="multipart/form-data">    {% csrf_token %}    用户名:<input type="text" name="username"> <br><br>    年龄:<input type="number" name="age"> <br><br>    薪水:<input type="number" name="salary"> <br><br>    生日:<input type="date" name="birthday"> <br><br>    头像:<input type="file" name="head_picture"> <br><br>    <input type="submit" value="提交"></form>
  • 定义view视图函数
def register_logic(request):    try:        username = request.POST.get('username')        age = request.POST.get('age')        salary = request.POST.get('salary')        birthday = request.POST.get('birthday')        # head_picture = request.POST.get('head_picture') #################### 接收文件时 使用request.FILES ###########################        head_picture = request.FILES.get('head_picture')        print(username, age, salary, birthday, head_picture)        with transaction.atomic():            User.objects.create(name=username, age=age, salary=salary, birthday=birthday, head_picture=head_picture)        return HttpResponse('提交成功')    except Exception as e:        print(e)        return HttpResponse('提交失败')
  • 修改头像的名字
import uuid# 获取原文件的扩展名 extendextend = os.path.splitext(head_picture.name)[1]# 改文件名head_picture.name = str(uuid.uuid4()) + extend
  • 头像回显

    • 设置静态资源查找目录
    # settings.py文件中,将media目录添加为静态资源的查找路径STATICFILES_DIRS = [os.path.join(BASE_DIR,'static'),MEDIA_ROOT]    
    
    • 在模板文件中,设置img标签
    <img src="/static/{{ user.head_picture }}" alt="" height="50px">或 将静态资源的访问路径改为软编码方式{% load static %}<img src="{% static user.head_picture.url %}" alt="" height="50px">
    

三、分页显示

1、简介
当页面中的数据过多时,需要进行分页展示,在页面上需要有相应的页号,上一页,下一页等功能,点击相应的页号时,跳转到对应的页。在django中,提供了一个类Paginator(分页器),来进行分页操作。
2、分页器Paginator
1. 第一步:初始化一个分页器对象	pagtor = Paginator(object_list=要分页的数据的'列表'-可迭代对象, per_page=每页要显示的数据个数)
# 源代码:class Paginator:    def __init__(self, object_list, per_page, orphans=0,                 allow_empty_first_page=True):        self.object_list = object_list        self._check_object_list_is_ordered()        self.per_page = int(per_page)        self.orphans = int(orphans)        self.allow_empty_first_page = allow_empty_first_page
  • 分页器对象的属性

声明分页器对象

pagtor = Paginator(object_list=users,per_page=3)

1. pagtor.count		获取所有页面的对象总数 - 也就是object_list参数中的元素的个数2. pagtor.num_pages 		获取总页数	 3. pagtor.page_range		返回页面的范围 range(1,num_pages+1)
  • 分页器对象的方法
# 重要的一个方法 page = pagtor.page(number)  # 调用page方法,获取某一页的页面对象,page = pagtor.page(1) 
3、页面对象
# 获取页面对象 page = pagtor.page(number) 
  • 页面对象的属性
1. page.object_list		返回当前页面中的所有的数据对象		2. page.number		返回当前的页号-页码		3. page.paginator		page.paginator.num_pages		返回当前页面所属的分页器对象
  • 页面对象的方法
1. page.has_next()		是否有下一页,返回为bool类型 2. page.has_previous()		是否有上一页,返回为bool类型 		3. page.has_other_pages()		是否有其它页,如果它有上一页或有下一页,则返回为True		4. page.next_page_number()		返回下一页的页号  page.number+1 如果不存在 则抛出异常		5. page.previous_page_number()		返回上一页的页号  page.number-1		如果不存在 则抛出异常		6. page.start_index()		返回当前页的起始索引7. page.end_index()		返回当前页的结束索引

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UyBoGq32-1644897742002)(Django07_实用扩展.assets/image-20210228145049860.png)]

4、分页案例
def userlist(request):    users = User.objects.all()    # 获取url中的参数,如果不存在返回第1页    number = int(request.GET.get('number',1))    # 声明分页器对象    pagtor = Paginator(object_list=users,per_page=3)    # 判断页号是否存在    if number not in pagtor.page_range:        number=1    page = pagtor.page(number)	# 向后端传递的是页面对象    return render(request,'uploadapp/userlist.html',{'page':page})
<!--遍历页面对象的数据-->   {% for user in page.object_list %}         <tr>            <td>{{ user.id }}</td>            <td>{{ user.name }}</td>            <td>{{ user.age }}</td>            <td>{{ user.salary }}</td>            <td>{{ user.birthday|date:'Y-m-d' }}</td>            <td>                <img src="{% static  user.head_picture.url %}" alt="" height="50px">            </td>        </tr>    {% endfor %}
<!--实现上一页和下一页 及 页号-->   {% if page.has_previous %}    <a href="{% url 'uploadapp:userlist' %}?number={{ page.previous_page_number }}">上一页</a>{% endif %}{% for n in page.paginator.page_range %}    {% if page.number == n %}        <a class="b" href="{% url 'uploadapp:userlist' %}?number={{ n }}">{{ n }}</a>    {% else %}        <a class="a" href="{% url 'uploadapp:userlist' %}?number={{ n }}">{{ n }}</a>    {% endif %}{% endfor %}{% if page.has_next %}    <a href="{% url 'uploadapp:userlist' %}?number={{ page.next_page_number }}">下一页</a>{% endif %}
/*a标签样式*/   <style>    .a {        width: 20px;        height: 20px;        border: 1px solid #e1e2e3;        cursor: pointer;        display: inline-block;        text-align: center;        line-height: 20px;    }    .b {        border: 0;        width: 20px;        height: 20px;        cursor: pointer;        display: inline-block;        text-align: center;        line-height: 20px;    }    a {        text-decoration: none;    }</style>

四、中间件

1、简介
1. 概念	中间件(Middleware)用于在http请求到达`视图函数之前`及`视图返回响应之后`的期间,django会根据自己的规则在合适的时机执行一些方法(中间件中的一些方法)。2. 中间件的作用	常用于抽取view中冗余的功能代码,如每个页面在访问时都需要进行`强制登录`	以前是每个视图中都行强制登录判断,如果加了中间件,就可以将判断放在中间件中。所有请求都先经过中间件,中间件中检测登录状态,有登录状态,请求正常执行(放行),否则在中间件中重定向到登录页面。
2、定义中间件
# 在任意目录(项目根目录或app目录)新建一个py文件class MyMiddleware(MiddlewareMixin):    def __init__(self, get_response):  # 初始化        super().__init__(get_response)        print("init1")    # view处理请求前执行    def process_request(self, request):  # 某一个view        print("request:", request)    # 在process_request之后View之前执行    def process_view(self, request, view_func, view_args, view_kwargs):        pass        # print("view:", request, view_func, view_args, view_kwargs)    # view执行之后,响应之前执行    def process_response(self, request, response):        print("response:", request, response)        return response  # 必须返回response    #    # 如果View中抛出了异常    def process_exception(self, request, ex):  # View中出现异常时执行        pass        # print("exception:", request, ex)
3、激活中间件
# 在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',    'uploadapp.mymiddleware.MyMiddleware',]
4、强制登录实例
def home(request):    return render(request, 'account/home.html')
def process_request(self, request):       # 将需要放行的URL存储一个列表中    pass_url = [reverse('account:login'),reverse('account:register')]    # 如果请求路径 在 放行的URL的列表中    if request.path in pass_url:        pass # 什么都不做    else:        is_login = request.session.get('is_login')        if is_login:            pass        else:            return redirect('account:login')

五、CSRF

1、简介
CSRF(Cross-site request forgery)跨站请求伪造,是一种常见网络攻击手段。
2、基本使用
django本身提供了防范CSRF攻击的机制具体做法:	在form表单的post请求中,	<form action='xx' method='post'>		{% csrf_token %}		xxx	</form>
3、实现原理
1. 在form表单中,添加了csrf_token,在渲染页面时,django会通过CsrfViewMiddleware在服务端生成一个随机的token(令牌),放在form表单的隐藏域中及cookie中。		<input type='hidden' name='csrfmiddlewaretoken' value='82KgpReeNNQh2PPICbVXxhqo3Q6dPE195rudsNSOgoWLcKOJcafvZoCmYbdZ3S2R' />	2. 当提交表单请求,request对象会携带cookie中的令牌 及form表单提交的隐藏域中的令牌到达服务器,然后django服务器的 CsrfViewMiddleware中间件会先验证判断两块令牌是否一致。

六、Admin管理后台

1. 前端页面-客户   2. 后台管理页面-管理员 3. 后端程序(程序员/公司的运维)之前:前端页面 + 后端程序以后:为了网站的管理和维护,我们需要给网站写一个后台管理页面 # 只要是使用django编写的项目,django框架会自动生成后台管理页面
1. 创建管理员帐户		python manage.py createsuperuser		2. 在app的admin.py中注册model类		admin.site.register(model类名)		3. 访问管理页面		http://127.0.0.1:8000/admin 即可访问		4. 修改管理页面为中文settings.py	LANGUAGE_CODE = 'zh-hans'	5. 可以自己定制admin的后台管理页面的界面- 符合django的规则   或不使用admin管理页面,自己去写
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值