web开发框架之Django基础

 

在脚本中如何进行Django的运行
if __name__ == '__main__':
    import os
    import django
    # 注意路径(当前所在的位置,要加载Django的配置文件)
    os.environ.setdefault("DJANGO_SETTINGS_MODULE","orm69.settings")
    django.setup()
    
    # 进行的操做



一.搭建环境
    设置pip install 的源
    建立虚拟环境    
        mkvirtualenv py6_django -p python3
    查看当前目录下的虚拟环境
        workon 
    设置Django的版本
        pip install django==1.11.11
    
    # 虚拟环境的指令
    mkvirtualenv  # 建立虚拟环境
    rmvirtualenv  # 删除虚拟环境
    workon        # 进入虚拟环境、查看全部虚拟环境
    deactivate    # 退出虚拟环境    
    ctrl + h       查看隐藏文件
    
    # pip
    pip install  # 安装依赖包
    pip uninstall  # 卸载依赖包
    pip list  # 查看已安装的依赖包
    pip freeze  # 冻结当前环境的依赖包
    
    
    workon + py6_django  进入当前的虚拟环境
    切换到桌面下的code中,将建立的项目放到里面
        cd ~/Desktop/code
        django-admin startproject demo
    查看树状图
        执行 tree,结果显示以下的目录结构
            与项目同名的目录,此处为demo
            settings.py 是项目的总体配置文件
            urls.py 是项目的URL配置文件
            wsgi.py 是项目与WSGI兼容的Web服务器入口
            manage.py 是项目管理文件,经过它管理项目
        
    运行开发服务器    
        python manage.py runserver
        
    建立子应用(相似于蓝图)
        python manage.py startapp testdatabase
            执行 tree,结果显示以下的目录结构
                admin.py 文件跟网站的后台管理站点配置相关
                apps.py 文件用于配置当前子应用的相关信息
                migrations 目录用于存放数据库迁移历史文件
                models.py 文件用户保存数据库模型类
                tests.py 文件用于开发测试用例,编写单元测试
                views.py 文件用于编写Web应用视图
        
        建立完子应用时须要进行三个步骤:
            第一步:设置路由
                在工程配置文件settings.py中,INSTALLED_APPS项保存了工程中已经注册安装的子应用,
                将刚建立的users子应用添加到工程中,可在INSTALLED_APPS列表中添加
                'testdatabase.apps.TestdatabaseConfig'
                
            第二步:在views中写视图函数
                from django.http import HttpResponse
                # 写视图函数时须要注意必需要传request参数和返回一个HttpResponse的响应
                def index(request):
                    """
                    index视图
                    :param request: 包含了请求信息的请求对象
                    :return: 响应对象
                    """
                    return HttpResponse("hello world!")
                    
            第三步:在子应用中建立urls.py,保存子应用中的地址
                    在users/urls.py文件中定义路由信息
                    
                        from django.conf.urls import url
                        from . import views

                        # urlpatterns是被django自动识别的路由列表变量
                        urlpatterns = [
                            # 每一个路由信息都须要使用url函数来构造
                            # url(路径, 视图)
                            # ^ / $ 需注意在子应用的urls.py中必定要有,
                            url(r'^index/$', views.index),
                        ]
                        
                        在该项目的(demo)urls.py中
                            from django.conf.urls import url, include
                            from django.contrib import admin

                            urlpatterns = [
                                url(r'^admin/', admin.site.urls),  # django默认包含的

                                # 添加
                                # ^ / 需注意在子应用的urls.py中必定要有
                                url(r'^testdatabase/', include('testdatabase.urls')), 
                            ]
                            
    从新启动django程序
        python manage.py runserver
        
    配置文件
        BASE_DIR
        DEBUG
        将语言和时区修改成中国大陆信息
        LANGUAGE_CODE = 'zh-hans'
        TIME_ZONE = 'Asia/Shanghai'
