django

http://docs.30c.org/djangobook2

MVC 设计模式

首先,我们分成4个Python的文件,(models.py ,views.py , urls.py ) 和html模板文件 (latest_books.html )

  • models.py 文件主要用一个 Python 类来描述数据表。 称为 模型(model) 。 运用这个类,你可以通过简单的 Python 的代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句。

  • views.py文件包含了页面的业务逻辑。 latest_books()函数叫做视图

  • urls.py 指出了什么样的 URL 调用什么的视图。 在这个例子中 /latest/ URL 将会调用 latest_books()这个函数。 换句话说,如果你的域名是example.com,任何人浏览网址http://example.com/latest/将会调用latest_books()这个函数。

  • latest_books.html 是 html 模板,它描述了这个页面的设计是如何的。 使用带基本逻辑声明的模板语言,如{% for book in book_list %}

结合起来,这些部分松散遵循的模式称为模型-视图-控制器(MVC)。 简单的说, MVC 是一种软件开发的方法,它把代码的定义和数据访问的方法(模型)与请求逻辑 (控制器)还有用户接口(视图)分开来。

Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在 MTV 开发模式中:

  • M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。

  • T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。

  • V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

Django基本配置

  Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能

1、安装:
  方式一、pip3 install django
  方式二、官网下载
      解压
      python3 setup.py install

# 添加环境变量 C:Python3Scripts


2、基本操作:

  • 创建project

    先进入自己指定的目录
    django-admin startproject mysite
  

  • 创建app
  cd mysite

  python3 manage.py startapp cmdb

  python3 manage.py startapp monitor

  mysite对应的目录结构

  - mysite (配置文件)

    -init

    -settings 配置文件

    -urls URL对应关系

    -wsgi  遵循WSIG规范,uwsgi+nginx

  - manage.py (管理Project)
  - app(cmdb)
    - models.py 数据库操作
    - admin.py 配置Django自带的后台管理
    - apps.py 当前app的配置
    - tests.py 单元测试
    - views.py 做业务处理...

Django里面没封装socket,当进行socket数据交互时要用到wsgi,生产环境下一般用第三方模块uwsgi和nginx就可以把Django程序跑起来

  • 创建templates目录

    放html文件

    需要在settings.py中加上

'DIRS': [os.path.join(BASE_DIR,'templates')],
  • 编辑url.py view.py 

    url是路由系统,每个url对应view函数处理业务

    view.py  业务处理

      1、return render(request,模板路径,{'key':'value'})   

      2、return redirect(url) 跳转

      3、return HttpResponse('ok')

  • 运行
  cd mysite
  python3 manage.py runserver 127.0.0.1:8000

1.urls.py下面指定url,一个url对应一个函数 from cmdb import view

2.view.py下面写函数,return的html会去templates目录下找

3.settings.py指定了html在templates目录下,如果POST的方式发送,这行需要注释,否则forbidden

# 'django.middleware.csrf.CsrfViewMiddleware',

 用户在浏览器中输入url,看到页面展示,整个流程

  url.py中匹配对应的路由系统,去view.py中找对应的函数处理,默认method=get,返回templates中的html。

 静态文件(css,js,图片)

创建statics文件夹(文件夹名字随意)

settings.py最后加上

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'statics'),#这里面的路径一定是创建的文件
os.path.join(BASE_DIR,'static'),#如果statics和static下面都有相同的js,优先执行statics的,static下面的不执行 )

css

创建commons.css

<link rel="stylesheet" href="/static/commons.css">

js

创建commons.js,记得把jquery也放在此目录下

{% load staticfiles %}#放在html最上面

<script src="{% static "jquery-1.12.4.js" %}"></script>
<script src="{% static "commons.js"%}"></script>

django数据库操作

  类 --> 数据库的表

  字段 --> 列

  对象 --> 一行数据

创建数据库表sqlite

models.py

        class UserInfo(models.Model):
            nid = models.AutoField(primary_key=True)
       user_group = models.ForeignKey('UserGroup') username
