Django基础
一、简介
Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的软件设计模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。
Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下:
模型(Model),即数据存取层
处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
模板(Template),即表现层
处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
视图(View),即业务逻辑层
存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。
基本目录结构:
mysite #django工程 - mysite # 整个站点配置目录 - __init__.py - settings.py # 配置文件 - urls.py # 路由关系 - wsgi.py # 遵循WSIG规范,生产一般采用uwsgi + nginx - manage.py # Django管理程序
二、安装配置django以及基本命令使用
1、安装django
#windows pip install django python -m pip install django #linux或者mac pip3 install django pip install django=1.9.5 #检查django是否安装成功 运行python终端 >>> import django >>> django.VERSION
2、创建django工程以及app
pycharm中创建:file-->New Project-->Django-->create
#创建工程 django-admin.py startproject projectname #创建app python manage.py startapp appname
tips:django中的工程和app概念,django相当于一个大项目,而其中的小系统如监控、资产管理属于这个项目的一部分我们称之为app。
app目录结构
app : migrations #数据库修改表结构记录 admin.py #Django提供的后台管理 apps.py #当前app配置文件 models.py #Django中的ORM,写指定的类 通过命令可以创建数据库结构 tests.py #项目的单元测试 views.py #MTV中的视图,用于写业务逻辑
3、配置django
模板配置:django工程-->相应工程名-->settings.py-->TEMPLATES(默认配置好的)
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
静态目录(图片、css)配置:django工程-->相应工程名-->settings.py-->STATICFILES_DIRS(需要自己手动添加,目录使用逗号隔开)
STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )
tips:若访问某个连接出现forbbiden,很有可能是有CSRF原因,可以在配置中注释
settings.py
4、其他django常用命令
#创建django命令 django-admin.py startproject project-name #创建django的app python manage.py startapp app-name 或 django-admin.py startapp app-name #同步数据库 python manage.py syncdb #注意:Django 1.7.1及以上的版本需要用以下命令 python manage.py makemigrations python manage.py migrate #命令行调试模式 python manage.py runserver 8001 python manage.py runserver 0.0.0.0:8000 #清除数据库 python manage.py flush #创建超级管理员 python manage.py createsuperuser 按照提示输入 #修改管理员密码 python manage.py changepassword username(需要修改的用户名) #导入和导出数据 python manage.py dumpdata appname > appname.json python manage.py loaddata appname.json #进入数据库 python manage.py dbshell
三、开始你的站点
1、配置路由(工程目录中的urls.py)
from django.conf.urls import url from django.contrib import admin from cmdb import views #从app中导入views视图 urlpatterns = [ url(r'^admin/', admin.site.urls), #当用户访问http://127.0.0.1:8000/admin/时候使用admin.site.urls处理 url(r'^$',views.index), #当用户访问http://127.0.0.1:8000,采用views下面的index函数处理,^表示开头,$表示结尾 ]
2、使用views处理用户请求(app下面的views.py)
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def index(request): #request中包含了用户所有的请求数据,通过该参数可以获取很多请求信息比如: # request.method GET / POST #获取用户请求的方法 # request.GET.get('key') #获取请求发来的而数据,参数为数据key # request.POST.get('key') return render(request,'index.html')#使用模板处理、响应用户请求,参数至少是两个,第一个固定为request,第二个为templates下的模板文件 #return HttpResponse("<p>this is wd </p>") #使用HttpResponse响应用户请求,参数为字符串 #return redirect("http://www.baidu.com") #将用户请求重定向到百度,若本地跳转只能写目录,比如'/login'
3、在templates目录中创建模板文件index.html,若模板文件中需要引入css或者images等内容,路径需要加上static,如
<link rel="stylesheet" href="/static/css/core/main.css">
4、运行django程序,访问http://127.0.0.1:8000你的站点就会呈现
四、视图(views)介绍
django中的视图用于处理业务逻辑,常用的定义试图方法有两种:FBV(fuction base view)、CBV(class base view)
1、FBV
views.py使用函数作为逻辑处理
def login(request): '''code''' return HttpResponse('login')
2、CBV
views.py使用面向对象的方式定义
class login(View):#需要继承View类 def dispath(self, request, *args, **kwargs): print("before do something") result = super(login, self).dispath(request, *args, **kwargs)#执行父类方法,使得重写子类方法不影响其他操作 print("after do something") return result #需要将结果返回 def get(self, request):#处理get方法的请求 print(request.method) return render(request, "index.html") def post(self, request):#处理post方法的请求 print(request.method) return render(request, "index.html")
使用cbv进行处理时候最,需要在urls.py中使用as_view()方法
url(r'^$', views.login.as_view())
五、模板语言(template)
若我们想让前端和后台进行数据交互、传递,那我需要了解django中的模板引起,下面简单介绍常用的模板语言。
1、获取单个数据,后台视图传递数据:{{ key }}
视图函数:
def person(request): if request.method=="GET": user_dict={'name':'wd','age':22} return render(request,'person.html',user_dict)#通过模板传递第三个参数,向html页面传递数据
模板文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ name }}</h1> <h1>{{ age }}</h1> </body> </html>
2、使用for循环
{% for item in item_list %} <a>{{ item }}</a> {% endfor %}
循环字典、列表,生成多行数据:
三种循环方式
<html> <body> <!-- 列表循环 --> {% for i in k1 % } <h1>{{ i }}</h1> {% endfor % } <!-- 字典循环 --> {% for k in k2.keys % } <h1>{{ k }}</h1> {% endfor % } {% for v in k2.values % } <h1>{{ v }}</h1> {% endfor % } {% for k,v in k2.items % } <h1>{{ k }}-{{ v }}</h1> {% endfor % } </body> </html>
for循环参数介绍:
{{ forloop.counter }} #计数器,循环一次增加1,可以用于获取行数,从1开始 {{ forloop.counter0 }} #计数器,循环一次增加1,可以用于获取行数,从0开始 {{ forloop.revcounter }} #计数器,循环一次增加1,倒叙,1最后 {{ forloop.revcounter0 }} #计数器,循环一次增加1,倒叙,0最后 {{ forloop.counter.first }} #是否是第一个循环,返回True 或者False {{ forloop.counter.last }} #是否是最后一个循环,返回True 或者False {{ forloop.parentloop }} #拿到父循环内容
for示例:
#视图函数 def person(request): if request.method=="GET": USER_INFO = { '1': {'name': 'jack', 'age': '22'}, '2': {'name': 'wd', 'age': '21'}, '3': {'name': 'rose', 'age': '18'}, } return render(request,'person.html',{'user_info':USER_INFO}) #html模板 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for row in user_info.values %} <p> <a>{{ row.name }}</a> <a>{{ row.age }}</a> </p> {% endfor %} </body> </html>
3、判断
{% if ordered_warranty %} {% else %} {% endif %}
4、或取单个值
html代码:
<p> 男:<input type="radio" name="gender" value="1"> 女:<input type="radio" name="gender" value="2"> 村长:<input type="radio" name="gender" value="3"> </p>
py代码:
def login(request): if request.method=="GET": return render(request,'login.html') elif request.method=="POST": v=request.POST.get('gender')#获取单个值 print(v) else: return redirect('/index/')
6、或取多个值
html代码:
<p> 男:<input type="checkbox" name="favor" value="1"> 女:<input type="checkbox" name="favor" value="2"> 村长:<input type="checkbox" name="favor" value="3"> </p>
py代码:
def login(request): if request.method=="GET": return render(request,'login.html') elif request.method=="POST": a=request.POST.getlist('favor') #获取多个值 print(a) else: return redirect('/index/')
7、上传文件
首先在工程里创建upload目录,把上传的文件都统一放到该目录
html代码:
<form action="/login/" method="post" enctype="multipart/form-data">
<p> <input type="file" name="file"> </p>
</form>
py代码:
import os def login(request): if request.method=="GET": return render(request,'login.html') elif request.method=="POST": obj = request.FILES.get('file')#上传文件 file_path=os.path.join('upload',obj.name)#放到upload目录,obj.name为上传文件名 f=open(file_path,mode='wb') for i in obj.chunks(): f.write(i) f.close() # from django.core.files.uploadedfile import InMemoryUploadedFile return render(request,'login.html') else: return redirect('/index/')
8、模版继承(extends)
当html模版中都使用了重复的html代码,我们可以使用模版来代替他们,然后让子模版继承它,但是需要注意的是,一个html只能继承一个模版。
母模版: {% block name %} {% endblock %} 使用: 先声明: {% extends 'html模版' %} {% block name %} 自己定义的内容 {% endblock %}
示例:
master.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <link href="/static/common.css" type="text/css"> {% block css %}{% endblock %} </head> <body> <div class="pg-header"></div> <div class="pg-menue"></div> <div class="pg-context"></div> {% block context %}{% endblock %} <script src="/static/jquery.js"></script> {% block js %}{% endblock %} </body> </html>
URL正则表达式
html代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul> {% for k,v in user_dict.items %} <li><a target="_blank " href="/detail-{{ k }}.html">{{ v.name }} </a></li> {% endfor %} </ul>
py代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render,HttpResponse,redirect # Create your views here. USER_DICT={ '1':{'name':'root1','email':'root@live.com'}, '2':{'name':'root2','email':'root@live.com'}, '3':{'name':'root3','email':'root@live.com'}, '4':{'name':'root4','email':'root@live.com'}, '5':{'name':'root5','email':'root@live.com'}, } # USER_DICT={ # 'k1':'root1', # 'k2':'root2', # 'k3':'root3', # 'k4':'root4', # } def index(request): # return HttpResponse('Index') return render(request,'index.html',{'user_dict':USER_DICT}) """ def login(request): if request.method=="GET": return render(request,'login.html') elif request.method=="POST": u=request.POST.get('user') p=request.POST.get('pwd') if u=='alex' and p=='123': return redirect('/index/') else: return render(request, 'login.html') else: return redirect('/index/') """ def login(request): if request.method=="GET": return render(request,'login.html') elif request.method=="POST": # v=request.POST.get('gender')#获取单个值 # print(v) # a=request.POST.getlist('favor') #获取多个值 # print(a) # file=request.POST.getfile('file')#获取文件名 # print(file) import os obj = request.FILES.get('file')#上传文件 file_path=os.path.join('upload',obj.name)#放到upload目录,obj.name为上传文件名 f=open(file_path,mode='wb') for i in obj.chunks(): f.write(i) f.close() # from django.core.files.uploadedfile import InMemoryUploadedFile return render(request,'login.html') else: return redirect('/index/') def detail(request,nid): # return HttpResponse(id) # id=request.GET.get('nid') detail_info=USER_DICT[nid] return render(request,'detail.html',{'detail_info':detail_info})