静态文件 在项目根目录下建立static_files目录来保存静态文件。 在demo/settings.py中修改静态文件的两个参数为 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static_files'), ] 此时在static_files添加的任何静态文件均可以使用网址 /static/文件在static_files中的路径来访问了 用127.0.0.1:8000/static/index.html来访问 注意:    Django 仅在调试模式下(DEBUG=True)能对外提供静态文件,当DEBUG=False工做在生产模式时,Django再也不对外提供静态文件,
     须要是用collectstatic命令来收集静态文件并交由其余静态文件服务器来提供 路由说明 路由定义位置 路由解析顺序 从上至下 注意:须要注意定义路由的顺序,避免出现屏蔽效应。
路由命名与reverse反解析(逆向) 路由信息 在定义路由的时候,能够为路由命名,方便查找特定视图的具体路径信息。 1) 在使用include函数定义路由时,可使用namespace参数定义路由的命名空间,如 url(r'^users/', include('users.urls', namespace='users')), 命名空间表示,凡是users.urls中定义的路由,均属于namespace指明的users名下。 命名空间的做用:避免不一样应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。 2) 在定义普通路由时,可使用name参数指明路由的名字,如 urlpatterns = [ url(r'^index/$', views.index, name='index'), url(r'^say', views.say, name='say'), ] reverse反解析   使用reverse函数,能够根据路由名称,返回具体的路径,如:   from django.core.urlresolvers import reverse # 注意导包路径   def index(request):   return HttpResponse("hello the world!")   def say(request):   url = reverse('users:index') # 返回 /users/index/   print(url)   return HttpResponse('say') 对于未指明namespace的,reverse(路由name) 对于指明namespace的,reverse(命名空间namespace:路由name) 路径结尾斜线的说明 Django中定义路由时,一般以斜线/结尾,其好处是用户访问不以斜线/结尾的相同路径时, Django会把用户重定向到以斜线/结尾的路径上,而不会返回404不存在。如 urlpatterns = [ url(r'^index/$', views.index, name='index'), ] 用户访问 index 或者 index/ 网址,均能访问到index视图。 说明: 虽然路由结尾带/能带来上述好处,可是却违背了HTTP中URL表示资源位置路径的设计理念。是否结尾带/以所属公司定义风格为准。 请求和响应 请求 利用HTTP协议向服务器传参有几种途径? 提取URL的特定部分,如/weather/beijing/2018,能够在服务器端的路由中用正则表达式截取 查询字符串(query string),形如key1=value1&key2=value2; 请求体(body)中发送的数据,好比表单数据、json、xml; 在http报文的头(header)中    具体以下:   request   传递数据的方式    a、以查询字符串的方式将参数放到了url中    http://127.0.0.1:8000/login?username=zhangsan&pwd=12345   b、将数据放到了请求体中    http://127.0.0.1:8000/login   c、路径参数:将数据放到了路径中    http://127.0.0.1:8000/login/zhangsan/123456   d、请求头:将数据放到了请求头中 URL路径参数 未命名参数传递 url(r'^weather/([a-z]+)/(\d{4})/$', views.weather), def weather(request, city, year): print('city=%s' % city) print('year=%s' % year) return HttpResponse('OK') 命名参数按名字的传递 url(r'^weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.weather), def weather(request, year, city): print('city=%s' % city) print('year=%s' % year) return HttpResponse('OK...')
Django中的QueryDict对象 定义在django.http.QueryDict HttpRequest对象的属性GET、POST都是QueryDict类型的对象与python字典不一样,QueryDict类型的对象用来处理同一个键带有多个值的状况
         方法get():根据键获取值 若是一个键同时拥有多个值将获取最后一个值,若是键不存在则返回None值,能够设置默认值进行后续处理 dict.get('键',默认值) 可简写为 dict['键'] 方法getlist():根据键获取值,值以列表返回,能够获取指定键的全部值,若是键不存在则返回空列表[],能够设置默认值进行后续处理 dict.getlist('键',默认值)
