web开发框架之Django学习一
2019-02-21 06:40:02来源:博客园 阅读 ()
在脚本中如何进行Django的运行 if __name__ == '__main__': import os import 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 the 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来构造响应对象,作用: 帮助我们将数据转换为json字符串 设置响应头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来设置全局默认值。 类视图 类视图的好处: 代码可读性好 类视图相对于函数视图有更高的复用性,如果其他地方需要用到某个类视图的某个特定逻辑, 直接继承该类视图即可 代码如下: 在上面的子应用中 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: 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)) # 修改 # 修改方法一: # 具体的对象没有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.渲染模板 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的设置
原文链接:https://www.cnblogs.com/wangxiongbing/p/10410033.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:python-学习计划
- 使用scrapy框架爬取全书网书籍信息。 2019-08-13
- python 之 前端开发(form标签、单选框、多选框、file上传文 2019-08-13
- python 之 前端开发(HTTP协议、head标签、img标签、a标签、 2019-08-13
- 网络编程相关知识点 2019-08-13
- 浅谈 Web框架 2019-08-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash