python学习笔记-Django

#==============================jango架站==============================
# 环境
    # python3.6
    # django2.1
# 参考资料
    # [django中文教程](http://python.usyiyi.cn/)
    # django架站的16堂课
# 环境搭建
# anaconda+pycharm
# pip install django=1.8(版本号)
 
# 后台需要的流程

# 创建第一个django程序

django-admin startproject project_name

# 命令行启动

    cd project_name
    python manage.py runserver

# pycharm 启动
    # 需要配置
    # 对manage.py进行配置,填写manage.py的参数值"runserver"
    
#==============================路由系统-urls==============================
# 创建app
    # app:负责一个具体业务或者一类具体业务的模块

    python manage.py startapp app01

# settings.py中的INSTALLED_APPS中注册app

# 路由
    # 按照具体的请求url,导入到相应的业务处理模块的一个功能模块
    # django的信息控制中枢
    # 本质上是接受的URL和相应的处理模块的一个映射
    # 在接受URL请求的匹配上使用了RE
    # URL的具体格式入urls.py中所示
# 需要关注两点:
    1. 接受的URL是什么,即如何用RE对传入URL进行匹配
    2. 已知URL匹配到哪个处理模块
   
# url匹配规则
    # 从上往下一个一个比对
    # url格式是分级格式,则按照级别一级一级往下比对,主要对应url包含子url的情况
    # 子url一旦被调用,则不会返回到主url
        # `/one/two/three/`
    # 正则以r开头,表示不需要转义,注意尖号(^)和美元符号($)
        # `/one/two/three` 配对 r'^one/
        # `/oo/one/two/three` 不配对 r'^one/"
        # `/one/two/three/` 配对 r'three/$'
        # `/oo/one/two/three/oo/` 不配对 r'three/$"
        # 开头不需要有反斜杠
    # 如果从上向下都没有找到合适的匹配内容,则报错
    
# 2. 正常映射
# 把某一个符合RE的URL映射到事物处理函数中去
    # 举例如下:# url.py:

from django.contrib import admin
from app01 import views as av01
from django.url import path, re_path

urlpatterns = [
  path('admin/', admin.site.urls),
  
  re_path(r'^gofun01/', av01.fun01),
]

# app01-views.py:

from django.http import HttpResponse
def fun01():
    return HttpResponse("fun01")

# 3. URL中带参数映射
# 在事件处理代码中需要由URL传入参数,形如 /myurl/param中的param
# 参数都是字符串形式,如果需要整数等形式需要自行转换
# 通常的形式如下:
# url.py:

```
  /search/page/432 中的 432需要经常性变换,所以设置成参数比较合适
```
urlpatterns = [
    re_path('first/(?P\d+)', av01.fun02),
]
# app01-views.py:
def fun02(param):
    return HttpResponse("fun02"+param)

# 4. URL在app中处理
# 如果所有应用URL都集中tulingxueyuan/urls.py中,可能导致文件的臃肿
# 可以把urls具体功能逐渐分散到每个app中
    # 从django.conf.urls 导入 include
    # 注意此时RE部分的写法
    # 添加include导入
# 使用方法
    # 确保include被导入
    # 写主路由的开头url
    # 写子路由
    # 编写views函数
# 同样可以使用参数    
# url.py:

from django.url import path, re_path, include
from app01 import app01_url
path('goapp01/', include(app01_url)),

# app01-app01_url.py:

from . import views as av01
urlpatterns = [
    # 视图函数名称只有名称,无括号和参数
    path(r'fun03/', av01.fun03),
]

# 5. URL中的嵌套参数
# 捕获某个参数的一部分
# 例如URL /index/page-3, 需要捕获数字3作为参数

re_path(r'index_1/(page-(\d+)/)?$', sv.myindex_1), #不太好
re_path(r'index_2/(?:page-(?P\d+)/)?$', sv.myindex_2), #好

# 上述例子会得到两个参数,但 ?: 表明忽略此参数    
    