查询字符串Query String 获取请求路径中的查询字符串参数(形如?k1=v1&k2=v2),能够经过request.GET属性获取, 返回QueryDict对象 # /qs/?a=1&b=2&a=3 def qs(request): a = request.GET.get('a') b = request.GET.get('b') alist = request.GET.getlist('a') print(a) # 3 print(b) # 2 print(alist) # ['1', '3'] return HttpResponse('OK') 重要:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然能够经过request.GET获取请求中的查询字符串数据。 请求体 表单类型 Form Data 前端发送的表单类型的请求体数据,能够经过request.POST属性获取,返回QueryDict对象 def get_body(request): a = request.POST.get('a') b = request.POST.get('b') alist = request.POST.getlist('a') print(a) print(b) print(alist) return HttpResponse('OK') 非表单类型 Non-Form Data 非表单类型的请求体数据,Django没法自动解析,能够经过request.body属性获取最原始的请求体数据,本身按照请求体
        格式(JSON、XML等)进行解析。request.body返回bytes类型。 例如要获取请求体中的以下JSON数据 {"a": 1, "b": 2}
能够进行以下方法操做: import json def get_body_json(request): json_bytes = request.body json_str = json_bytes.decode() json_data = json.loads(json_str) print(json_data['a']) print(json_data['b']) return HttpResponse('OK') 请求头 经过request.META属性获取请求头headers中的数据,request.META为字典类型 常见的请求头如: CONTENT_LENGTH – The length of the request body (as a string). CONTENT_TYPE – The MIME type of the request body. HTTP_ACCEPT – Acceptable content types for the response. HTTP_ACCEPT_ENCODING – Acceptable encodings for the response. HTTP_ACCEPT_LANGUAGE – Acceptable languages for the response. HTTP_HOST – The HTTP Host header sent by the client. HTTP_REFERER – The referring page, if any. HTTP_USER_AGENT – The client’s user-agent string. QUERY_STRING – The query string, as a single (unparsed) string. REMOTE_ADDR – The IP address of the client. REMOTE_HOST – The hostname of the client. REMOTE_USER – The user authenticated by the Web server, if any. REQUEST_METHOD – A string such as "GET" or "POST". SERVER_NAME – The hostname of the server. SERVER_PORT – The port of the server (as a string). 具体使用如: def get_headers(request): print(request.META['CONTENT_TYPE']) return HttpResponse('OK') 其余经常使用HttpRequest对象属性 method:一个字符串,表示请求使用的HTTP方法,经常使用值包括:'GET'、'POST' user:请求的用户对象 path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分 encoding:一个字符串,表示提交的数据的编码方式,若是为None则表示使用浏览器的默认设置,通常为utf-8这个属性是可写的,能够经过修改它来
                修改访问表单数据使用的编码, 接下来对属性的任何访问将使用新的encoding值 FILES:一个相似于字典的对象,包含全部的上传文件 响应 HttpResponse 可使用django.http.HttpResponse来构造响应对象。 HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)也可经过HttpResponse对象属性来设置响应体、
            响应体数据类型、状态码:     content:表示返回的内容。     status_code:返回的HTTP响应状态码。     content_type:指定返回数据的的MIME类型。 响应头能够直接将HttpResponse对象当作字典进行响应头键值对的设置: response = HttpResponse() response['Itcast'] = 'Python' # 自定义响应头Itcast, 值为Python 示例: from django.http import HttpResponse def demo_view(request): return HttpResponse('itcast python', status=400) 或者 response = HttpResponse('itcast python') response.status_code = 400 response['Itcast'] = 'Python' return response HttpResponse子类 Django提供了一系列HttpResponse的子类,能够快速设置状态码 HttpResponseRedirect 301 HttpResponsePermanentRedirect 302 HttpResponseNotModified 304 HttpResponseBadRequest 400 HttpResponseNotFound 404 HttpResponseForbidden 403 HttpResponseNotAllowed 405 HttpResponseGone 410 HttpResponseServerError 500 JsonResponse 若要返回json数据,可使用JsonResponse来构造响应对象,做用:   1)帮助咱们将数据转换为json字符串   2)设置响应头Content-Type为 application/json from django.http import JsonResponse def demo_view(request): return JsonResponse({'city': 'beijing', 'subject': 'python'}) redirect重定向 from django.shortcuts import redirect def demo_view(request): return redirect('/index.html') Cookie Cookie的特色 Cookie以键值对的格式进行信息的存储。 Cookie基于域名安全,不一样域名的Cookie是不能互相访问的,如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,
          没法访问到itcast.cn写的Cookie信息。当浏览器请求某网站时,会将浏览器存储的跟网站相关的全部Cookie信息提交给网站服务器。 设置Cookie 能够经过HttpResponse对象中的set_cookie方法来设置cookie。 HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期) max_age 单位为秒,默认为None。若是是临时cookie,可将max_age设置为None。 代码以下: def demo_view(request): response = HttpResponse('ok') response.set_cookie('itcast1', 'python1') # 临时cookie response.set_cookie('itcast2', 'python2', max_age=3600) # 有效期一小时 return response 读取Cookie 能够经过HttpRequest对象的COOKIES属性来读取本次请求携带的cookie值。 request.COOKIES为字典类型。 代码以下: def demo_view(request): cookie1 = request.COOKIES.get('itcast1') print(cookie1) return HttpResponse('OK') Session 启用Session(Django默认启用) 存储方式 在settings.py文件中,能够设置session数据的存储方式,能够保存在数据库、本地缓存等 本地缓存 存储在本机内存中,若是丢失则不能找回,比数据库的方式读写更快。 SESSION_ENGINE='django.contrib.sessions.backends.cache' 混合存储 优先从本机内存中存取,若是没有则从数据库中存取。 SESSION_ENGINE='django.contrib.sessions.backends.cached_db' Redis 在redis中保存session,须要引入第三方扩展,咱们可使用django-redis来解决 安装扩展 pip install django-redis 配置 在settings.py文件中作以下设置 "default" 只要两次设置的名字同样就能够啦 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default" 若是redis的ip地址不是本地回环127.0.0.1,而是其余地址,访问Django时,可能出现Redis链接错误 解决方法: 修改redis的配置文件,添加特定ip地址。 打开redis的配置文件 sudo vim /etc/redis/redis.conf 进行修改 在以下配置项进行修改(如要添加10.211.55.5地址) bind 127.0.0.1 10.211.55.5 从新启动redis服务 sudo service redis-server restart Seesion操做 经过HttpRequest对象的session属性进行会话的读写操做。 以键值对的格式写session。 request.session['键']=值 根据键读取值。 request.session.get('键',默认值) 清除全部session,在存储中删除值部分。 request.session.clear() 清除session数据,在存储中删除session的整条数据。 request.session.flush() 删除session中的指定键及值,在存储中只删除某个键及对应的值。 del request.session['键'] 设置session的有效期 request.session.set_expiry(value) 若是value是一个整数,session将在value秒没有活动后过时。 若是value为0,那么用户session的Cookie将在用户的浏览器关闭时过时。 若是value为None,那么session有效期将采用系统默认值,默认为两周, 能够经过在settings.py中设置SESSION_COOKIE_AGE来设置全局默认值。 类视图 类视图的好处: 1)代码可读性好 2)类视图相对于函数视图有更高的复用性,若是其余地方须要用到某个类视图的某个特定逻辑,直接继承该类视图便可 代码以下: 在上面的子应用中 from django.views import View def wrapper(func): def inner(*args,**kwargs): print("获取页面数据1") ret = func(*args,**kwargs) print("获取页面数据2") return ret return inner class RegisterView(View): @wrapper def get(self,*args,**kwargs): print("test get page") return HttpResponse("get page") def post(self,*args,**kwargs): print("test post page") return HttpResponse("post page") urlpatterns = [ url(r"^register/$", views.RegisterView.as_view()), ] 中间件 中间件的定义方法 在testdatabase应用中新建一个middleware.py文件, def my_middleware(get_response): print('init 被调用') def middleware(request): print('before request 被调用') response = get_response(request) print('after response 被调用') return response return middleware 定义好中间件后,须要在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', 'testdatabase.middleware.my_middleware', # 添加中间件 ] 定义一个视图进行测试 def demo_view(request): print('view 视图被调用') return HttpResponse('OK') 多个中间件的执行顺序 在请求视图被处理前,中间件由上至下依次执行 在请求视图被处理后,中间件由下至上依次执行 代码以下: 定义两个中间件 def my_middleware(get_response): print('init 被调用') def middleware1(request): print('before request 被调用') response = get_response(request) print('after response 被调用') return response return middleware def my_middleware2(get_response): print('init2 被调用') def middleware(request): print('before request 2 被调用') response = get_response(request) print('after response 2 被调用') return response return middleware 注册添加两个中间件 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', 'testdatabase.middleware.my_middleware1', # 添加中间件 'testdatabase.middleware.my_middleware2', # 添加中间件 ] 执行结果为: init2 被调用 init 被调用 before request 被调用 before request 2 被调用 view 视图被调用 after response 2 被调用 after response 被调用 数据库 ORM的关系 一对多 ForeignKey 在多的一方设置外键 多对多 ManyToMany 通常设置在处理业务逻辑比较多的一方 配置 在settings.py中保存了数据库的链接配置信息,Django默认初始配置使用sqlite数据库。 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } 使用mysql数据库 pip install PyMySQL 在Django的工程同名子目录的__init__.py文件中添加以下语句 # 将PyMySQL装饰成MySQLdb,方便Django识别 from pymysql import install_as_MySQLdb install_as_MySQLdb() 修改DATABASES配置信息 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 数据库主机 'PORT': 3306, # 数据库端口 'USER': 'root', # 数据库用户名 'PASSWORD': 'mysql', # 数据库用户密码 'NAME': 'py6_django' # 数据库名字 } } 在MySQL中建立数据库 create database py6_django default charset=utf8; 进行数据库的迁移操做 迁移文件的生成 python manage.py makemigrations 同步到数据库中 python manage.py migrate 若是不成功使用强制迁移 强制迁移 python manage.py migrate testdatabase --fake 查看MySQL数据库日志 ...... tail -f /var/log/mysql/mysql.log # 能够实时查看数据库的日志内容 利用ORM建立表并手动增长数据 # 添加数据 book = BookInfo( btitle='西游记', bpub_date=date(1988, 1, 1), bread=10, bcomment=10) book.save() hero = HeroInfo( hname="孙悟空", hgender=0, hcomment="七十二变", hbook=book, is_delete=0, ) hero.save() hero = HeroInfo( hname="猪八戒", hgender=0, hbook_id=book.id, is_delete=0, ) hero.save() HeroInfo.objects.create( hname='沙悟净', hgender=0, hbook=book )

