ORM和模板

1.ORM

  • 介绍

    • ORM:对象关系映射
  • 作用:

    • #1.将定义数据库 `模型类 `--> 数据库表
      #2.将定义数据库模型类中的 `属性` ---> 数据库表`字段`
      #3.将模型对象的操作(save,delete,get) ---> 对应sql语句,并将执行结果提交到数据库
      
  • 优点:

    • 只需要面向对象编程, 不需要面向数据库编写代码.
    • 实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
  • 缺点:

    • 相比较直接使用SQL语句操作数据库,有性能损失.
    • 根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.

2.django中使用mysql的配置

  • 1.使用MySQL数据库首先需要安装驱动程序

  • pip install PyMySQL
    
  • 2.在Django的工程同名子目录的__init__.py文件中添加如下语句

  • from pymysql import install_as_MySQLdb
    	
    install_as_MySQLdb()
    
  • 3.修改DATABASES配置信息 [copy]

  • DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '127.0.0.1',  # 数据库主机
            'PORT': 3306,  # 数据库端口
            'USER': 'root',  # 数据库用户名
            'PASSWORD': 'mysql',  # 数据库用户密码
            'NAME': 'django_orm'  # 数据库名字
        }
    }
    
  • 4.在MySQL中创建数据库

  • create database django_orm default charset=utf8;
    
  • 扩展:

  • python2用到的mysql驱动叫: MySQLdb
    python3用到的mysql驱动叫: pymysql
        
    # 注意:
    一些框架默认仍然用的是MySQLdb,但是python3已经不支持MySQLdb,取而代之的是pymysql,因此运行的时候会报 
    ImportError: No module named ‘MySQLdb’
    
    # 解决方案:将pymysql转换成MySQLdb
    pymysql.install_as_MySQLdb()
    

3.定义模型类

  • 模型类被定义在"应用/models.py"文件中

  • 模型类必须继承自Model类

  • 定义模型类:

    from django.db import models
    
    #定义图书模型类BookInfo
    class BookInfo(models.Model):
        btitle = models.CharField(max_length=20, verbose_name='名称')
        bpub_date = models.DateField(verbose_name='发布日期')
        bread = models.IntegerField(default=0, verbose_name='阅读量')
        bcomment = models.IntegerField(default=0, verbose_name='评论量')
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    
        class Meta:
            db_table = 'tb_books'  # 指明数据库表名
            verbose_name = '图书'  # 在admin站点中显示的名称
            verbose_name_plural = verbose_name  # 显示的复数名称
    
        def __str__(self):
            """定义每个数据对象的显示信息"""
            return self.btitle
    
    #定义英雄模型类HeroInfo
    class HeroInfo(models.Model):
        GENDER_CHOICES = (
            (0, 'female'),
            (1, 'male')
        )
        hname = models.CharField(max_length=20, verbose_name='名称') 
        hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  
        hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') 
        hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    
        class Meta:
            db_table = 'tb_heros'
            verbose_name = '英雄'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.hname
    

4.执行数据库迁移

  • 作用 :

    • 1.当表不存在的情况,根据`模型类`创建--->数据库`关系表`
      2.当表已经存在的情况,当`模型类`属性修改 ----> 数据库表的`字段`跟着改变。
      
  • 步骤:

    • 1.生成迁移文件

    • python manage.py makemigrations
      
    • 2.同步到数据库中【此时数据库表才会生成】

    • python manage.py migrate
      
  • 注意:

    • 提示:no changes detected
    • 没有注册应用,迁移是发现不了models中的模型类

5.演示工具使用

  • shell工具

    • python manage.py shell
      
  • 查看mysql数据库日志

    • sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
      	general_log_file = ...
          
      sudo service mysql restart
      
      sudo tail -f /var/log/mysql/mysql.log  # 可以实时查看数据库的日志内容
      