# 6. 传递额外参数
# 参数不仅仅来自以URL,还可能是我们自己定义的内容

url(r'extrem/$', sv.extremParam, {'name':"myparam"}),

# 附加参数同样适用于include语句,此时对include内所有都添加


# 7. URL的反向解析
# 防止硬编码
# 本质上是对每一个URL进行命名
# 以后再编码代码中使用URL的值,原则上都应该使用反向解析

# url.py:

urlpatterns = [
    url(r'^yourname/$', av01.revParse, name="askname"),
]

# app01-views.py:

# 需要导入reverse 
from django.core.urlresolvers import reverse
def revParse(r):
    return HttpResponse("Your requested URL is {0}".format(reverse("askname")))

#==============================views 视图==============================
# 1. 视图概述
# 视图即视图函数,接收web请求并返回web响应的事物处理函数.
# 响应指符合http协议要求的任何内容,包括json,string, html等
# 本章忽略事务处理,重点在如何返回处理结果上
# 2 其他简单视图
# django.http给我们提供类很多和HttpResponse类似的简单视图,

    #通过查看django.http代码我们知道,

# 此类视图使用方法基本类似,可以通过return语句昨晚直接反馈返回给浏览器
# Http404为Exception子类,所以需要raise使用       

# 3. HttpResponse详解
# 方法
    # init :使用页内容实例化HttpResponse对象
    # write(content):以文件的方式写
    # flush():以文件的方式输出缓存区
    # set_cookie(key, value='', max_age=None, expires=None):设置Cookie
       #  key,value都是字符串类型
       #  max_age是一个整数,表示在指定秒数后过期
       #  expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期,注意datetime和timedelta值只有在使用PickleSerializer时才可序列化
       #  max_age与expires二选一
       #  如果不指定过期时间,则两个星期后过期
    # delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生# 4. HttpResponseRedirect
   # 重定向,服务器端跳转
   # 构造函数的第一个参数用来指定重定向的地址
   # 案例 ShowViews/views.py

        ```python
           # 在 east/urls中添加一下内容
           url(r'^v10_1/', views.v10_1),
           url(r'^v10_2/', views.v10_2),
           url(r'^v11/', views.v11, name="v11"), 
        ```
        ```python
        # /east/ShowViews/views中添加一下内容
        def v10_1(request):
            return HttpResponseRedirect("/v11")

        def v10_2(request):
            return HttpResponseRedirect(reverse("v11"))

        def v11(request):
            return HttpResponse("哈哈,这是v11的访问返回呀")

        ```

# 5.Request对象
# Request介绍
    # 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象
    # 视图函数的第一个参数是HttpRequest对象
    # 在django.http模块中定义了HttpRequest对象的API
# 属性
    # 下面除非特别说明,属性都是只读的
    # path:一个字符串,表示请求的页面的完整路径,不包含域名
    # method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'
    # encoding:一个字符串,表示提交的数据的编码方式
        # 如果为None则表示使用浏览器的默认设置,一般为utf#8
        # 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
    # GET:一个类似于字典的对象,包含get请求方式的所有参数
    # POST:一个类似于字典的对象,包含post请求方式的所有参数
    # FILES:一个类似于字典的对象,包含所有的上传文件
    # COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串
    # session:一个既可读又可写的类似于字典的对象,表示当前的会话
        # 只有当Django 启用会话的支持时才可用,
        # 详细内容见“状态保持”
# 方法
    # is_ajax():如果请求是通过XMLHttpRequest发起的,则返回True
    
# QueryDict对象
    # 定义在django.http.QueryDict
    # request对象的属性GET、POST都是QueryDict类型的对象
    # 与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
    # 方法get():根据键获取值
        # 只能获取键的一个值
        # 如果一个键同时拥有多个值,获取最后一个值
    # 方法getlist():根据键获取值
        # 将键的值以列表返回,可以获取一个键的多个值
