Django杂记2

ADMIN
  • admin.py
    把自己的模型类注册到管理后台
from django.contrib import admin
from .models import MyModel
# 注册自己的模型类
admin.site.register(MyModel)
模型管理器类
  • admin.py
    定义模型管理器类
class MyManager(admin.ModelAdmin):
	# 自定义列表页显示的字段
	list_display = ['id','f1','f2','f3']
	# 修改跳转链接关联的字段 
	list_display_links = ['f1']
	# 点击跳转显示自定义可编辑字段
	# fields = ['f1','f2','f3']
	# 和fields 二选一,fieldsets可以为字段添加面板头
	fieldsets = [
        (None, {'fields': ['title']}),
        ('出版社', {'fields': ['pub']}),
        ('Date information', {'fields': ['pub_date']}),
    ]
	# 添加过滤器
	list_filter = ['f2']	
  # 添加搜索框[模糊查询]
  search_fields = ['title']
  # 添加可在列表页编辑的字段
  list_editable = ['price']

fieldsets的效果
在这里插入图片描述

绑定注册模型管理器和模型类

from django.contrib import admin
from .models import *
admin.site.register(MyModel,MyManager)
# 绑定MyModel模型类到管理器类MyManager
管理后台模型类显示名称单,复数
class Meta:
	db_table = 'book'
	verbose_name = '图书'
	verbose_name_plural = verbose_name

关系映射

一对一

synax:
OneToOneField(类名,on_delete=xxx)

class A(models.Model):
	pass
class B(models.Model):
	...
	foto = models.OneToOneField(A, on_delete = models.CASCADE)

注意: 数据库中存储的foto字段名称为foto_id

    • 先创建一行a的数据
    • 再创建b的数据
      a1 = A.objects.create('f1'='xxx')
      b1 = B.objects.create('f1'='yyy', foto=a1)
  1. 正查
    • 先获取b对象
    • .查询外键foto的属性
      b1=B.objects.get(f1='b1')
      b1.foto.f1
  2. 反查
    • 先获取a对象
    • .查询被关联的B表类名的小写,来获取一个b对象
      a1=A.objects.get(f1='a1')
      a1.b.f1
一对多

synax:
ForeignKey(类名,on_delete=xxx)

模型类结构和一对一 一样

class A(models.Model):
	pass
class B(models.Model):
	...
	fotm = models.ForeignKey(A, on_delete = models.CASCADE)
    • 先创建一行a的数据
    • 再创建多行b的数据,关联到相同的外键
      a1 = A.objects.create('f1'='xxx')
      b1 = B.objects.create('f1'='yyy', fotm=a1)
      b2 = B.objects.create('f1'='zzz', fotm=a1)
  1. 正查
    • 同一对一,先获取b对象,再 用.查询外键fotm的属性
      b1=B.objects.get(f1='b1')
      b1.fotm.f1
  2. 反查
    • 先获取a对象
    • 通过.关联类名小写_set查询关联的属性,因为一对多,所以增加了一个_set来获取一个objects
      a1=A.objects.get(f1='a1')
      a1.b_set.all()
    • A中的外键a1被删除掉后,B中的多行数据都会被级联删除
    • B中的数据删除了,不会影响A表数据
多对多
  • mysql中多对多要依赖第三张表
  • Django不需要第三张表,自动完成

synax:
ManyToManyField(类名)

class A(models.Model):
	pass
class B(models.Model):
	...
	fmtm = models.ManyToMaynField(A)
  1. 正增
    • 先创建一行b的数据
    • 再通过b的外键,创建一行a的数据
    • b也可以同时 绑定到其他 a
      b1 = B.objects.create('f1'='yyy')
      a1 = b1.fmtm.create('f1'='xxx')
      b1.fmtm.add(a2)
  2. 反增
    • 先创建多行a的数据
    • 再创建一条b的数据
    • 在把新建的b,绑定给其他a
      a1 = A.objects.create('f1'='xxx1')
      a2 = A.objects.create('f1'='xxx2')
      b1 = a1.b_set.create('f1'='yyy')
      a2.b_set.add(b1)
  3. 正查
    • ,先获取b对象,再 用.查询外键fmtm, fmtm可以看做一个objects.
      b1=B.objects.get(f1='b1')
      b1.fmtm.all()
  4. 反查
    • 先获取a对象
    • 通过.关联类名小写_set查询关联的属性
      a1=A.objects.get(f1='a1')
      a1.b_set.all()

cookies和session

  • js原生session操作
    sessionStorage.setItem('key','value')
    value = sessionStorage.getItem('key')
cookies

cookies是服务器发起请求,存储在客户端中的,所以设置cookies的方法,被封装进了HttpResponse

synax:
设置:
HttpResponse.set_cookie(key,value='',max_age=None, expires=None)
不指定max_ageexpires时,关闭浏览器数据失效
max_age 设置过期时间,单位是秒

获取:
value = request.COOKIES.get('cookies名','默认值')

删除:
HttpResponse.delete_cookie(key)

views.py

def set_cookies(request):
	resp = HttpResponse('set cookies is ok')
	resp.set_cookie('uuid','jdj-kldjl-jd',500)
	return resp

设置过期变量

from datetime import datetime,timedelta
expires = datetime.now()+timedelta(days=7))
session