6.数据库操作—增、删、改、查

  • 增加数据:

  • # 1.save()
    book = BookInfo(btitle='西游记后传',bpub_date='2020,1,1')
    book.save()
    # 2.object.create()
    book = BookInfo.objects.create(btitle='大三国',bpub_date='2019,11,11')
        
    hero = HeroInfo.objects.create(
        hname='曹操',
        hgender=0, 
        hbook=book, # 直接给外键赋值应该赋模型对象
        hbook_id=book.id   # 给外键_id字段赋值应该模型对应模型的id
    )
    
    
  • 删除数据:

  • 1)模型类对象delete
    	hero.delete()
    
    2)模型类.objects.filter().delete()
    """
    删除
    模型对象.delete()   删除当前这一个模型对象所代表的数据
    HeroInfo.objects.get(id=13).delete()
    HeroInfo.objects.filter(id=14).delete() 等同于QuerySet.delete()  默认删除查询集内的所有模型对象数据
    """
    # hero = HeroInfo.objects.get(id=23).delete()
    # hero = HeroInfo.objects.filter(id=21).delete()
    # book = BookInfo.objects.filter(id=5).delete()
    
  • 修改数据:

  • 1)修改模型类对象的属性,然后执行save()方法
        hero.hname = '猪悟能'
        hero.save()
    
    2)update
    	使用模型类.objects.filter().update(属性名=需要修改的属性值),会返回受影响的行数
    """
    修改
    把修改的对象查询出来,然后给对象重新赋值 save后才会修改表中数据  只能修改单一数量
    批量进行修改  只能是返回值为查询集的才能修改
    """
    # book = BookInfo.objects.get(id=1)
    # book.btitle='射雕英雄传外传'
    # book.save()
    
    # 批量进行修改
    read = BookInfo.objects.filter(id__gt=1)
    read.update(bread=100)
    
    
  • 基本查询:

  • """
    基本查询:
    get  单一查询   如果查询有多个数据,会报错;如果没有该数据,也会报错
    all   无条件查找所有
    cout    查询数据数量
    """
    # book = BookInfo.objects.get(id=1)
    # book = BookInfo.objects.get(btitle='小三国')
    # print(book)
    
    # book = BookInfo.objects.all()  # 返回的数据是查询集QuerySet
    # print(book)
    
    
    #book = BookInfo.objects.count()
    #print(book)
    

7.过滤查询

  • filter 过滤出多个结果

  • exclude 排除掉符合条件剩下的结果

  • get 过滤单一结果

  • 过滤条件的表达语法如下:

  • 属性名称__比较运算符=# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
    
  • 演练:

    """
    过滤查询
    get    单一查询
    filter   根据条件查询满足条件的任意数量的数据
    exclude   查询满足条件以外的数据
    contains   包含
    endswith startswith  以什么结尾  以什么开头
    isnull   不为空
    in    在...中
    gt/gte/lt/lte   大于/大于等于/小于/小于等于
    exclude   不等于
    模型属性字段__运算符
    """
    # book = BookInfo.objects.get(id=5)
    # book = BookInfo.objects.filter(bread=50) # 当查询的数据不存在时,也不会报错
    # book = BookInfo.objects.filter(id=5)  #返回的是查询集
    # book = BookInfo.objects.exclude(id=3)  #返回的也是查询集
    # book = BookInfo.objects.filter(id__exact=2)  # 等同于filter(id=2)
    # book = BookInfo.objects
    # print(book)
    # 1.查询编号为1的图书。
    # book = BookInfo.objects.get(id=1)
    # book = BookInfo.objects.filter(id=1)
    # book = BookInfo.objects.filter(id__exact=1)
    # 2.查询书名包含'传'的图书。contains
    # book = BookInfo.objects.filter(btitle__contains='传')
    # 3.查询书名以'部'结尾的图书 endswith startswith
    # book = BookInfo.objects.filter(btitle__endswith='部')
    # 4.查询书名不为空的图书。 isnull = False
    # book = BookInfo.objects.filter(btitle__isnull=False)
    # 5.查询编号为1或3或5的图书  in
    # book = BookInfo.objects.filter(id__in=(1,3,5))
    # book = BookInfo.objects.filter(id__in=[1,3,5])
    # 6.查询编号大于3的图书 gt/lt/gte/lte
    #  gt 表示大于  gte表示大于等于  lt表示小于 lte表示小于等于
    # book = BookInfo.objects.filter(id__gt=3)
    # book = BookInfo.objects.filter(id__gte=3)
    # book = BookInfo.objects.filter(id__lt=3)
    # book = BookInfo.objects.filter(id__lte=3)
    # 7.查询编号不等于3的图书 exclude
    # book = BookInfo.objects.exclude(id=3)
    # 8.查询1980年发表的图书。year/month/day/...
    # book = BookInfo.objects.filter(bpub_date__year=1980)
    # book = BookInfo.objects.filter(bpub_date__month=11)
    # book = BookInfo.objects.filter(bpub_date__day=12)
    # 9.查询1980年1月1日后发表的图书。
    # book = BookInfo.objects.filter(bpub_date__gt='1980-1-1')
    book = BookInfo.objects.filter(bpub_date__gt=date(1980,1,1)) # 这里需要导入模块 from datetime import date
    