# GET属性
    # QueryDict类型的对象
    # 包含get请求方式的所有参数
    # 与url请求地址中的参数对应,位于?后面
    # 参数的格式是键值对,如key1=value1
    # 多个参数之间,使用&连接,如key1=value1&key2=value2
    # 键是开发人员定下来的,值是可变的

def v8_get(request):
    rst = ""
    for k,v in request.GET.items():
        rst += k + "-->" + v
        rst += ","

# POST属性
    # QueryDict类型的对象
    # 包含post请求方式的所有参数
    # 与form表单中的控件对应
    # 表单中空间必须有name属性,name为键,value为值
        # checkbox存在一键多值的问题
    # 键是开发人员定下来的,值是可变的
    # 案例:
        # settings中设置模板位置(已经设置完毕)

TEMPLATES = [
    {
        'DIRS': [os.path.join(BASE_DIR, "templates")],
    }


        # 设置get页面的urls和函数
            # urls.py

            # 需要在路由文件中添加两个路由
            path(r'v9_get/', views.v9_get),    # 填写页面
            path(r'v9_post/', views.v9_post), # 提交方法处理

             # app01/views.py

# 在文件中添加下面两个处理函数
def v9_get(request):
    #渲染一个模板
    return  render_to_response("for_post.html")

def v9_post(request):
    rst = ""
    for k,v in request.POST.items():
    rst += k + "-->" + v
    rst += ","
    return HttpResponse("Get value of POST is {0} ".format(rst))

        # 添加文件/templates/for_post.html
        # 由于安全原因,需要在设置中安全选项中删除csrf设置
          # 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',
            ]


        
# 手动编写视图    
    # 实验目的:
        # 利用django快捷函数手动编写视图处理函数
        # 编写过程中理解视图运行原理
    
    # 分析:
        # django把所有请求信息封装入request
        # django通过urls模块把相应请求跟事件处理函数链接起来,并把request昨晚参数传入
        # 在相应的处理函数中,我们需要完成两部分
            # 处理业务
            # 把结果封装并返回,我们可以使用简单HttpResponse,同样也可以自己处理此功能
        # 本案例不介绍业务处理,把目光集中在如何渲染结果并返回
        
    # render(request, template_name[, context][, context_instance][, content_type][, status][, current_app][, dirs][, using])
        # 使用模板和一个给定的上下文环境,返回一个渲染和的HttpResponse对象
        # request: django的传入请求
        # template_name: 模板名称
        # content_instance: 上下文环境
                #例:
                #template/names.html代码片段:


Your name is {{name}}

        # 案例代码1,app01/views:

def render2_test(request):
  #  环境变量
  c = dict()
  c["name"] = "Zhou"
  c["name2"] = "Wu"
  c["name3"] = "Zheng"
  rsp = render(request, "names.html", context=c )
  # rsp = render(request, "render.html") #不传参数直接返回
  return rsp

        # 案例代码2,app01/views:

def render3_test(request):
    from django.template import loader
    # 得到模板
    t = loader.get_template("names.html")
    print(type(t))    # Template类型
    r = t.render({"name": "Zhou"})
    print(type(r))    # SafeText类型
    return HttpResponse(r)

        # render_to_response
        # 根据给定的上下文字典渲染给定模板,返回渲染后的HttpResponse
        
        # 案例代码3,app01/views

def render4_test(request):
    # 反馈回模板render2.html
    rsp = render_to_response("names.html", context={"name": "Zhou"})
    return rsp

# 系统内建视图
    # 系统内建视图,可以直接实用
    # 404
        # default.page_not_found(request, template_name='404.html')
        # 系统引发Http404时出发
        # 默认船体request_path变量给模板,即导致错误的URL
        # DEBUG=True则不会调用404, 取而代之是调试信息
        # 404视图会被传递一个RequestContext对象并且可以访问模板上下文处理器提供的变量(MEDIA_URL等)
    # 500(server error)
        #  defaults.server_error(request, template_name='500.html')
        # 需要DEBUG=False,否则不调用
    # 403 (HTTP Forbidden) 视图
        # defaults.permission_denied(request, template_name='403.html')
        # 通过PermissionDenied触发
    # 400 (bad request) 视图
        # defaults.bad_request(request, template_name='400.html')
        # DEBUG=False
        
    #例:

