python--Django框架(一)
1 1. 自己开发Web框架 2 - socket 3 - http协议 4 - HTML知识 5 - 数据库(pymysql,SQLAlchemy) 6 7 HTTP: 8 无状态、短连接 9 10 TCP: 11 不断开 12 13 WEB应用(网站): 14 Http协议: 15 发送: 16 POST /index HTTP/1.1 17 Host: 127.0.0.1:8080 18 Connection: keep-alive 19 Cache-Control: max-age=0 20 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 21 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36 22 HTTPS: 1 23 Accept-Encoding: gzip, deflate, sdch 24 Accept-Language: zh-CN,zh;q=0.8 25 Cookie: csrftoken=hNmu2JOtntGMN0hSRSPmMQk2newEb3o8zb6pXW5Cc3m54IaA5VlTkUvqWsFezpni 26 27 28 p=123 29 30 响应: 31 200 OK 32 Cache-Control:public, max-age=15 33 Connection:keep-alive 34 Content-Encoding:gzip 35 Content-Type:text/html; charset=utf-8 36 Date:Wed, 14 Jun 2017 01:21:17 GMT 37 Expires:Wed, 14 Jun 2017 01:21:33 GMT 38 Last-Modified:Wed, 14 Jun 2017 01:21:03 GMT 39 Transfer-Encoding:chunked 40 Vary:Accept-Encoding 41 X-Frame-Options:SAMEORIGIN 42 X-UA-Compatible:IE=10 43 44 45 46 用户在页面看到的内容“字符串”(看到页面效果,由于浏览器解析) 47 48 49 浏览器(socket客户端) 50 2. www.cnblogs.com(42.121.252.58,80) 51 sk.socket() 52 sk.connect((42.121.252.58,80)) 53 54 sk.send('我想要xx') 55 5. 接收 56 6. 连接断开 57 58 59 60 博客园(socket服务端) 61 1. 监听ip和端口(42.121.252.58,80) 62 while True: 63 用户 = 等待用户连接 64 3. 收到'我想要xx' 65 4. 响应:“好” 66 用户断开 67 68 69 70 import socket 71 72 sock = socket.socket() 73 sock.bind(('127.0.0.1',8080)) 74 sock.listen(5) 75 76 while True: 77 conn,addr = sock.accept() # hang住 78 # 有人来连接了 79 # 获取用户发送的数据 80 data = conn.recv(8096) 81 conn.send(b"HTTP/1.1 200 OK\r\n\r\n") 82 conn.send(b'123123') 83 conn.close() 84 85 86 87 1. Http,无状态,短连接 88 2. 89 浏览器(socket客户端) 90 网站(socket服务端) 91 92 3. 自己写网站 93 a. socket服务端 94 b. 根据URL不同返回不同的内容 95 路由系统: 96 URL -> 函数 97 c. 字符串返回给用户 98 模板引擎渲染: 99 HTML充当模板(特殊字符) 100 自己创造任意数据 101 字符串 102 103 4. Web框架: 104 框架种类: 105 - a,b,c --> Tornado 106 - [第三方a],b,c --> wsgiref -> Django 107 - [第三方a],b,[第三方c] --> flask, 108 109 分类: 110 - Django框架(Web。。。。。。) 111 - 其他
Django: - 路由 - 视图 - 模板 - ORM(类-表;对象-行; pymysql连接数据库) Torando: - 路由 - 视图 - 模板 - 自由:pymysql;SqlAchemy Flask: - 路由 - 视图 - 模板(第三方的组件) - 自由:pymysql;SqlAchemy
一、Django安装以及基础命令的使用
Django主要的是通过:views(视图,配置函数)、setting(配置。设置中间件、静态文件、数据库配置、等)、urls(路由系统)、templates(模板)
安装--pip3 install Django
创建项目-- django-admin startproject sitename
-- 在pycharmIDE中创建项目
创建app-- python manage.py startapp appname
-- 在pycharmIDE中创建项目的时候可以直接点击下面的setting创建 app

