Python之路Day19-Django(二)

本节内容概要:

一、路由系统URL

二、视图

三、模板

四、ORM操作

问题1:Django请求生命周期

-> URL对应关系(匹配) -> 视图函数 -> 返回用户字符串
-> URL对应关系(匹配) -> 视图函数 -> 打开一个HTML文件,读取内容

问题2:创建Django project

django-admin  startproject xxx

cd xxx

python manage.py startapp CMDB

创建项目的所有步骤

    1. 创建Django工程
django-admin startproject 工程名 2. 创建APP
cd 工程名
python manage.py startapp cmdb 3、静态文件
project.settings.py STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
) 4、模板路径 DIRS ==> [os.path.join(BASE_DIR,'templates'),] 5、settings中 middlerware # 注释 csrf 6、定义路由规则
url.py "login" --> 函数名 7、定义视图函数
app下views.py def func(request):
# request.method GET / POST # http://127.0.0.1:8009/home?nid=123&name=alex
# request.GET.get('',None) # 获取请求发来的而数据 # request.POST.get('',None) # return HttpResponse("字符串")
# return render(request, "HTML模板的路径")
# return redirect('/只能填URL') 8、模板渲染
特殊的模板语言 -- {{ 变量名 }} 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 <html>
..
<body>
<div>{{current_user}}</div> <ul>
{% for row in user_list %} {% if row == "alex" %}
<li>{{ row }}</li>
{% endif %} {% endfor %}
</ul> </body> </html> #####索引#################
def func(request):
return render(request, "index.html", {
'current_user': "alex",
'user_list': ['alex','eric'],
'user_dict': {'k1': 'v1', 'k2': 'v2'}}) index.html <html>
..
<body>
<div>{{current_user}}</div> <a> {{ user_list.1 }} </a>
<a> {{ user_dict.k1 }} </a>
<a> {{ user_dict.k2 }} </a> </body> </html> ###### 条件 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 <html>
..
<body>
<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 %}
</body> </html>

所有步骤

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

一、路由系统URL

1.三种方式

1、url(r'^index/', views.index),
url(r'^home/', views.Home.as_view()),
2、url(r'^detail-(\d+).html', views.detail),
3、url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)

ps:

def detail(request, *args,**kwargs):
pass

实战:

1.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)

2.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)

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

多级路由

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),
]

默认值

命名空间

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

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

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

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

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

通过反射机制,为django开发一套动态的路由系统Demo: 点击下载

二、视图

1、获取用户请求数据

request.GET
request.POST
request.FILES

PS:
GET:获取数据
POST:提交数据
2、checkbox等多选的内容

request.POST.getlist()

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()

4、FBV & CBV
function base view

url.py
index -> 函数名

view.py
def 函数(request):
...

====》
/index/ -> 函数名
/index/ -> 类
====》
建议:两者都用
5、装饰器

三、ORM

1.mysql和ORM对应示例

select * from tb where id > 1
# 对应关系
models.tb.objects.filter(id__gt=1)
models.tb.objects.filter(id=1)
models.tb.objects.filter(id__lt=1)

1.根据类自动创建数据库表

创建类

a. 先写类

找到models.py:

from django.db import models

class UserInfo(models.Model):
# id列,自增,主键
# 用户名列,字符串类型,指定长度
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)

找到如下添加最后一行:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]

执行命令

python manage.py makemigrations 
python manage.py migrate 

现在已经创建了一个表:app01_userinfo

提示:如果你不是用的默认数据库那么你需要找到setting.py的DATABASE更改其内容

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}

# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

Django默认使用MySQLdb模块链接MySQL
主动修改为pymysql,在project同名文件夹下的__init__文件中添加如下代码即可:

import pymysql
pymysql.install_as_MySQLdb() 
3. 根据类对数据库表中的数据进行各种操作
def  orm(request):
    # 创建
# models.UserInfo.objects.create(username='root',password='123') # dic = {'username': 'eric', 'password': '666'}
# models.UserInfo.objects.create(**dic) # obj = models.UserInfo(username='alex',password='123')
# obj.save() # 查
# result = models.UserInfo.objects.all()
# result = models.UserInfo.objects.filter(username='root',password='123')
#
# result,QuerySet => Django => []
# [obj(id,username,password),obj(id,username,password), obj(id,username,password)]
# for row in result:
# print(row.id,row.username,row.password)
# print(result) # 删除
# models.UserInfo.objects.filter(username="alex").delete() # 更新
# models.UserInfo.objects.filter(id=3).update(password="69") return HttpResponse('orm')

进阶操作

 # 获取个数
#
# models.Tb1.objects.filter(name='seven').count() # 大于,小于
#
# models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
# models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
# models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in
#
# models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
# models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains
#
# models.Tb1.objects.filter(name__contains="ven")
# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
# models.Tb1.objects.exclude(name__icontains="ven") # range
#
# models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似
#
# startswith,istartswith, endswith, iendswith, # order by
#
# models.Tb1.objects.filter(name='seven').order_by('id') # asc
# models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset
#
# models.Tb1.objects.all()[10:20] # group by
from django.db.models import Count, Min, Max, Sum
# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

  • 创建数据库,设计表结构和字段
  • 使用 MySQLdb 来连接数据库,并编写数据访问层代码
  • 业务逻辑层去调用数据访问层执行数据库操作
import MySQLdb

def GetList(sql):
db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchall()
db.close()
return data def GetSingle(sql):
db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchone()
db.close()
return data

django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

  PHP:activerecord

  Java:Hibernate

  C#:Entity Framework

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

1、创建Model,之后可以根据Model来创建数据库表

from django.db import models

class userinfo(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField 图片
24、models.FilePathField 文件

更多字段

null
default
primary_key
db_column
db_index
unique
unique_for_date
unique_for_month
unique_for_year
choices
auto_now
auto_now_add
blank
verbose_name
editable
error_messages
help_text
validators

参数

class UserInfo(models.Model):
user = models.CharField(max_length=12)
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True) class Meta:
# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
db_table = "table_name" # 联合索引
index_together = [
["pub_date", "deadline"],
] # 联合唯一索引
unique_together = (("driver", "restaurant"),)

元信息

字段参数

            null               -> db是否可以为空
default -> 默认值
primary_key -> 主键
db_column -> 列名
db_index -> 索引
unique -> 唯一索引
unique_for_date ->
unique_for_month
unique_for_year
auto_now -> 创建时,自动生成时间
auto_now_add -> 更新时,自动更新为当前时间 # obj = UserGroup.objects.filter(id=1).update(caption='CEO')
# obj = UserGroup.objects.filter(id=1).first()
# obj.caption = "CEO"
# obj.save() choices -> django admin中显示下拉框,避免连表查询
blank -> django admin是否可以为空
verbose_name -> django admin显示字段中文
editable -> django admin是否可以被编辑
error_messages -> 错误信息欠
help_text -> django admin提示
validators -> django form ,自定义错误信息(欠)

.未完待续

上一篇:[Linux] 查看系统启动时间


下一篇:【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)