def get404(request):
    from django.views import defaults
    return defaults.page_not_found(request, template_name="defined.html")

# 8. 基于类的视图
# 和基于函数的视图的优势和区别:
    # HTTP方法的methode可以有各自的方法,不需要使用条件分支来解决
    # 可以使用OOP技术(例如Mixin)
# 概述
    # 核心是允许使用不同的实例方法来相应不同的HTTP请求方法,而避开条件分支实现
    # as_view函数作为类的可调用入库,该方法创建一个实例并调用dispatch方法,按照请求方法对请求进行分发,如果该方法没有定义,则引发HttpResponseNotAllowed
# 类属性使用
    # 在类定义时直接覆盖
    # 在调用as_view的时候直接作为参数使用,例如:

        urlpatterns = [
            url(r'^about/', GreetingView.as_view(greeting="Greetxxx")),
            ]

# 对基于类的视图的扩充大致有三种方法: Mixin, 装饰as_view, 装饰dispatch
# 使用Mixin
    # 多继承的一种形式,来自弗雷的行为和属性组合在一起
    # 解决多继承问题
    # View的子类只能单继承,多继承会导致不可期问题
    # 多继承带来的问题:
        # 结构复杂
        # 优先顺序模糊
        # 功能冲突
    # 解决方法
        # 规格继承 # java interface
        # 实现继承 # python,ruby
# 在URLconf中装饰

    from django.contrib.auth.decorators import login_required, permission_required
    from django.views.generic import TemplateView

    from .views import VoteView

    urlpatterns = [
        url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
        url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
    ]

# 装饰类
    # 类的方法和独立方法不同,不能直接运用装饰器,需要用methode_decorator进行装饰

        from django.contrib.auth.decorators import login_required
        from django.utils.decorators import method_decorator
        from django.views.generic import TemplateView

        class ProtectedView(TemplateView):
            template_name = 'secret.html'

            @method_decorator(login_required)
            def dispatch(self, *args, **kwargs):
                return super(ProtectedView, self).dispatch(*args, **kwargs)

#=============================Models 模型=============================
# ORM
    # ObjectRelationMap : 把面向对象思想转换成关系数据库思想.操作上把类等价于表格
    # 类对应表格
    # 类中的属性对应表中的字段
    # 在应用中的models.py文件中定义class
    # 所有需要使用ORM的class都必须是 models.Model 的子类
    # class中的所有属性对应表格中的字段
    # 字段的类型都必须使用 models.xxx 不能使用python中的类型
    # 在django种,Models负责跟数据库交互
    
# django链接数据库
    # 自带默认数据库Sqllite3
        # 关系型数据库
        # 轻量级
    # 建议开发用sqlite3, 部署用mysql之类数据库
        # 切换数据库在settings中进行设置 
        # django 连接 mysql需要在项目文件下的__init__文件中导入pymysql包

# 在主项目的__init__文件中
import pymysql
pymysql.install_as_MySQLdb()

# models类的使用
# 定义和数据库表映射的类
    # 在应用中的models.py文件中定义class
    # 所有需要使用ORM的class都必须是 models.Model 的子类
    # class中的所有属性对应表格中的字段
    # 字段的类型都必须使用 modles.xxx 不能使用python中的类型
# 字段常用参数
    1. max_length : 规定数值的最大长度
    2. blank : 是否允许字段为空,默认不允许
    3. null : 在DB中控制是否保存为null, 默认为false
    4. default : 默认值
    5. unique : 唯一
    6. verbose_name : 假名
# 例:app01/models.py

from django.db import models