# 基本查询
print(BookInfo.objects.all())
print(BookInfo.objects.get(btitle='雪山飞狐').id)
print(BookInfo.objects.get(id=3))
print(BookInfo.objects.get(pk=3))
# 将ID=3的排除,显示其余的
print(BookInfo.objects.exclude(id=3))
print(111111111)
try:
  print(BookInfo.objects.get(id=12))
# except Exception as e:html

# 使用get获取数据时,若是没有回抛出异常前端

except BookInfo.DoesNotExist:
  print("未找到对应的ID")
print(BookInfo.objects.count())
# 关于values的查询
print("values".center(80,"*"))
print(BookInfo.objects.values("btitle","bpub_date"))
print("values_list".center(80,"#"))
print(BookInfo.objects.values_list("btitle","bpub_date"))
# 关于reverse的翻转
print("reverse".center(80,"*"))
print(BookInfo.objects.all().reverse())
# 获取最后一个数据
print("last".center(80,"#"))
print(BookInfo.objects.all().last())
# 获取第一个数据
print("first".center(80,"*"))
print(BookInfo.objects.all().first())
# 判断数据库中是否有数据
print(BookInfo.objects.exists())
# 过滤查询
# 表示判等
print(BookInfo.objects.filter(id__exact=1))
print(BookInfo.objects.filter(id=1)[0])
# 是否包含 contains
# 忽略大小写 icontains
print(BookInfo.objects.filter(btitle__contains="西"))
#至关于between and 左右闭区间 1 <= ret <=5
print(BookInfo.objects.filter(id__range(1,5)))
print(BookInfo.objects.filter(btitle__startswith="雪"))
print(BookInfo.objects.filter(btitle__endswith="传"))
# 时间和日期的查询
print(BookInfo.objects.filter(bpub_date__year=1986))
print(BookInfo.objects.filter(bpub_date__gt=date(1986,1,1)))
# 空查询
# 查询书名不为空的
print(BookInfo.objects.filter(btitle__isnull=False))
# 查询书名为空的
print(BookInfo.objects.filter(btitle__isnull=True))
# 范围查询
print(BookInfo.objects.filter(id__in=[1,2,3,5,7]))
# 比较查询
print(BookInfo.objects.filter(id__gt=3))
print(BookInfo.objects.filter(id__gte=3))
print(BookInfo.objects.filter(id__lt=3))
print(BookInfo.objects.filter(id__lte=3))