= models.CharField(max_length=32) pwd = models.CharField(max_length=64) age = models.IntegerField()
     class UserGroup(models.Model):
       uid = models.AutoField(primary_key=True)
       caption = models.CharField(max_length=64)

*需要在settings.py下  INSTALLED_APPS加上app名字,否则不能创建表

termail下执行

  python3 manage.py makemigrations

  python3 manage.py migrate

需要注意的是,在创建完数据库后,UserInfo表中会出现user_group_id的字段,user_group存在的,代表UserGroup这个对象

在view.py中,能通过user_group访问对象的属性

obj = models.UserInfo.objects.all()

for row in obj:

  row.user_group.uid

  row.user_group.caption

连接mysql

*需要自己先创建数据库

create database day19 charset utf8;

*django连接mysql用的是MySqlDB,如果用的是python3的话,需要在配置目录的init.py中加上:

import pymysql
pymysql.install_as_MySQLdb()

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day19',
        'USER': 'root',
        'PASSWORD': 'centos',
        'HOST': '192.168.147.147',
        'PORT': '3306',
    }
}

数据库基本操作

a. 查

  models.tb.objects.all()
  models.tb.objects.filter(nid=1)
  models.tb.objects.filter(nid=1).first()

b. 增
  1.models.tb.objects.create(...)
  2.
  obj = models.tb(...)
  obj.save()
c. 删
  models.tb.objects.all().delete()
  models.tb.objects.filter(nid=1).delete()
d. 改
  models.tb.objects.all().update(...)
  models.tb.objects.filter(nid=1).update(...)

路由系统urls.py

1、单一路由对应

1
url(r'^index$', views.index),

2、基于正则的路由

1
2
url(r'^index/(d*)', views.index),
url(r'^manage/(?P<name>w*)/(?P<id>d*)', views.manage),

利用  url(r'^edit_user_new-(?P<nnid>d+).html$', views.edit_user_new)实现编辑,url中带.html以为是静态文件,权重会高点。

整个流程  

  user.html中<a href="/edit_user_new-{{ row.nid }}.html">新编辑</a>

  新编辑跳转到这个url,url.py中加url(r'^edit_user_new-(?P<nnid>d+).html$', views.edit_user_new)

  views.py中def edit_user_new(request,nnid)需要带上参数,method是GET

  编辑完之后提交,action="/edit_user_new-{{ obj.nid }}.html"

  

3、添加额外的参数

1
url(r'^manage/(?P<name>w*)', views.manage,{'id':333}),

4、为路由映射设置别名

1
2
url(r'^home', views.home, name='h1'),
url(r'^index/(d*)', views.index, name='h2'),

h1就代指这个url

<form method="POST" action="{% url 'nnn' nnid=obj.nid %}">

设置名称之后,可以在不同的地方调用,如:

  • 模板中使用生成URL     {% url 'h2' 2012 %}
  • 函数中使用生成URL     reverse('h2', args=(2012,))      路径:django.urls.reverse
  • Model中使用获取URL  自定义get_absolute_url() 方法

5、根据app对路由规则进行分类

1
url(r'^app01/',include('app01.urls')),

当访问127.0.0.1:8000/app01/user时,先去匹配前面的app01,然后去app01下面的url.py中匹配

6、命名空间

a. project.urls.py

1
2
3
4
5
6
from django.conf.urls import url,include
 
urlpatterns = [
    url(r'^a/', include('app01.urls', namespace='author-polls')),
    url(r'^b/', include('app01.urls', namespace='publisher-polls')),
]

b. app01.urls.py

1
2
3
4
5
6
7
from django.conf.urls import url
from app01 import views
 
app_name = 'app01'
urlpatterns = [
    url(r'^(?P<pk>d+)/$', views.detail, name='detail')
]

c. app01.views.py

1
2
3
def detail(request, pk):
    print(request.resolver_match)
    return HttpResponse(pk)