class Teacher(models.Model):
    name = models.CharField(max_length=12)
    age = models.IntegerField()
    address = models.CharField(max_length=50)
    course = models.CharField(max_length=20)

# 数据库的迁移
    1. 在命令行中,生成数据迁移的语句(生成sql语句)

python manage.py makemigrations

    2. 在命令行中,输入数据迁移的指令

python manage.py migrate

            ps : 如果迁移中出现没有变化或者报错,可以尝试强制迁移

# 强制迁移命令
python manage.py makemigrations app01 #(应用名)
python manage.py migrate app01 #(应用名)

    3. 对于默认数据库, 为了避免出现混乱,如果数据库中没有数据,每次迁移前可以把系统
    自带的sqlite3数据库删除
        
# #### 1. 查看数据库中的数据

```
1. 启动命令行 : python manage.py shell
ps: 注意点: 对orm的操作分为静态函数和非静态函数两种.静态是指在内存中只有一份内容存在,调用的时候使用 类名. 的方式.如果修改了那么所有使用的人都会受影响.
2. 在命令行中导入对应的映射类
    from 应用.models import 类名
3. 使用 objects 属性操作数据库. objects 是 模型中实际和数据库进行交互的 Manager 类的实例化对象.
4. 查询命令
    # 类名.objects.all() 查询数据库表中的所有内容. 返回的结果是一个QuerySet类型,实际上是类列表中装这个一个一个数据对象.
    # 类名.objects.filter(条件) 

```
# from 应用名.models import 类名
from myapp.models import Student

# 查询Student表中的所有数据,得到的是一个QuerySet类型
Student.objects.all()

# 如果要取出所有QuerySet类型中的所有数据对象,需要遍历取出所有的对象,再用对象.属性来查看值
s = Student.object.all()
for each in s:
    print(each.name , each.age , each.address , each.phone)

# 如果要进行过滤筛选,使用filter()方法
Student.objects.filter(age=18)

#### 2. 添加数据
对象 = 类()   # 使用类实例化对象
对象.属性 = 值  # 给对应的对象的属性赋值
对象.save()  # 必须要执行保存操作,否则数据没有进入数据库
python3 manage.py shell 命令行中添加数据

# from 应用名.models import 类名
from myapp.models import Student

# 实例化对象
s = Student()

# 给对象的属性赋值
s.name = '张三'
s.address = '云南昭通'
s.phone = '13377886678'
s.age = 20

# 保存数据
s.save()

# 常见查找方法

1. 通用查找格式: 属性名__XX (用下面的内容) = 值

# gt : 大于
# gte : 大于等于
# lt : 小于
# lte : 小于等于
# range: 范围
# year : 年份
# isnull : 是否为空

2. 查找等于指定值的格式: 属性名 = 值
3. 模糊查找:  属性名__XX (使用下面的内容) = 值

* exact : 精确等于
* iexact: 不区分大小写
* contains: 包含
* startwith: 以...开头
* endwith: 已...结尾 

#=============================DB数据库表关系=============================
# 多表联查:利用多个表联合查找某一项信息或者多项信息
# 1:1 OneToOne
    # 建立关系:在模型任意一边即可,使用OneToOneField
    # app01/models:

class School(models.Model):
  school_id = models.IntegerField()
    school_name = models.CharField(max_length=20)
    # my_manager = models.OneToOneField(Manage) #只需要加一边
  def __str__(self):
        return self.school_name
    
class Manager(models.Model):
  m_id = models.IntegerField()
  m_name = models.CharField(max_length=20)
  my_school = models.OneToOneField(School)
  def __str__(self):
    return self.m_name

    # add:  

        # 添加没有关系的一边,直接实例化保存就可以
            >>> s = School()
            >>> s.school_id = 2
            >>> s.school_name = "Mars'school"
            >>> s.save()
            
        # 添加有关系的一边,使用create方法,或者使用实例化然后save
            # 方法1
            >>> m = Manager()
            >>> m.manager_id = 10
            >>> m.manager_name = "Mars"
            >>> m.my_school = s
            >>> m.save()

            # 方法2,不需要save()