# F对象(两个字段做比较) -->横向比较,能够进行F(("bcomment")+1)*4操做
# 查询阅读量大于评论量的读书
print(BookInfo.objects.filter(bread__gt=10)) # 阅读量大于10
print(BookInfo.objects.filter(bread__gt=F("bcomment")))
# 查询阅读量大于2倍评论量的读书
print(BookInfo.objects.filter(bread__gt=F("bcomment")*2))
# 给每本书加版本
print(BookInfo.objects.update(btitle=Concat(F("btitle"),Value("(初版)"))))
# Q对象 -->多个条件的 & | ~
# 查询阅读量大于20而且编号小于3
print(BookInfo.objects.filter(bread__gt=20,id__lt=3))
# 查询阅读量大于20,或者编号小于3
print(BookInfo.objects.filter(Q(bread__gt=20) | Q(id__lt=3)))
# 查询编号不为3的
print(BookInfo.objects.filter(~Q(id=3)))
# 聚合函数
# 查询全部的阅读数
print(BookInfo.objects.aggregate(get_sum = Sum("bread")))
# 查询全部的书籍
print(BookInfo.objects.count())
# 分组查询 annotate
books = BookInfo.objects.all().annotate(read = Count("bread"))
for book in books:
print(book.read)
# 排序
# 升序
print(BookInfo.objects.all().order_by("bread"))
# 降序
print(BookInfo.objects.all().order_by("-bread"))
# 关联查询
# 由一到多的访问语法 -->一对应的模型类对象,多对应的模型类名小写_set
book = BookInfo.objects.get(id=1)
print(book.heroinfo_set.all())
# 由多到一的访问语法 -->多对应模型类对象,一对应模型类中的关系类属性名
hero = HeroInfo.objects.get(id=1)
print(hero.hbook)
#访问一对应的模型类关联对象的id语法:多对应的模型类对象.关联类属性_id
hero = HeroInfo.objects.get(id=1)
print(hero.hbook_id)
# 关联过滤查询
# 由多模型类条件查询一模型类数据:
# 语法以下:
# 关联模型类名小写__属性名__条件运算符 = 值
# 注意:若是没有 "__运算符"部分,表示等于
# 图书英雄是孙悟空
print(BookInfo.objects.filter(heroinfo__hname="孙悟空"))
# 要求图书中英雄的描述包含八
print(BookInfo.objects.filter(heroinfo__hname__contains="郭"))
# 由一模型类条件查询多模型类数据:
# 语法以下:
# 一模型类关联属性名__一模型类属性名__条件运算符=值
# 注意:若是没有"__运算符"部分,表示等于
# 查询书名为天龙八部中的所欲英雄
print(HeroInfo.objects.filter(hbook__btitle="天龙八部"))
# 查询阅读量大于30的全部英雄
print(HeroInfo.objects.filter(hbook__bread__gt=30))python

            # 修改
                        # 修改方法一:
                        #  具体的对象没有updete方法.只有QuerySet对象才有update方法
                                            
                    hero = HeroInfo.objects.get(hname='猪八戒')
                    hero.hname = '猪悟能'
                    hero.save()
                        # 修改方法二:
                    HeroInfo.objects.filter(hname='沙悟净').update(hname='沙僧')
                            
                    # 删除
                        # 模型类对象.delete()
                    hero = HeroInfo.objects.get(id=13)
                    hero.delete()
                        # 模型类.objects.filter().delete()
                    HeroInfo.objects.filter(id=17).delete()
                    
        查询集 QuerySet
            概念:
                Django的ORM中存在查询集的概念。
                查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
                当调用以下过滤器方法时,Django会返回查询集(而不是简单的列表):
                all():返回全部数据。
                filter():返回知足条件的数据。
                exclude():返回知足条件以外的数据。
                order_by():对结果进行排序。
                对查询集能够再次调用过滤器进行过滤,如
                BookInfo.objects.filter(bread__gt=30).order_by('bpub_date')
                也就意味着查询集能够含有零个、一个或多个过滤器.
                过滤器基于所给的参数限制查询的结果
                从SQL的角度讲,查询集与select语句等价,过滤器像where、limit、order by子句。
                判断某一个查询集中是否有数据:
                exists():判断查询集中是否有数据,若是有则返回True,没有则返回False。
            两大特性
                惰性执行
                缓存
            限制查询集
            
    管理器Manager
        概念:
            管理器是Django的模型进行数据库操做的接口,Django应用的每一个模型类都拥有
            至少一个管理器。咱们在经过模型类的objects属性提供的方法操做数据库时,
            便是在使用一个管理器对象objects。当没有为模型类定义管理器时,
            Django会为每个模型类生成一个名为objects的管理器,它是models.Manager类的对象。
            
            自定义管理器
                咱们能够自定义管理器,并应用到咱们的模型类上。
                注意:一旦为模型类指明自定义的过滤器后,Django再也不生成默认管理对象objects。
                自定义管理器类主要用于两种状况:
                1. 修改原始查询集,重写all()方法。
                    a)打开booktest/models.py文件,定义类BookInfoManager
                        #图书管理器
                        class BookInfoManager(models.Manager):
                            def all(self):
                                #默认查询未删除的图书信息
                                #调用父类的成员语法为:super().方法名
                                return super().filter(is_delete=False)
                    b)在模型类BookInfo中定义管理器
                        class BookInfo(models.Model):
                            ...
                            books = BookInfoManager()
                    c)使用方法
                        BookInfo.books.all()
                2. 在管理器类中补充定义新的方法

                    a)打开booktest/models.py文件,定义方法create。
                        class BookInfoManager(models.Manager):
                            #建立模型类,接收参数为属性赋值
                            def create_book(self, title, pub_date):
                                #建立模型类对象self.model能够得到模型类
                                book = self.model()
                                book.btitle = title
                                book.bpub_date = pub_date
                                book.bread=0
                                book.bcommet=0
                                book.is_delete = False
                                # 将数据插入进数据表
                                book.save()
                                return book
                    b)为模型类BookInfo定义管理器books语法以下
                        class BookInfo(models.Model):
                              ...
                            books = BookInfoManager()
                    c)调用语法以下:
                        book=BookInfo.books.create_book("abc",date(1980,1,1))
                            
    模板
        1)配置文件
            在工程中根目录下建立模板目录templates
            在settings.py配置文件中修改TEMPLATES配置项的DIRS值
            TEMPLATES = [
                    {
                        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 此处修改
                    }
                ]
                
        2)定义模板文件(index.html)
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>Title</title>
            </head>
            <body>
                <h1>{{ city }}</h1>
            </body>
            </html>
            
        3)模板渲染
            模板渲染须要三步
                找到模板
                定义上下文
                渲染模板
                
            第一种方法:
                from django.http import HttpResponse
                from django.template import loader, RequestContext
                
                def index(request):
                    # 1.获取模板
                    template=loader.get_template('testdatabase/index.html')
                    # 2.定义上下文
                    context={'city': '北京'}
                    # 3.渲染模板            # httpresponse返回的是一个含有HTML的字符串
                    return HttpResponse(template.render(context))
           第二种方法:
                from django.shortcuts import render
                
                def index(request):
                    context={'city': '北京'}
                    return render(request,'index.html',context)
                    
        4)模板语法    
            模板变量
                视图函数代码以下:
                    def index(request):
                        context = {
                            'city': '北京',
                            'adict': {
                                'name': '西游记',
                                'author': '吴承恩'
                            },
                            'alist': [1, 2, 3, 4, 5]
                        }
                        return render(request, 'index.html', context)
                        
                # 前端代码以下    
                    <!DOCTYPE html>
                    <html lang="en">
                    <head>
                        <meta charset="UTF-8">
                        <title>Title</title>
                    </head>
                    <body>
                        <h1>{{ city }}</h1>
                        <h1>{{ adict }}</h1>
                        <h1>{{ adict.name }}</h1>  注意字典的取值方法
                        <h1>{{ alist }}</h1>  
                        <h1>{{ alist.0 }}</h1>  注意列表的取值方法
                    </body>
                    </html>    
                    
            模板语句
                for循环
                    {% for item in 列表 %}
                    
                    循环逻辑
                    {{forloop.counter}}表示当前是第几回循环,从1开始
                    {%empty%} 列表为空或不存在时执行此逻辑
                    {% endfor %}
                    
                if语句
                    {% if ... %}
                    逻辑1
                    {% elif ... %}
                    逻辑2
                    {% else %}
                    逻辑3
                    {% endif %}
                    
                注意:运算符左右两侧不能紧挨变量或常量,必须有空格。

                    {% if a == 1 %}  # 正确
                    {% if a==1 %}  # 错误
                    
            过滤器
                语法以下:
                    变量|过滤器:参数
                和flask同样基本没变化
                
            注释
                单行注释语法以下:

                    {#...#}
                多行注释使用comment标签,语法以下:

                    {% comment %}
                    ...
                    {% endcomment %}
                    
            模板继承
                只有继承操做
                {% extend "抽取的基类模板"%}
                
                进行挖坑填坑操做
                {% block 名称 %}
                
                #实际填充内容
                {{ block.super }}用于获取父模板中block的内容
                {% endblock 名称 %}
    表单
        form表单
        非form表单
    
    admin站点
        使用Django的管理模块,须要按照以下步骤操做:
            1)管理界面本地化
                在settings.py中设置语言和时区
                    LANGUAGE_CODE = 'zh-hans' # 使用中国语言
                    TIME_ZONE = 'Asia/Shanghai' # 使用中国上海时间
                    
            2)建立管理员
                建立管理员的命令以下,按提示输入用户名、邮箱、密码。
                    python manage.py createsuperuser
                建立成功可访问:
                    http://127.0.0.1:8000/admin/
                    
            3)注册模型类
                打开testdatabase/admin.py文件,编写以下代码:

                    from django.contrib import admin
                    from booktest.models import BookInfo,HeroInfo

                    admin.site.register(BookInfo)
                    admin.site.register(HeroInfo)
                    
            4)自定义管理页面
                具体看子应用testdabase的设置