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                 - 其他
自己开发web框架的流程
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>


#######################
View Code

 

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
test.py
{% 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>
test.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
View Code

 

 注意一个常用方法: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/,所以当刷新后
#     又得重新登录.
补充

 

posted @ 2017-06-14 15:41  beiguuu  阅读(127)  评论(0)    收藏  举报