运行服务-- python makemigrations runserver 127.0.0.1:8080
--点击pycharmIDE里面的运行按钮
数据库使用-- python manage.py makemigrations
-- python manage.py migrate
二、配置文件
1.配置urls路由系统
from mysite import views urlpatterns = [ url(r'^pro/', views.pro), url(r'^guanli/', include('mysite.urls')) ] 1.基本配置: ''' 1.路劲的名称。2.调用的视图函数。3.别名html文件调用 ''' 2.Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 在做项目的时候,会有很多的文件,为了很好的管理路由系统,将相同事物的路径写到同一个主路由下。 url(r'^blog/', include('blog.urls')) 写好上面的这串代码后,在自己的app项目中创建一个urls,再将住路由下的路径写到新创建的urls文件中。方法和Django中的urls代码相同
2.配置数据库
因为django默认的是sqlite数据库;
#myspl的数据配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', #引擎的名称 'NAME': 'Django_orm', #你的数据库名称 'USER': 'root', #你的数据库用户名 'PASSWORD': '1234qwer', #你的数据库密码 'HOST': '', #你的数据库主机,留空默认为localhost 'PORT': '3306', #你的数据库端口 } } PS.在配置之前,先将sqlite的配置注释掉
2.在django项目下的__init__.py中添加 import pymysql pymysql.install_as_MySQLdb() #告诉django将我的驱动引擎替换成myspl 3.在models中创建类,类=>表 class Book(models.Model): #CharField:存储一个字符串类型 name = models.CharField(max_length=20) #IntegerField:整数类型的 price =models.IntegerField() #DateField:时间类型 pub_data = models.DateField() author = models.CharField(max_length=32) 4.在terminal中,输入两条命令 python manage.py makemigrations python manage.py migrate 5.在database中创建mysql库,选择你要连接的库名,对应的账号密码。即可
3.静态文件
STATIC_URL = '/static/'#静态文件的别名 STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'mysite', '../static'),#找到我的命名的静态文件的绝对路径 ) 所有的静态文件都是写在这个新创建的文件夹中,js、css、images等
三、路由系统
1.单一的路由设置
#配置在urls中 url(r'^login/', views.login),
2.设置正则路由系统
#当输入路径时,不同的正则判断,渲染的页面不同 url(r'^article/(\d{4})', views.article_show),
3.添加额外的参数
url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),
4.为路由映射设置名称
url(r'^home', views.home, name='h1'), url(r'^index/(\d*)', views.index, name='h2'),
5.当路由错误的时候,直接给用户跳转一个404的页面
#在路由中什么也不写,给一个函数,在函数中添加html或者HttpResponse即可 url(r'^', views.d),
路由映射:
可以在不同的地方调用
-- 在模板中生成url {% url 'reg' %}
--
5.根据url进行分发
url(r'^guanli/', include('mysite.urls'))
分类:
由于内容过多、方面管理,查找
6.urls+views+html的一个登陆
urlpatterns = [ url(r'^index',views.index,name='bieming'), url(r'^admin/', admin.site.urls), # url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ] ################### def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登陆成功") return render(req,'index.html') ##################### <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# <form action="/index/" method="post">#} <form action="{% url 'bieming' %}" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html> #######################
7. 伪静态路由系统
#html:伪静态路由系统,seo中默认是静态文件,搜索的纪律会大大提升。 #$:以$符号结尾路由中最后就是https://i.cnblogs.com/EditArticles.aspx?postid=7009198&update=1这种方式而不是这种:http://127.0.0.1:8000/index/ url(r'^res/(\w+).html$', views.res,name='a2'),#name = '名称':这是给路由其别名,
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
四、模板
模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。
1.在views文件中,创建一个基于html文档格式的请求体,
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
2.通过views文件中的函数,将数据返回给html
views.py文件 class A(): def __init__(self,name,age): self.name = name self.age = age def pro(repuest): k =['杨翔','alex','end'] d = {'name':'yang','age':23} c = A('老男孩',30) d1 ='ya ngx ia ng' v = datetime.datetime.now() v1 = [] v2 = '<a herf="#">点击</a>' li = [1,2,3,4,5,6,7,89,9] return render(repuest,'name.html',locals())#{'name':k} ----------------------------- name.html文件 1.遍历列表中的内容,返回到html中, for循环: {% for i in items %}#开始 {{ i }}#内容 {% endfor %}#结束 <ul> {% for i in k %} <li>{{ i }}</li> {% endfor %} </ul> 2.获取字典中的val,都是用点的形式去得到 <h1> {{ d.name }}{{ d.age }} </h1> 3.实例化出来的对象。 {{ c.name }} 4.通过模板中内置的方法去除空格 <h1>{{ d1|cut:' ' }}</h1> 5.设置时间模块,通过获取的时间,传给html中 <h1>{{ v|date:'Y-m-d' }}</h1> #内置方法,将获取的时间格式化 6.内置方法 <h1>{{ v1|default:'空的' }}</h1> 7. #直接原样显示 <h1>{{ v2 }}</h1> #需要通过内置模板,就可以获取标签里面的内容 {% autoescape off %} {{ v2 }} {% endautoescape %} 8.遍历 <ul> {% for i in k %} <li>{{ i }}</li> {% endfor %} </ul> {% for item in li %} <p>{{ forloop.counter0 }} : {{ item }}</p> <p>{{ forloop.revcounter }} : {{ item }}</p> <p>{{ forloop.revcounter0 }} : {{ item }}</p> {% endfor %}
forloop的使用
django forloop如下: 在每个`` {% for %}``循环里有一个称为`` forloop`` 的模板变量。这个变量有一些提示循环进度信息的属性。 forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。 {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。 forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。 forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。在第一次执行循环时,该变量会被置为序列的项的个数减1。 forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为```` 在下面的情形中这个变量是很有用的: System Message: WARNING/2 (<string>, line 1071); backlink Inline literal start-string without end-string. {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|) {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %} 上面的模板可能会产生如下的结果: Link1 | Link2 | Link3 | Link4 另一个常见的用途是为列表的每个单词的加上逗号。 Favorite places: {% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %} forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。 例子在此: {% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }}</td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table> {% endfor %} forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了。 Context和forloop变量 在一个 {% for %} 块中,已存在的变量会被移除,以避免 forloop 变量被覆盖。 Django会把这个变量移动到 forloop.parentloop 中。通常我们不用担心这个问题,但是一旦我们在模板中定义了 forloop 这个变量(当然我们反对这样做),在 {% for %} 块中它会在 forloop.parentloop 被重新命名。
1.遍历一个列表, 2.进行判断,是第一次遍历, 3第一个li添加一个class, 4如果不是就不添加class。 5.列表为空,那么就打印H1里面的内容 {% for name in k %} {% if forloop.first %} <li class="first"> {% else %} <li> {% endif %} {{ name }} </li> {% empty %} <h1>没有内容.重新去玩</h1> {% endfor %}
{% for item in li %}
# 从0开始排序
{# <p>{{ forloop.counter0 }} : {{ item }}</p>#}
# 倒序排列最小是1,但是内容是顺序的。
{# <p>{{ forloop.revcounter }} : {{ item }}</p>#}
# 倒序排列最小是0,但是内容是顺序的
<p>{{ forloop.revcounter0 }} : {{ item }}</p>
{% endfor %}
3.自定义模板
(1).在app01下创建一个templatetags目录(这个名称是固定的),
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.filter() def my_upper(v1): return v1.upper() @register.tag() def tag1(v1,v2,): if v1 is True: return v1 elif v2.isupper(): return v2
{% load test %} #导入要使用的文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>test</h1>
<h2>filter</h2>
{{ name|my_upper }}#自定义的方法
</body>
</html>
simple_tag缺点:不能在前端用作if else判断条件,filter可以。
filter缺点:不能传任意参数,simple_tag可以。
五、views视图
http请求中产生两个核心对象:
http请求:HttpRequest对象
http响应:HttpResponse对象
1 HttpRequest对象的属性和方法:
# path: 请求页面的全路径,不包括域名 # # method: 请求中使用的HTTP方法的字符串表示。全大写表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含所有HTTP GET参数的类字典对象 # # POST: 包含所有HTTP POST参数的类字典对象 # # 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过 # HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用 # if req.POST来判断是否使用了HTTP POST 方法;应该使用 if req.method=="POST" # # # # COOKIES: 包含所有cookies的标准Python字典对象;keys和values都是字符串。 # # FILES: 包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中 name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys: # # filename: 上传文件名,用字符串表示 # content_type: 上传文件的Content Type # content: 上传文件的原始内容 # # # user: 是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前 # 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你 # 可以通过user的is_authenticated()方法来辨别用户是否登陆: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 时该属性才可用 # # session: 唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。 #方法 get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 req.path:/index33
注意一个常用方法:request.POST.getlist('')
2 HttpResponse对象:
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染: render()(推荐)<br> render_to_response(),
页面跳转: redirect("路径")
locals(): 可以直接将函数中所有的变量传给模板
-----------------------------------url.py url(r"login", views.login), url(r"yuan_back", views.yuan_back), -----------------------------------views.py def login(req): if req.method=="POST": if 1: # return redirect("/yuan_back/") name="yuanhao" return render(req,"my backend.html",locals()) return render(req,"login.html",locals()) def yuan_back(req): name="苑昊" return render(req,"my backend.html",locals()) -----------------------------------login.html <form action="/login/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性别<input type="text" name="sex"></p> <p>邮箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> -----------------------------------my backend.html <h1>用户{{ name }}你好</h1> #总结: render和redirect的区别: # 1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分 # 除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦. # 2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后 # 又得重新登录.

浙公网安备 33010602011771号