8.F和Q对象使用

  • 步骤:

  • 1.导包
    from django.db.models import F,Q
    2.对比两个字段使用F对象: F(属性名) 实现两个字段之间的+-*/
    3.查询多个条件使用Q对象:  Q(属性名__运算符=)  可以实现and or not和一些基本查询
    符号: &  |  ~
    
  • 演练:

    1. # 1.查询阅读量大于等于评论量的图书
      # book = BookInfo.objects.filter(bread__gte=F('bcomment'))
      # 2.查询阅读量大于2倍评论量的图书
      # book = BookInfo.objects.filter(bread__gte=F('bcomment') * 2)
      # 3.查询阅读量大于20,并且编号小于3的图书
      # book = BookInfo.objects.filter(bread__gte=20,id__lt=3)
      # book = BookInfo.objects.filter(Q(bread__gt=20)&Q(id__lt=3))
      # 4.查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现
      # book = BookInfo.objects.filter(Q(bread__gt=20) | Q(id__lt=3))  # 需要导入Q模块
      # 5.查询编号不等于3的图书 exclude
      # book = BookInfo.objects.exclude(id=3)
      # book = BookInfo.objects.filter(~Q(id=3))
      

    9.聚合函数&排序

    • 聚合函数

      • 包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 总和
      • aggregate()过滤器调用聚合函数。
    • 排序

      • 使用order_by对结果进行排序

      • order_by(字段) 
        	默认是升序:字段名
        	降序: -字段名
        
    • 使用:

    • """
      聚合函数作用:进行对某列数据进行运算  
      返回值为字典  字典的key值为:查询的字段名__聚合函数的名字  bread__sum   bread__avg
      """
      # from django.db.models import F, Q, Sum, Avg, Count, Max, Min
      # book = BookInfo.objects.aggregate(Sum('bread'))    
      # book = BookInfo.objects.aggregate(Avg('bread'))
      # book = BookInfo.objects.aggregate(Count('bread'))
      # book = BookInfo.objects.aggregate(Max('bcomment'))
      # book = BookInfo.objects.aggregate(Min('bread'))
      
      """
      排序  
      order_by('字段名')  默认为升序
      order_by('-字段名')  为降序
      """
      
      # book = BookInfo.objects.order_by('bread')  # 如果有相同的数据 会按照id从小到大
      book = BookInfo.objects.order_by('-bread')  #如果字段里面的数据相同 不管升序还是降序 会按照id从小到大排序
      
      

    10.关联查询

    • 关联查询

      • 书籍 [一] <—> 英雄 [多]

      • """
        关联基本查询
        1.一个查多个  一个的模型对象.多的模型名小写_set.all() 
        BookInfo.objects.get(btitle='天龙八部').heroinfo_set.all()
        2.一个查多个  一个的模型对象.多的模型名小写_set.filter(写条件)
        BookInfo.objects.get(btitle='天龙八部').heroinfo_set.filter(hname='乔峰')
        3.多个查一个  多的模型对象.hbook
        HeroInfo.objects.get(hname='令狐冲').hbook
        """
        
        # 案列:查询天龙八部中所有英雄
        # book = BookInfo.objects.get(btitle='天龙八部').heroinfo_set.all()
        # book = BookInfo.objects.get(btitle='天龙八部').heroinfo_set.filter(hname='乔峰')
        # 案列:查询令狐冲英雄属于哪个本书籍
        # hero = HeroInfo.objects.get(hname='令狐冲').hbook
        
      • #2. 多查一 语法: 多对应的模型类对象.外键属性名称
        	hero.hbook
        """
        关联基本查询
        1.一个查多个  一个的模型对象.多的模型名小写_set.all() 
        BookInfo.objects.get(btitle='天龙八部').heroinfo_set.all()
        2.一个查多个  一个的模型对象.多的模型名小写_set.filter(写条件)
        BookInfo.objects.get(btitle='天龙八部').heroinfo_set.filter(hname='乔峰')
        3.多个查一个  多的模型对象.hbook
        HeroInfo.objects.get(hname='令狐冲').hbook
        """
        
        # 案列:查询天龙八部中所有英雄
        # book = BookInfo.objects.get(btitle='天龙八部').heroinfo_set.all()
        # book = BookInfo.objects.get(btitle='天龙八部').heroinfo_set.filter(hname='乔峰')
        # 案列:查询令狐冲英雄属于哪个本书籍
        # hero = HeroInfo.objects.get(hname='令狐冲').hbook
        

    11.关联过滤查询

    • 关联过滤查询:

      • 书籍 [一] <—> 英雄 [多]

      • # 案列:查询图书,要求图书英雄为"东方不败"
        # 案例:查询图书,要求图书中英雄的描述包含"八"
        # 案列:查询 书名为“天龙八部”的所有 英雄
        # 案列:询图 书阅读量大于30的所有 英雄
        
        #《一》多模型类条件 查询 一模型类数据: 多查一
        # 语法:关联模型类名小写__属性名__条件运算符=值
        	heroinfo__hname__exact="东方不败"
        
        # 案列:查询图书,要求图书英雄为"东方不败"
        	BookInfo.objects.filter(heroinfo__hname__exact="东方不败")
        
      • #《二》 一模型类条件 查询 多模型类数据 : 一查多
        #语法:外键名称__一模型类属性名__条件运算符=值
            hbook__btitle__exact="天龙八部"
        
        # 案列:查询 书名为“天龙八部”的所有 英雄
            HeroInfo.objects.filter(hbook__btitle__exact="天龙八部")
           
        # 案列: 询图 书阅读量大于30的所有 英雄
            HeroInfo.objects.filter(hbook__bread__gt=30)
        
        
    """
    关联过滤查询
    1.一个查多个  filter(多个里面的对象字段作为查询条件)
    filter(heroinfo__hname='东方不败')   
    filter(heroinfo__hcomment__contains='八')
    2.多个查一个  filter(外键作为查询条件)
    filter(hbook__btitle='天龙八部')
    filter(hbook__bread__gt=30)
    """
    # 案列:查询图书,要求图书英雄为"东方不败"
    # book = BookInfo.objects.filter(heroinfo__hname='东方不败')
    # print(book)
    # 案例:查询图书,要求图书中英雄的描述包含"八"
    # book = BookInfo.objects.filter(heroinfo__hcomment__contains='八')
    # print(book)
    # 案列:查询书名为“天龙八部”的所有 英雄
    # hero = HeroInfo.objects.filter(hbook__btitle='天龙八部')
    # print(hero)
    # 案列:询图书阅读量大于30的所有英雄
    # hero = HeroInfo.objects.filter(hbook__bread__gt=30)
    

    12.查询集 QuerySet

    • 概念:

      • 查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。

      • all、filter、exclude、order_by 函数返回的查询集

      • 支持迭代执行

        books = BookInfo.objects.all().filter(id__in=[1,3,5,8]).order_by("bread").filter(id=1)
        
    • 两大特性:

      • 惰性执行: 不查询结果,不会发生sql语句给数据
      • 缓存: 访问的数据在查询结果集中,不会访问数据库数据
    • 支持切片访问:[0], [0:3] …

      • 不支持负数使用

    13.Django模板语法

    • 模板变量: 字母、数字、下划线(不能开头)

      • from django.shortcuts import render
        from django import http
        from django.views import View
        from booktest.views import BookInfo,HeroInfo
        # Django中的模板
        # 使用Django中的模板  需要用到render这个函数  需要导入模块 from django.shortcuts import render
        class Templates(View):
            def get(self,request,*args,**kwargs):
                # return render(request='请求对象',template_name='模板文件',context='上下文(传递的数据必须是字典类型)')
                # return render(request,'index.html',)
                book = BookInfo.objects.get(id=1)
                content={
                    'name':'ssj',
                    'age':18,
                    'book':book,  # 调用对象是调对象的属性  即.对象的属性
                    'alist':['A','B','C'],
                    'dict':{'sex':1,'height':185},
                    'num':5,
                    'word':'<h1>你们失败了</h1>'
                }
        
        
                return render(request,'index.html',context=content)
        
      • 注意:字典取值方法和列表的取值方法(以点访问)

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>英雄联盟</title>
        </head>
        <body>
            人在塔在
        {#    <h1>{{ name }}</h1>#}
        {#    <h1>{{ age }}</h1>#}
        {#    <h1>{{ book.btitle }}</h1>#}
        {#    <h1>{{ alist }}</h1>#}
        {#    <h1>{{ alist.2 }}</h1>#}
        {#    <h1>{{ dict }}</h1>#}
        {#    <h1>{{ dict.keys }}</h1>#}
        {#    <h1>{{ dict.values }}</h1>#}
        {#    {% for item in dict.keys%}#}  {# 得到字典的key #}
        {#    {% for item in dict.values%}  {# 得到字典的values #}
            {% for item in dict.items%}  {# 得到字典的键值对 #}
                <li>{{ item }}</li>
                <li>{{ forloop.revcounter0 }}</li>
            {% endfor %}
            {% if num == 1 %}
                <h1>哈哈</h1>
            {% elif num == 2 %}
                <h1>才错了</h1>
            {% else %}
                <h1>油菜错乐</h1>
            {% endif %}
        {#    {% if  %}#}
            {{ word }}
            {{ word | safe}}
        </body>
        </html>
        
    • 模板语句

      • for循环 {% for var in list %}

        • ​ {% endfor %}

          {#    {% for item in dict.keys%}#}  {# 得到字典的key #}
          {#    {% for item in dict.values%}  {# 得到字典的values #}
              {% for item in dict.items%}  {# 得到字典的键值对 #}
                  <li>{{ item }}</li>
                  <li>{{ forloop.revcounter0 }}</li>
              {% endfor %}
              {% if num == 1 %}
                  <h1>哈哈</h1>
              {% elif num == 2 %}
                  <h1>才错了</h1>
              {% else %}
                  <h1>油菜错乐</h1>
              {% endif %}
          {#    {% if  %}#}
              {{ word }}
              {{ word | safe}}
          </body>
          </html>
          
              {% for num in adict.values %}
          {#    {% for num in adict %}#}
                  <li>{{ num }}</li>
              {% endfor %}
              </ul>
          </body>
          </html>
          
      • if条件 {% if a == 1 %}

        • 比较运算符(==,!=, >, <, <=, >=)
        • 布尔运算符(and, or, not)
      • 注意:(运算符左右两侧不能紧挨变量或者常量)

            {% if num == 1 %}
                <h1>哈哈</h1>
            {% elif num == 2 %}
                <h1>才错了</h1>
            {% else %}
                <h1>油菜错乐</h1>
            {% endif %}
        {#    {% if  %}#}
            {{ word }}
            {{ word | safe}}
        </body>
        </html>
        

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DjXLQBT1-1587393072105)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1577095621205.png)]

14.django自带模板的过滤器使用

  • 作用:

    • 让变量内容按照需求格式化输出
  • 语法:

    • 变量|过滤器:参数
  • 系统常见过滤器:

    • safe :

      fdjsk

    • length
    • default
    • date
      • Y表示年,格式为4位,y表示两位的年。

      • m表示月,格式为01,02,12等。

      • d表示日, 格式为01,02等。

      • j表示日,格式为1,2等。

      • H表示时,24进制,h表示12进制的时。

      • i表示分,为0-59。

      • s表示秒,为0-59。

            {#这是一个过滤器 让h1显示其功能#}
            {{ htmltext | safe}}
            {# 显示字符长度  #}
            {{ htmltext | length}}
            {# htmltext2不存在,会显示default后面的内容 #}
            {{ htmltext2 | default:'哈哈'}}
        </body>
        </html>
        

15.django自定义过滤器步骤

  • template提供的内置过滤器,不够用,不灵活,就可以自己定义一个过滤器

  • 自定义过滤器步骤:

  • 要进行自定义过滤器的应用一定要注册,并且编写自定义过滤器的包名必须叫templatetags

    • 1.在自己的app里建一个templatetags包, 并创建一个后面要在HTML文件引用的py文件

    • 哪个应用要使用自定义模板 就要把templatetags创建到该应用下

      • templatetags.listreverse.py
    • 2.导入template包

      • from django import template
    • 3.创建注册对象

      • register = template.Library()
    • 4.自定义函数完成列表反转,利用装饰器将注册自定义的过滤器 [ps 函数名即为过滤器名称]

      • @register.filter
        def do_listreverse(x):
            ...
        
  • 使用:

    • 5.load加载定义过滤器的py文件
      • {% load listreverse %}
    • 6.使用自定义的过滤器
      • {{ list | do_listreverse }}

16.模板的继承

  • 作用:

    • 模板继承和类的继承含义是一样的,主要是为了提高代码重用,将相同的内容封装到父模板中。
  • 步骤:

    • # 1.在父模板中将不同的内容,需要重写的内容使用block包含起来
      	{% block 名称 %}
          ...
          {% endblock 名称 %}
      # 2.继承父模板:
      	{% extends "父模板路径"%}
      # 3.在子模板中重写block实现特定代码
      	{% block 名称 %}
          实际填充内容
          {{ block.super }}用于获取父模板中block的内容
          {% endblock 名称 %}
      

17.Django中使用jinja2模板

  • 介绍:

    • 相对django默认模板引擎而言,jinja2 引擎功能齐全,速度快。
  • 使用步骤:

    • 1.安装jinja2模块

      • pip install jinja2
    • 2.配置jinja2

      • 新建文件jinja2_env.py

      • from jinja2 import Environment
        
        def environment(**options):
            env = Environment(**options)
        
            return env
        
      • 修改settings.py配置信息

        TEMPLATES = [
            {
                'BACKEND': 'django.template.backends.jinja2.Jinja2',#修改1
                'DIRS': [os.path.join(BASE_DIR, 'templates')],
                'APP_DIRS':True,
                'OPTIONS':{
                    'environment': 'jinja2_env.environment',# 修改2
                    'context_processors':[
                        'django.template.context_processors.debug',
                        'django.template.context_processors.request',
                        'django.contrib.auth.context_processors.auth',
                        'django.contrib.messages.context_processors.messages',
                    ],
                },
            },
        ]
        
    • jinja2在使用上和django自带模板差异

      • 1.for循环有差异

        • Forloop.counter --> loop.index
      • 2.jinja2自定义过滤器

        • from jinja2 import Environment
          
          def environment(**options):
              env = Environment(**options)
              env.filter['listreverse'] = listreverse
              
              return env
          
          def listreverse(list):
              list.reverse()
              return list
          

18.自定义管理器Manager

  • 概念:

    • Django会为每一个模型类生成一个管理器对象:objects [ all filter get ]
  • 自定义管理器:

    • 当系统的管理器对象提供的方法不够用或者使用不方便的时候我们可以:自定义管理器

    步骤:

    • 1.自定义一个管理器类,继承models.Manager
      2.重写或者自定义管理器中的方法
      3.将管理器对象添加到模型类中
      
    • 注意:一旦为模型类指明自定义的管理对象后,Django不再生成默认管理对象objects。

Admin站点管理基本使用

  • 使用步骤:

    • 管理界面本地化

    • LANGUAGE_CODE = 'zh-hans' # 使用中国语言
      TIME_ZONE = 'Asia/Shanghai' # 使用中国上海时间
      
    • 创建管理员

    • python manage.py createsuperuser
      输入用户名、邮箱、密码
      
      扩展:修改密码:
      	python manage.py changepassword 用户名
      
    • 注册模型类

      #子应用/admin.py:
          
      from booktest.models import BookInfo,HeroInfo
      
      admin.site.register(BookInfo)
      admin.site.register(HeroInfo)
      
    • 自定义管理页面 …

  • 调整站点信息:

    • admin.site.site_header 设置网站页头
    • admin.site.site_title 设置页面标题
    • admin.site.index_title 设置首页标语

调整列表页展示

  • 自定义与使用Admin管理类调整列表页面的UI显示:

    • 1.自定义管理类需要继承自admin.ModelAdmin类
      2.注册管理类:admin.site.register(BookInfo,BookInfoAdmin)
      3.修改显示的属性:
      	#1. 每页中显示多少条数据,默认为每页显示100条数据
          list_per_page 
      
          #2. "操作选项"的位置
          action_on_top
          action_on_bottom
          
          #3. 列表中展示的属性
          list_display = [需要显示的字段,....]
       
      	#4. 右侧栏过滤器
          list_filter = [需要过滤的属性,....]
          
          #5. 搜索框
          search_fields = []
      

调整列表页展示-[关联对象]

  • 将自定义方法的返回值作为列的名称展示

    • 1.1 在模型列中自定义方法,并且返回需要显示的数据内容的格式
          def pub_date(self):
              return self.bpub_date.strftime('%Y-%m-%d')
      
      1.2 修改展示中文名称和添加排序功能[copy]:
          pub_date.short_description = '发布日期'
          pub_date.admin_order_field = 'bpub_date'
      
      1.3 注册显示
      	list_display = ['pub_date']
      
  • 显示关联对象的属性

    • #比如:在英雄列中显示书籍的阅读量
      
      #2.1 在模型列中自定义方法,并且返回需要显示的数据内容的格式
       def read(self):
              #      英雄.书籍.阅读量
              return self.hbook.bread	
          
      #2.2 展示中文名字:
          read.short_description = "阅读量"
      
      #2.3 注册显示
      	list_display = ['read']
      
      
    • 注意:关联对象不能指定排序依据

调整编辑页展示

  • #1. 显示字段
    	fields=[]
    
    #2. 分组显示	
        fieldsets=(
            ('组1标题',{'fields':['字段1','字段2']}),
            ('组2标题',{'fields':['字段3','字段4']}),
        )
        
        注意:逗号不能丢
        # 是否折叠显示
        'classes': ('collapse',)  
    
    #3. 关联对象
    比如: 在修改书籍的编辑页面,也可以添加英雄
    
    #1.自定义管理类
        1.1.如果显示格式以`表格`的形式嵌入
            继承子类TabularInline
    
        1.2.如果显示格式以`块`的形式嵌入
            继承子类StackedInline
        
        	class HeroInfoStackInline(admin.StackedInline):
        		model = HeroInfo  # 要编辑的对象
        		extra = 1  # 附加编辑的数量
        
    #2. 在BookInfoAdmin类下 注册:
    	inlines = [HeroInfoStackInline]
    
  • 注意:fields和fieldsets两者选一使用

通过站点管理上传图片

  • 步骤:

  • #1. 安装模块:
    	pip install Pillow
        
    #2. 配置图片保存的路径 (需要提取创建media文件夹)
    	MEDIA_ROOT=os.path.join(BASE_DIR,"media")
    
    #3. 为模型类添加ImageField字段:
        image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)
    	注释:upload_to 选项指明该字段的图片保存在MEDIA_ROOT目录中的哪个子目录
        
    #4. 修改了模型类的属性,需要借助 `数据库迁移` 同步修改数据表的字段
    	python manage.py makemigrations
    	python manage.py migrate
        
    #5. 回到admin中在详情页添加”image“属性展示
    	("必填", {"fields":["btitle", "bpub_date", "image"]}),
    
    

csrf攻击和防护理解[理解&面试]

  • 概念:

    • 跨站请求伪造
    • 指攻击者盗用了你的身份,以你的名义发送恶意请求。
      • 包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…
  • 防止 CSRF 攻击步骤:

    • 在返回转账页面模板的时候: GET
      # 1.在模板中返回csrf_token随机加密字符串
      # 2.在cookie中设置了csrf_token随机加密字符串
      # 3.在模板中input输入框记录 csrf_token  格式: csrf_token : "随机加密字符串" 
      
      在发送请求的时候:POST
      # 1.提取form表单携带的csrf_token
      # 2.提取cookie中的csrf_token
      # 3.校验对比这两个字段的值是否一致,如果不一致:表示非法请求
      

django中使用csrf防护

  • # 使用csrf中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    
    # 在模板的form中加入下面:
    {% csrf_token %}
    

geField字段:
image = models.ImageField(upload_to=‘booktest’, verbose_name=‘图片’, null=True)
注释:upload_to 选项指明该字段的图片保存在MEDIA_ROOT目录中的哪个子目录

#4. 修改了模型类的属性,需要借助 `数据库迁移` 同步修改数据表的字段
	python manage.py makemigrations
	python manage.py migrate
    
#5. 回到admin中在详情页添加”image“属性展示
	("必填", {"fields":["btitle", "bpub_date", "image"]}),

```

csrf攻击和防护理解[理解&面试]

  • 概念:

    • 跨站请求伪造
    • 指攻击者盗用了你的身份,以你的名义发送恶意请求。
      • 包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…
  • 防止 CSRF 攻击步骤:

    • 在返回转账页面模板的时候: GET
      # 1.在模板中返回csrf_token随机加密字符串
      # 2.在cookie中设置了csrf_token随机加密字符串
      # 3.在模板中input输入框记录 csrf_token  格式: csrf_token : "随机加密字符串" 
      
      在发送请求的时候:POST
      # 1.提取form表单携带的csrf_token
      # 2.提取cookie中的csrf_token
      # 3.校验对比这两个字段的值是否一致,如果不一致:表示非法请求
      

django中使用csrf防护

  • # 使用csrf中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    
    # 在模板的form中加入下面:
    {% csrf_token %}
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值