session是客户端请求,服务器存储的,所以session被封装成了request中的一个字典
客户端只存一个sessionid.
服务器端根据客户端存储的sessionid去调对应的数据,返回给客户端

  1. 保存
    request.session['key']=value
  2. 获取
    request.session['key']
    request.session.get('key',默认值)
  3. 删除
    del request.session['key']

views.py

def set_session(request):
	request.session['uuid'] = 'jdj-kldjl-jd'
	return HttpResponse('set session is ok')

分页

django.core.paginator

paginator的属性

  • count: 需要分页数据的对象总数
  • num_pages:分页后的页面总数
  • page_range:从1开始的range对象,用于记录当前的页码数
  • per_page:每页数据的个数

paginator的方法

  • paginator.page(number)

    • 属性number为页码信息
    • 返回当前number页对应的信息,一个page对象
    • 如果页码不存在,抛出InvalidPage异常
  • page对象

    属性

    • object_list: 当前页上所有数据对象的列表
    • number:当前页的序号,从1开始
    • paginator:当前page对象相关的Paginator对象

    方法

    • has_next(): 有下一页,返回True
    • has_previous():有上一页返回True
    • has_other_pages(): 有上或下页 返回True
    • next_page_number(): 返回下一页的页码,不存在,抛InvalidPage
    • previous_page_number():返回上一页页码,不存在,抛InvalidPage

封装一个分页函数

views.py

# 封装一个分页函数
def my_paginator(object_list, request, per_page=8, nav_num=5):
    # object_list: 传入的数据列表
    # request: 请求
    # per_page: 默认每页8条数据
    # nav_num: 默认导航条标签数量5

    paginator = Paginator(object_list, per_page)
    # 取出当前需要暂时的页码, 默认为1
    c_page = int(request.GET.get('page', 1))
    if c_page < 1:
        c_page = 1
    if c_page > paginator.num_pages:
        c_page = paginator.num_pages
    # 取出当前页数据
    try:
        page = paginator.page(c_page)
    except Exception as e:
        print('exception: ', e)
        page = paginator.page(1)
    # 显示导航页数 5
    if paginator.num_pages < nav_num + 1:
        # 小于5页,全部显示
        dis_range = range(1, paginator.num_pages + 1)
    else:  # 总页数,大于等于5页
        if c_page + nav_num // 2 >= paginator.num_pages:
            # 当前页+跨度>=总页数时
            dis_range = range(c_page - nav_num // 2, paginator.num_pages + 1)
        elif c_page - nav_num // 2 < 1:
            # 当前页-跨度 <= 1时
            dis_range = range(1, nav_num + 1 )
        else:
            dis_range = range(c_page - nav_num // 2, c_page + nav_num // 2 + 1)

    rst = {'page': page, 'paginator': paginator, 'dis_range': dis_range}
    print('dis_range: ', dis_range)
    return rst    

views.py
调用封装函数

def test_page(request):
    # /test_page/4
    # /test_page?page=1
    page_num = request.GET.get('page', 1)
    # 虚拟数据
    all_data = []
    for i in range(60):
        all_data.append('a' + str(i))
    rst = my_paginator(all_data, request, 8, 5)
    return render(request, 'test_page.html', locals())

模板test_page.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>分页</title>
    <link rel="stylesheet" href="{% static 'bootstrap/dist/css/bootstrap.css' %}">
</head>
<body>
<h1>BOOTSTRAP分页练习</h1>
{% for p in rst.page.object_list %}
    <p>
        {{ p }}
    </p>
{% endfor %}
<nav aria-label="Page navigation example">
    <ul class="pagination">
        {% if rst.page.has_previous %}
            <li class="page-item">
                <a class="page-link" href="/test_page?page={{ rst.page.previous_page_number }}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
        {% else %}
            <li class="page-item">
                <a class="page-link" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
        {% endif %}

        {% for c_page in rst.dis_range %}
            {% if rst.page.number == c_page %}
                <li class="page-item active"><a class="page-link" href="/test_page?page={{ c_page }}">{{ c_page }}</a></li>
            {% else %}
                <li class="page-item"><a class="page-link" href="/test_page?page={{ c_page }}">{{ c_page }}</a></li>
            {% endif %}
        {% endfor %}

        {% if rst.page.has_next %}
            <li class="page-item">
                <a class="page-link" href="/test_page?page={{ rst.page.next_page_number }}" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        {% else %}
            <li class="page-item">
                <a class="page-link" href="#" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        {% endif %}
    </ul>
</nav>

<a class="btn btn-info" href="/make_page_csv?page={{ rst.page.number }}">下载当前页数据</a>

<script src="{% static 'jquery.js' %}"></script>
<script src="{% static 'bootstrap/dist/js/bootstrap.js' %}"></script>

</body>
</html>

缓存页面

  • 配置
    settings.py
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table', 
        'TIMEOUT': 300,  # 缓存保存时间 单位秒 ,默认值为300,
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 缓存最大数据条数
            'CULL_FREQUENCY': 2,  # 缓存条数达到最大值时, 删除1/x的缓存数据
        }
    }
}
  • 创建数据库缓存表
    python manage.py createcachetable

  • 给面页加装饰器
    views.py

from django.views.decorators.cache import cache_page

@catch_page(30) ->单位s
def my_view(request):
	...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q_M_Y_Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值