>>> m = Manager.objects.create(manager_id=20, manager_name="Mars2", my_school=s[0])

    # query:
       

# 由子表查母表: 由子表的属性直接提取信息
>>> m.my_school
# 由母表查子表:使用双下划线 
>>> s = School.objects.get(manager__manager_name="Mars")
>>> s

    # change:
        # 单个修改使用save     
        # 批量修改使用update
        # 无论对子表还是对母表的修改
    # delete: 直接使用delete删除                   
    
# 1:N OneToMany
    # 一个表格的一个数据项/对象等,可以有很多个另一个表格的数据项
    # 比如:一个学校可以有很多个老师,但一个老师只能在一个学校里上班
    # 使用上
        # 使用ForeignKey()
        # 外键在多的那一边进行定义

    class Teacher(models.Model):
    teacher_name = models.CharField(max_length=20)
    # 注意写法
    schools = models.ForeignKey("School")

    # Add:
        # 跟一对一方法类似,通过create和new来添加
        # create: 把属性都填满,然后不需要手动保存
        # new: 可以属性或者参数为空,必须用save保存
    # Query: 
        # 以学校和老师的例子为准
        # 如果知道老师,查学校  ,则通过增加的关系属性,直接使用 
    t1.schools
        # 从school反向查找

# 有学校,我想查下这个学校所有老师,则系统自动在老师模型名称的小写下直接加下划线set,
s1.teacher_set.all()
        
Teacher.objects.filter(schools=s1)
Teacher.objects.filter(schools__school_id=0)

    #change: update
    #delete: 对象和queryset都可以用delete
    
# N:N ManyToMany
    # 表示任意一个表的数据可以拥有对方表格多项数据,反之亦然
    # 比如典型例子就是老师和学生的关系
    # 使用上,在任意一方,使用ManyToMany定义,只需要定义一边

 class Student(models.Model):
        student_name = models.CharField(max_length=20)
        teachers = models.ManyToManyField("Teacher")

    # Add:
        # .add()
        1: # 如果是已有用户,用get

st1 = Student.objects.create(student_name="stu1")
stu.teachers.add(*ts)

        2:

stu = ....
t = Teacher.objects.create(xxxxx)
t.student_set.add(stu)

    # Query:
        # 跟一对多类似,使用_set查询
        #也可以使用双下划线
    # delete:
        #delete删除内容
        #remove,clear删除关系

#=============================template模板系统=============================
# 模板:一组相同或者相似的页面,在需要个性化的地方进行留白,需要的时候只是用数据填充就可以使用
# 步骤:
    1. 在settings中进行设置:TEMPLATES
    2. 在tmepltes文件夹下编写模并调用
    
## 模板-变量
# 变量的表示方法: {{var_name}}
# 在系统调用模板的时候,会用相应的数据查找相应的变量名称,如果能找到,则填充,或者叫渲染,否则,跳过

## 模板-标签

# for标签: {% for .. in .. %}
# 用法:
        {% for .. in .. %}
            循环语句
        {% endfor %}

## if标签
# 用来判断条件
# 代码示例:
        {% if 条件 %}
            条件成立执行语句
        {% elif 条件 %}}
            条件成立执行语句
        {% else %}
            以上条件都不成立执行语句
        {% endif %}}
        
## csrf标签
# csrf:跨站请求伪造
#  在提交表单的时候,表单form页面需要加上 
{% csrf_token %},
# 实际是由于setting的MIDDLEWARE设置了django.middleware.common.CommonMiddleware中间件作用


#=============================session=============================
# 为了应对HTTP协议的无状态性
# 用来保存用户比较敏感的信息
# 属于request的一个属性
# 常用操作:
    # request.session.get(key, defaultValue)
    # request.session.clear():清除全部
    # request.session[key] = value :赋值
    # request.session.flush(): 删除当前回话且清除回话的cookie
    # del request.session[key]

