s14 django基础
Django基础篇
- 参考资料
Django【基础篇】
https://www.cnblogs.com/wupeiqi/articles/5237704.html
- Web框架
- Web框架本质、自定义Web框架
https://www.cnblogs.com/wupeiqi/articles/5237672.html
- MVC和MTV
MVC
Model View Controller
数据库 模板文件 业务处理
MTV
Model Template View
数据库 模板文件 业务处理
- 基本配置
# 安装:pip3 install django
# 创建Django工程
django-admin startproject 【工程名称】
mysite
- mysite # 对整个程序进行配置
- init
- settings # 配置文件
- url # URL对应关系
- wsgi # 遵循WSIG规范,上线后:uwsgi + nginx
- manage.py # 管理Django程序:
- python manage.py
- python manage.py startapp xx
- python manage.py makemigrations
- python manage.py migrate
- app01
- views.py
- admin.py
- models.py # 创建数据库表
# 运行Django功能
python manage.py runserver 127.0.0.1:8001
# 创建app
cd mysite
python manage.py startapp cmdb
python manage.py startapp openstack
python manage.py startapp xxoo....
# app:
migrations 数据修改表结构
__init__.py python2必须文件,python3不需要
admin Django为我们提供的后台管理
apps 配置当前app
models ORM,写指定的类,通过命令可以创建数据库结构
tests 单元测试
views 业务代码
# 其他常用命令:
python manage.py runserver 0.0.0.0
python manage.py startapp appname
python manage.py syncdb
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
# 配置模板的路径
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',
],
},
},
]
# 配置静态目录
static
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
<link rel="stylesheet" href="/static/commons.css" />
# 数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}
# Django连接MySQL时使用MySQLdb模块,而python3中无此模块,所以需要使用pymysql来代替
# 如下设置放置的与project同名的配置的 __init__.py文件中
import pymysql
pymysql.install_as_MySQLdb()
# 使用model.py时配置 project.settings.py
INSTALLED_APPS
app01,
# 注释csrf(暂时注释)
# Django请求生命周期
- 路由系统
- 单一路由对应
url(r'^index$', views.index),
# url.py
# from app01 import views
# "login" --> 函数名
# 此处r'^login/'中的/ 与form中的action="/login/" 保持一致
# RuntimeError at /login
1、url(r'^index/', views.index),
url(r'^home/', views.Home.as_view()),
2、url(r'^detail-(\d+).html', views.detail),
def detail(request,nid):
3、url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)
def detail(request, *args,**kwargs):
pass
示例:
a.
url(r'^detail-(\d+)-(\d+).html', views.detail),
def func(request, nid, uid):
pass
def func(request, *args):
args = (2,9)
def func(request, *args, **kwargs):
args = (2,9)
b.
url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)
def func(request, nid, uid):
pass
def funct(request, **kwargs):
kwargs = {'nid': 1, 'uid': 3}
def func(request, *args, **kwargs):
args = (2,9)
- 字典嵌套,查看详细,URL正则
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'},
}
# def detail(request):
# nid = request.GET.get('nid')
# detail_info=USER_DICT[nid]
# return render(request,'detail.html',{'detail_info':detail_info})
def detail(request,nid):
"""
# return HttpResponse(nid)
print(nid,uid)
return HttpResponse(nid,uid)
# uid 无法返回
"""
detail_info=USER_DICT[nid]
return render(request,'detail.html',{'detail_info':detail_info})
# detail('req',1,2)
# detail('req',nid=1,uid=3)
# def detail(request,*args,**kwargs):
# url(r'^detail/', views.detail),
# url(r'^detail-(\d+).html/', views.detail),
# url(r'^detail-(\d+)-(\d+).html/', views.detail),
# url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html/', views.detail),
{% for k,row in user_dict.items %}
//<li><a target="_blank" href="/detail/?nid={{ k }}">{{ row }}</a></li>
//<li><a target="_blank" href="/detail/?nid={{ k }}">{{ row.name }}</a></li>
<li><a target="_blank" href="/detail-{{ k }}.html">{{ row.name }}</a></li>
{% endfor %}
4、 name
对URL路由关系进行命名,以后可以根据此名称生成自己想要的URL
url(r'^asdfasdfasdf/', views.index, name='i1'),
url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'),
url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'),
def func(request, *args, **kwargs):
from django.urls import reverse
url1 = reverse('i1') # asdfasdfasdf/
url2 = reverse('i2', args=(1,2,)) # yug/1/2/
url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/
xxx.html
{% url "i1" %} # asdfasdfasdf/
{% url "i2" 1 2 %} # yug/1/2/
{% url "i3" pid=1 nid=9 %} # buy/1/9/
注:
# 当前的URL
request.path_info
- 示例:
# url(r'^xxxxxxxxxxxxxxxx/', views.index,name='indexx'),
# url(r'^index/(\d+)/(\d+)/', views.index,name='indexx'),
url(r'^index/(?P<nid>\d+)/(?P<uid>\d+)/', views.index,name='indexx'),
//<form action="{% url 'indexx' %}" method="POST">#}
//<form action="{% url 'indexx' 4 %}" method="POST">#}
//<form action="{{ request.path_info }}" method="POST">#}
// 添加完后留在当期页
<form action="{% ur 'indexx' nid=1,uid=3 %}" method="POST">#}
<input type="text"name="user">#}
<input type="text"name="email">#}
<input type="submit">#}
</form>#}
- 反向生成URL
def index(request,nid,uid):
print(request.path_info)
# /xxxxxxx/33333333
from django.urls import reverse
# v = reverse('indexx')
# v = reverse('indexx',args=(90,80,))
v = reverse('indexx',kwargs={'nid':11,'uid':99})
print(v)
return render(request,'index.html',{'user_dict':USER_DICT})
5、多级路由
project/urls.py
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^cmdb/', include("app01.urls")),
url(r'^monitor/', include("app02.urls")),
]
app01/urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^login/', views.login),
]
app02/urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app02 import views
urlpatterns = [
url(r'^login/', views.login),
]
- 示例:
# project/urls.py
from django.conf.urls import url,include
from django.contrib import admin
# from app01 import views as V1
# from app02 import views as V2
# from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^cmdb/', include('app01.urls')),
url(r'^monitor/', include('app02.urls')),
]
# app01/urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^login/', views.login),
]
6、默认值
url(r'^index/', views.index, {'name': 'root'}),
def index(request,name):
print(name)
return HttpResponse('OK')
7、命名空间
a. project.urls.py
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
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
from django.shortcuts import render,HttpResponse
from django.urls import reverse
def detail(request, pk):
print(request.resolver_match)
return HttpResponse(pk)
以上定义带命名空间的url之后,使用name生成URL时候,应该如下:
v = reverse('author-polls:detail', kwargs={'pk':11})
{% url 'author-polls:detail' pk=12 pp=99 %}
# django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,
# 这样才能将请求交给对一个的view中的函数去处理。
# 其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
# 通过反射机制,为django开发一套动态的路由系统Demo: 点击下载:django_dynamic_router.rar
- 视图函数
# app下views.py
from django.shortcuts import HttpResponse,render,redirect
def func(request):
# request 包含用户提交的所有数据
# request.method GET / POST
# 获取请求发来的而数据
# http://127.0.0.1:8009/home?nid=123&name=alex
# request.GET.get('',None)
# request.POST.get('',None)
# request.POST['users']
# 没有users则报错,不推荐
# return HttpResponse("字符串")
# return render(request, "/path/HTML模板的路径",{'':xxx})
# return redirect('/只能填URL')
# 本地则时/home,网址无需 /
1、获取用户请求数据
request.GET
request.POST
request.FILES
request.getlist # checkbox等多选的内容
request.method
request.path_info
request.COOKIES
request.body
request.GET(request.body)
request.POST(request.body)
request.FILES
request.getlist # checkbox等多选的内容
request.Meta
request.method
request.path_info
request.COOKIES
PS:
GET:获取数据
POST:提交数据
- 请求的其他信息
# def index(request):
# print(type(request))
# from django.core.handlers.wsgi import WSGIRequest
# print(request.environ)
# for k,v in request.environ.items():
# print(k,v)
# return HttpResponse('ok')
from django.core.handlers.wsgi import WSGIRequest
request.environ
request.environ['HTTP_USER_AGENT']
2、返回值
def func(request):
return HttpResponse('字符串')
return render(request, 'index.html', {''})
retrun redirect('URL')
a = '中国‘
return HttpResponse(bytes(a))
# 支持字符串、字节
3、上传文件
# 上传文件,form标签做特殊设置
obj = request.FILES.get('fafafa')
obj.name
f = open(obj.name, mode='wb')
for item in obj.chunks():
f.write(item)
f.close()
# 文件对象.size
4、FBV & CBV
function base view
url.py
index -> 函数名
view.py
def 函数(request):
...
/index/ -> 函数名
/index/ -> 类
建议:两者都用
# CBV
url(r'^home/', views.Home.as_view()),
# ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
from django.views import View
class Home(View):
def dispatch(self, request, *args, **kwargs):
# 调用父类中的dispatch方法
print('before')
result = super(Home,self).dispatch(request, *args, **kwargs)
print('after')
return result
# dispatch实现拓展
def get(self,request):
print(request.method)
return render(request,'home.html')
def post(self,request):
print(request.method)
return render(request,'home.html')
5、装饰器
见cookie
- 登陆实现:
def login(request):
if request.method =='GET':
# 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:
# put,delete,head,option..
return redirect('/index/')
<form action="/cmdb/login/"method="POST">
<p><input type="text"name="user"placeholder="用户名"></p>
<p><input type="password"name="pwd"placeholder="密码"></p>
<p><input type="submit"value="提交"></p>
</form>
- 注册实现:
def login(request):
if request.method =='GET':
# GET 必须大写,否则无法进入
return render(request,'login.html')
elif request.method=='POST':
# ------ radio/ select 单选
# v=request.POST.get('gender')
# print(v)
# ------ checkbox/ select 多选
# 报错:erros:A server error cocurred. Please contact the administrator
# 解决:makemigrations migrate
# v=request.POST.getlist('favor')
# print(v)
# ------ 文件
# v= request.POST.get('fafafa')
# print(v)
# 只拿到文件名
obj = request.FILES.get('fafafa')
print(obj,type(obj),obj.name)
# obj.name __str__ --> __repr__
from django.core.files.uploadedfile import InMemoryUploadedFile
# 上传功能实现:
import os
file_path = os.path.join('upload',obj.name)
f = open(file_path,mode='wb')
for i in obj.chunks():
f.write(i)
f.close()
return render(request,'login.html')
else:
# put,delete,head,option..
return redirect('/index/')
<form action="/login/"method="POST" enctype="multipart/form-data">
{# # 上传文件必须设置:enctype="multipart/form-data"#}
{# 没加表示上传字符串、文件名#}
<p><input type="text"name="user"placeholder="用户名"></p>
<p><input type="password"name="pwd"placeholder="密码"></p>
<p>男:<input type="radio" name="gender"value="1">
女:<input type="radio" name="gender"value="2">
中:<input type="radio" name="gender"value="3"></p>
<p>男:<input type="checkbox" name="favor"value="11">
女:<input type="checkbox" name="favor"value="22">
中:<input type="checkbox" name="favor"value="33"></p>
<p><select name="city" multiple>
<option value="sh">上海</option>
<option value="bj">北京</option>
<option value="tj">天津</option></select></p>
<p><input type="file"name="fafafa"></p>
<p><input type="submit"value="提交"></p>
</form>
- 模板语言
- 特殊的模板语言
# {{ 变量名 }}
# view.py
def func(request):
return render(request, "index.html", {'current_user': "alex"})
# index.html
<html>
<body>
<div>{{current_user}}</div>
</body>
</html>
#最后生成的字符串
<html>
<body>
<div>alex</div>
</body>
</html>
- For循环:
def func(request):
return render(request, "index.html",{、
current_user': "alex",
'user_list': ['alex','eric']})
# index.html
<div>{{current_user}}</div>
<ul>
{% for row in user_list %}
{% if row == "alex" %}
<li>{{ row }}</li>
{% endif %}
{% endfor %}
</ul>
- 索引
def func(request):
return render(request, "index.html", {
'current_user': "alex",
'user_list': ['alex','eric'],
'user_dict': {'k1': 'v1', 'k2': 'v2'}})
# index.html
<div>{{current_user}}</div>
<a> {{ user_list.1 }} </a>
<a> {{ user_dict.k1 }} </a>
<a> {{ user_dict.k2 }} </a>
- 条件:
def func(request):
return render(request, "index.html", {
'current_user': "alex",
"age": 18,
'user_list': ['alex','eric'],
'user_dict': {'k1': 'v1', 'k2': 'v2'}})
# index.html
<div>{{current_user}}</div>
<a> {{ user_list.1 }} </a>
<a> {{ user_dict.k1 }} </a>
<a> {{ user_dict.k2 }} </a>
{% if age %}
<a>有年龄</a>
{% if age > 16 %}
<a>老男人</a>
{% else %}
<a>小鲜肉</a>
{% endif %}
{% else %}
<a>无年龄</a>
{% endif %}
- 字典循环
# USER_DICT = {
# 'k1':'root1',
# 'k2':'root2',
# 'k3':'root3',
# 'k4':'root4',
# }
{{ user_dict.k1 }}
<ul>
{% for k in user_dict.keys %}
<li>{{ k }}</li>
{% endfor %}
</ul>
<ul>
{% for val in user_dict.values %}
<li>{{ val }}</li>
{% endfor %}
</ul>
<ul>
{% for k,row in user_dict.items %}
<li>{{ k }}-{{ row }}</li>
{% endfor %}
</ul>
- 再举例
render(request, "模板的文件的路径",
{'obj': 1234,
'k1': [1,2,3,4],
"k2": {'name': '张扬','age': 73}})
<h1> {{ obj }} </h1>
<h1> {{ k1.3 }} </h1>
<h1> {{ k2.name }} </h1>
{% for i in k1 %}
<p> {{ i }} </p>
{% endfor %}
{% for row in k2.keys %}
{{ row }}
{% endfor %}
{% for row in k2.values %}
{{ row }}
{% endfor %}
{% for k,v in k2.items %}
{{ k }} - {{v}}
{% endfor %}
- 模板继承extends
- 模板master中,变化部分用标记占位
{% block content %}
{% endblock %}
{% block title %}
{% endblock %}
- 子板中顶部先声明引用,只写block的内容
{% extends 'master.html' %}
{% block title %}标题{% endblock %}
{% block content %}
“子板内容”
{% endblock %}
- 子板css
在 模板<stytle></stytle> 下方进行单独block
{% block css %} {% endblock %}
- 子板JS
在 模板<script></script> 下方进行单独block
{% block js %} {% endblock %}
# 子板中block顺序随意
# 一个子板只能有一个模板
- 模板导入include
- 定义tag.htm(放在templates)
- 使用处
{% include 'tag.html' %}
# tag.html 如有模板语言,django回渲染
# 一个页面可以有多个tag
- 内置函数
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
- 自定义函数
simple_tag
a. app下创建templatetags目录
b. 任意xxoo.py文件
c. 创建template对象 register
d.
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.simple_tag
def func(a1,a2,a3....)
return " a1 + a2"
e. settings中注册APP
f. 顶部 {% load xxoo %}
g. {% 函数名 arg1 arg2 %}
# 不能作为if条件
# 参数任意
filter
a. app下创建templatetags目录
b. 任意xxoo.py文件
c. 创建template对象 register
d.
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter
def func(a1,a2)
return "asdfasd"
e. settings中注册APP
f. 顶部 {% load xxoo %}, 若有extend,则extend 在最上面
g. {{ 参数1|函数名:"参数二,参数三" }} {{ '参数1'|函数名:'数字' }}
# 能作为if条件
# 最多两个参数,不能加空格
- admin
# django amdin是django提供的一个后台管理页面,提供完善的html和css,
# 在通过Model创建完数据库表之后,就可以对数据进行增删改查,
# 使用django admin 则需要以下步骤:
- 创建后台管理员
- 配置url
- 注册和配置django admin后台管理页面
1、创建后台管理员
python manage.py createsuperuser
2、配置后台管理url
url(r'^admin/', include(admin.site.urls))
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
from django.contrib import admin
from app01 import models
admin.site.register(models.UserType)
admin.site.register(models.UserInfo)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
b、设置数据表名称
class UserType(models.Model):
name = models.CharField(max_length=50)
class Meta:
verbose_name = '用户类型'
verbose_name_plural = '用户类型'
c、打开表之后,设定默认显示,需要在model中作如下配置
class UserType(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
d、为数据表添加搜索功能
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
search_fields = ('username', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
e、添加快速过滤
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
search_fields = ('username', 'email')
list_filter = ('username', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
更多:http://docs.30c.org/djangobook2/chapter06/
- 常用记录:
# 用户名与密码
<link rel="stylesheet" href="/static/commons.css">
<style>label{width: 80px;text-align: right;display: inline-block;}</style>
<form action="/login/" method="POST">
//urls.py中的r'^login/' / 与此处保持一致#}
<p>
<label for="username">用户名:</label>
<input id='username'name="user" type="text">
</p>
<p>
<label for="password">密码;</label>
<input id='password'name="pwd" type="password" >
<input type="submit"value="提交">
<span style="color: red">{{ error_msg }}</span>
</p>
# 添加框、查看详情、删除
<div>
<form action="/home" method="POST">
<input type="text"name="username"placeholder="用户名">
<input type="text"name="email"placeholder="邮箱">
<input type="text"name="gender"placeholder="性别">
<input type="submit"value="添加">
</form>
</div>
<div>
<table>
{% for row in user_list %}
<tr>
<td>{{ row.username }}</td>
<td>{{ row.email }}</td>
<td>{{ row.gender }}</td>
<td><a href="/detail?nid={{ row.id }}">查看详细</a>|
<a class='del'href="#" row_id="{{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</table>
</div>
<div>
<form action="/del_host"method="POST">
<input style="display: none"id="nid" type="text" name="nid">
<p><input type="submit"></p>
<p><input type="button"></p>
</form>
</div>
<script src="/static/jquery-1.12.4.js"></script>
<script>
$('.del').click(function () {
var row_id = $(this).attr('row_id');
$('#nid').val(row_id)
})
</script>