以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

  • v = reverse('author-polls:detail', kwargs={'pk':11})
  • {% url 'app01:detail' pk=12 pp=99 %}

django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

视图函数views.py

  获取请求信息:
    request.POST {'username':'root'..}
    request.GET
    request.FILES

      obj = request.FILES.get(input里面的name)

      文件名 obj.name

      for line in obj.chunks()

    request.method
    request.body = username=root;age=18;gender=male

  响应结果:
    return HttpReponse(..)
    return render(request,'path/a.html',{})
    return redirect('http://www.baidu.com')

模板

 模板中也有自己的语言,该语言可以实现数据展示

  • {{ item }}
  • {% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
      forloop.counter
      forloop.first
      forloop.last 
  • {% if ordered_warranty %}  {% else %} {% endif %}
  • extend

    母板:{% block title %}{% endblock %}
    子板:{% extends "base.html" %}
       {% block title %}新内容{% endblock %}

  • include

    子板:{% extends "base.html" %}
       {% block title %}新内容{%include 'small.html'%}{% endblock %} 

  • 字典.key   列表.索引
  • 帮助方法:
    {{ item.event_start|date:"Y-m-d H:i:s"}}
    {{ bio|truncatewords:"30" }}
    {{ my_list|first|upper }}
    {{ name|lower }}

3、自定义simple_tag(页面展示)

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
   
register = template.Library()
   
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
   
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)
from django import template
from django.utils.safestring import mark_safe
register = template.Library()

@register.filter()

def anyway(value,num):
    return 'dassssssssssssssssssssssssssss'+value+str(num)
@register.filter()
def ya(value,v):
    temp = "<a href='http://www.baidu.com?t=%s'>%s</a>"%(v,value)
    return mark_safe(temp)

c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

1
{% load xx %}

d、使用simple_tag

1
2
{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配置当前app,不然django无法找到自定义的simple_tag  

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
)

4、自定义filter(在if条件中做条件时)

{{ summary|anyway:8 }}

在页面仅显示内容用simple_tag

 cookie

  - 是用户浏览器上的一个键值对
  - 设置超时时间

  利用cookie可实现:
    - 登录验证
    - 页面显示条数
    - 拖动位置..

  两大忌讳:
    - 敏感信息
    - 简单

1、获取Cookie:

1
2
3
4
5
6
request.COOKIES.get('key')
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间

2、设置Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
rep = HttpResponse(...) 或 rep = render(request, ...) 或 rep = redirect(url)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

1
2
<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num"30,{ path: '/' });

  设置cookie

    obj = redirect('/app02/groups')
    obj.set_cookie(key='user_name',value=u,max_age=10)
    return obj

  获取cookie

    request.COOKIES.get('user_name')

session

session依赖cookie

SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默认)

SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False

 生成随机字符串保存在客户端,服务器端保存形式字典,{'随机字符串':{'username':'root','password':'pwd'}}

  request.session['user'] = u

  v = request.session.get('user')

装饰器+session实现登录认证

from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

from app01 import models
# Create your views here.
def auth(func):
    def inner(request,*args,**kwargs):
        v = request.session.get('user')
        if not v:
            return redirect('/app02/login')
        else:
            return func(request,*args,**kwargs)
    return inner
@auth
# group = auth(group)
def group(request):
    # # v = request.session.get('username')
    # if not v:
    #     return redirect('/app02/login')
    # else:
    return render(request,'groups.html')
@auth
def user(request):
    return render(request,'user.html')

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        u = request.POST.get('username')
        p = request.POST.get('pwd')
        v = models.UserInfo.objects.filter(username=u,pwd=p).first()
        if v:
            obj = redirect('/app02/groups')
            # obj.set_cookie(key='user',value=u,max_age=10)
            request.session['user'] = u
            return obj
        else:
            return render(request, 'login.html',{'msg':'用户名或密码错误'})

主要加了个auth函数,auth函数功能,取session,有执行func,没有的话跳转到login

原文地址:https://www.cnblogs.com/hongpeng0209/p/6516357.html