def mySess(request):
    print(type(request.session))
    print(request.session)
    # 如果session中没有teacher_name的值,则返回NoName
    print(request.session.get("teacher_name", "NoName"))

    # 清除session所有的值
    request.session.clear()
    print("In mySess")
    return None

#=============================分页=============================

# django提供现成的分页器用来对结果进行分页
from django.core.paginator import Paginator
def student(request):
    #请求所有学生的详情列表
    # 大约有10000名学生
    stus = Student.objects.all()
    # 两个参数
    # 1. 数据来源,也即从数据库中查询出的结果
    # 2. 单页返回数据量
    p = Paginator(stus, 40)
    # 对Paginator进行设置或者对变量属性使用
    print(p.count) # p里面有多少数据
    print(p.num_pages) # 页面总数
    print(p.page_range) # 页码列表,从1开始

    # 取得第三页的内容
    # 如果页码不存在,报异常InvalidPage
    p.page(3)
    return  stus

#=============================Ajax=============================

#=============================基于类的试图=============================
# 可以针对http协议不同的方法创建不同的函数
# 可以使用Mixin等oop技术
# Mixin
    # 把来自父类的行为或者属性组合在一起
    # 解决多重继承问题
# ListView
# app01/models:

from django.views.generic import ListView
class  StudentListView(ListView):
    '''
    需要设置两个主要内容
    1. queryset:数据来集合
    2. template_name:模板名称
    '''
    queryset = Student.objects.all().filter(gender="nan")
    template_name = "student_list.html"

# urls:

path(r'stulist/', v.StudentListView.as_view)

#=============================admin=============================
## 1. 创建Admin

# settings中填入app`

INSTALLED_APPS = [
    'django.contrib.admin',
    ]

# 打开urls.py

from django.contrib import admin
from django.urls import path
urlpatterns = [
    path('admin/', admin.site.urls),
    ]

# shell下创建超级用户

python manage.py createsuperuser

# 配置settings文件

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

## 2. 绑定管理模型

from django.contrib import admin
from aadmin.models import Student, ClassRoom, Teacher
admin.site.register(Student)
admin.site.register(ClassRoom)
admin.site.register(Teacher)

## 3. 设置admin管理类

# admin.py:

admin.site.site_header = "站头"
admin.site.site_title = "站标题"
admin.site.index_title = "首页标"

# 实现方式
    # 1、ModelAdmin
class ClassRoomAdmin(admin.ModelAdmin):
    pass
class StudentAdmin(admin.ModelAdmin):
    pass
admin.site.register(Student, StudentAdmin)
admin.site.register(ClassRoom, ClassRoomAdmin)

    # 2、装饰器
@admin.register(Teacher)
class TeacherAdmin(admin.ModelAdmin):
      list_per_page = 2 # 修改页面显示数量:list_per_page
      actions_on_bottom = True # 操作选项: actions_on_top/button 
      actions_on_top = False
      list_display = ["name", "room", "curTime", "getRoomName"] # 控制列表中显示的内容
      search_fields = ["name"] # 搜索框

    # 显示字段
    # field = ["name", "room"]
    
    # 分组显示
    fieldsets = (
        ("基本信息", {"fields":["name",]}),
        ("其他信息", {"fields":["room","course"]}),
    )

# models.py:

class Teacher(models.Model):
  name = models.CharField(max_length=5)
  course = models.CharField(max_length=20)
  room = models.OneToOneField(ClassRoom)

  # # 将方法作为列显示。关联对象,函数必须返回值
  def getRoomName(self):
      return self.room.roomName
    # 设置short_descraption作为描述
  getRoomName.short_description = "教室"
  # 排序使用admin_order_field
  getRoomName.admin_order_field = "name"

  def __str__(self):
      return self.name


 

你可能感兴趣的:(python学习)