Django|第一部
Django
· Django流程
· Django url
· Django view
· Django form
①:Django流程介绍
MTV模式
注明的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起.
模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求.
注: 什么是松耦合:简单的说,松耦合是一个 重要的保证互换性的软件开发方法.
Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
②:Django URL
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。URL的家在是从配置文件中开始。
参数说明:
· 一个正则表达式字符串
· 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
· 可选的要传递给视图函数的默认参数(字典形式)
· 一个可选的name参数
下面是一个示例URLconf:
from django.conf.urls import url from . import views urlpatterns = [
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),
]
注释:
· To capture a value from the URL, just put parenthesis around it.
(从URL中捕获值,只是把它周围的括号。)
- There’s no need to add a leading slash, because every URL has that. For example, it’s
^articles
, not^/articles
.
(没有必要添加一个领先的削减,因为每个URL。例如,它的^的文章,而不是^ /文章。)
· The 'r' in front of each regular expression string is optional but recommended. It tells Python that a string is “raw” – that nothing in the string should be escaped. See Dive Into Python’s explanation.
(每个正则表达式字符串前面的'R'是可选的,但建议。它告诉Python字符串是“原始” - 没有什么字符串中应该进行转义。见深入Python的解释。)
Example requests:
· A request to /articles/2005/03/
would match the third entry in the list. Django would call the functionviews.month_archive(request, '2005', '03')
.
(请求/文章/ 2005/03 /匹配列表中的第三项,Django的将调用函数views.monthly存档(要求下,'2005','03')。)
· /articles/2005/3/ would not match any URL patterns, because the third entry in the list requires two digits for the month.
(/文章/ 2005/3 /不匹配任何URL模式,因为第三个条目列表中需要两个数字的月. .)
· /articles/2003/
would match the first pattern in the list, not the second one, because the patterns are tested in order, and the first one is the first test to pass. Feel free to exploit the ordering to insert special cases like this. Here, Django would call the function views.special_case_2003(request)
(/文章/ 2003 /将匹配第一个模式列表中,没有第二个,因为模式是为了进行测试.第一个是第一个测试通过,随时利用顺序插入这样的特殊情况,这里,Django所说的功能的观点。特殊情况2003(请求))
· /articles/2003 would not match any of these patterns, because each pattern requires that the URL end with a slash.
(/文章/ 2003不匹配任何这些模式,因为每个模式要求以斜线结尾的URL。)
· /articles/2003/03/03/
would match the final pattern. Django would call the functionviews.article_detail(request, '2003', '03', '03')
.
(/文章/ 2003/03/03 /将最终的模式相匹配,Django将调用函数views.article细节(的要求,'2003','03','03')。)
Named groups
· The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.
(上面的例子中使用简单,non-named正则表达式组(通过括号)捕捉到的URL,将他们作为一个视图的位置参数。在更高级的用法,可以使用指定的正则表达式组捕获的URL)
· In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern)
, where name
is the name of the group and pattern
is some pattern to match.
(在Python正则表达式,命名正则表达式组的语法是(?P <名>的模式),其中name是组的名称和模式是某种模式相匹配。)
· Here’s the above example URLconf, rewritten to use named groups:
(下面是上面的例子中的URLconf,改写使用命名组:)
import re ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo') print(ret.group())
print(ret.group('id'))
print(ret.group('name'))
正则知识
from django.conf.urls import url from . import views urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments. For example:
(这完成了前面的例子一样,有一个微妙的差异:捕获的值传递给视图函数作为关键字参数而不是位置参数。例如:)
A request to /articles/2005/03/ would call the function views.month_archive(request, year='2005',month='03'), instead of views.month_archive(request, '2005', '03').
(的请求/用品/ 2005/03/会调用函数views.monthly存档(要求,今年='2005',一个月='03'),而不是views.monthly存档(要求下,'2005','03')。)
A request to /articles/2003/03/03/
would call the function views.article_detail(request, year='2003',month='03', day='03')
.
(请求/文章/ 2003/03/03 /将调用该函数的观点。文章细节(请求,年= ' 2003 ',月=“03”,天=“03”)。)
In practice, this means your URLconfs are slightly more explicit and less prone to argument-order bugs – and you can reorder the arguments in your views’ function definitions. Of course, these benefits come at the cost of brevity; some developers find the named-group syntax ugly and too verbose.
(在实践中,这意味着你的URLconf稍微更明确,不容易参数顺序错误 - 你可以在你的意见'函数定义重新排序的参数。当然,这些优点来在简短的费用;一些开发商找到命名组的语法丑陋,太冗长。)
常见写法实列:
Captured arguments are always strings:
Each captured argument is sent to the view as a plain Python string, regardless of what sort of match the regular expression makes. For example, in this URLconf line:
(每个捕获的参数发送到视图作为普通的Python字符串,无论什么样的匹配正则表达式做。例如,在该URL配置行:)
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
...the year
argument passed to views.year_archive()
will be a string,
(…参数传递给视图。年存档()将是一个字符串,)
not an integer, even though the [0-9]{4}
will only match integer strings.
(不是整数,即使[0-9]{4}将只匹配整数串。)
Including other URLconfs :
At any point, your urlpatterns
can “include” other URLconf modules. This essentially “roots” a set of URLs below other ones.
(在任何时候,您的网址模式可以“包含”其他的URLconf模块。这实质上是“根”的一套低于其他的网址。)
For example, here’s an excerpt of the URLconf for the Django website itself. It includes a number of other URLconfs:
(例如,这里的URL配置为Django的网站本身的摘录。它包括许多其他URL配置的:)
from django.conf.urls import include, url urlpatterns = [
# ... snip ...
url(r'^community/', include('django_website.aggregator.urls')),
url(r'^contact/', include('django_website.contact.urls')),
# ... snip ...
]
Passing extra options to view functions:
URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.
(URLconf中有一个挂钩,可以传递额外的参数给您的视图功能,作为一个Python字典。)
The django.conf.urls.url()
function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.
(该django.conf.urls.url()函数可以接受这应该是额外的参数的字典传递给视图功能可选的第三个参数。)
For example:
from django.conf.urls import url
from . import views urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year='2005',foo='bar').
(在本例中,请求/博客/ 2005 / Django将调用视图。年存档(请求,年= ' 2005 ',foo = '参数')。)
This technique is used in the syndication framework to pass metadata and options to views.
(这种技术用于聚合框架通过元数据和视图选项。)
Dealing with conflicts
( 应对冲突)
It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.
(可以有一个URL模式捕获关键字参数,并通过参数具有相同名字的字典的额外参数。当这种情况发生时,将使用参数在字典里而不是参数捕获)
需要注意的是,当你加上参数时,对应函数views.index必须加上一个参数,参数名也必须命名为a,如下:
if auth(): obj=model.user.filter() {'obj':obj}
应用
name param
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=='':
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> #######################
name的应用
Django views
http请求中产生两个核心对象:
http请求:HttpRequest对象
- http响应:HttpResponse对象
# 获取提交方式
request.method
if request.method == "POST":
times = time.time()
return render(request,'index.html') # 获取前端post提交的数据
request.POST.get('username') # 获取域名后路径
get_full_path()
例:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
HttpRequest对象
def test(request):
# 往前端写入字符串
return HttpResponse("xxx")
# 跳转路径
return redirect('/index/') # 渲染HTML文件两种方式
return render(reuqest, "test.html")
return render_to_response('text.html') # 可以直接将函数中所有的变量传给模板
return render(reuqest, "test.html",locals()) # 可以根据通过字典的方式往前端传值,取值输入key即可
return render(reuqest, "test.html",{'shijie':'你好'})
HttpResponse对象
# 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支持时该属性才可用。
参数
Django Form
一、基础form提交
比如写一个计算 a和 b 之间的简单应用,网页上这么写.
<!DOCTYPE html>
<html>
<body>
<p>请输入两个数字</p> <form action="/add/" method="POST"><input type="text" name="a"> <input type="text" name="b">
<input type="submit" value="提交">
</form>
</body>
</html>
HTML
把这些代码保存成一个index.html,放在 templates 文件夹中。
网页的值传到服务器是通过 <input> 或 <textarea>标签中的 name 属性来传递的,在服务器端这么接收:
from django.http import HttpResponse
from django.shortcuts import render def index(request):
return render(request, 'index.html') def add(request):
a = request.POST.GET('a')
b = request.POST.GET('b')
a = int(a)
b = int(b)
return HttpResponse(str(a+b)
服务器端
但是,比如用户输入的不是数字,而是字母,就出错了,还有就是提交后再回来已经输入的数据也会没了。
那么,当然如果我们手动将输入之后的数据在 views 中都获取到再传递到网页,这样是可行的,但是很不方便,所以 Django 提供了更简单易用的 forms 来解决验证等这一系列的问题。
二、Django Forms应用
1、简单案例一
在app01下新建一个文件forms.py
from django import forms class AddForm(forms.Form):
a = forms.IntegerField()
b = forms.IntegerField()
forms.py
(视图函数) views.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.shortcuts import render,HttpResponse
from app01.forms import AddForm def index(request):
if request.method == 'POST':# 当提交表单时
# form 包含提交的数据
form = AddForm(request.POST)
# 如果提交的数据合法
if form.is_valid():
a = form.cleaned_data['a']
b = form.cleaned_data['b']
return HttpResponse(str(int(a) + int(b)))
# 当正常访问时
else:
form = AddForm()
return render(request, 'index.html', {'form': form})
views.py
对应的模板文件 index.html
<form method='post'>
{% csrf_token %}
{{ form }}
<input type="submit" value="提交">
</form>
index.html
这个简单的案例,大家不知道有没有看出其中的蹊跷呢,仔细观察,form类给我做了验证,用户输入错了会弹出报错信息
2丶简单案例二
from django.db import models # Create your models here. class BookType(models.Model):
caption = models.CharField(max_length=64) #最大长度 class Book(models.Model):
name = models.CharField(max_length=64) #最大长度
pages = models.IntegerField()
price = models.DecimalField(max_digits=10,decimal_places=2)
pubdate = models.DateField()
book_type = models.ForeignKey('BookType') #当然min_length --最小长度
models.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.shortcuts import render
from app01.forms import Form1 def form1(request):
if request.method == 'POST':
# 获取请求内容做验证
f = Form1(request.POST)
if f.is_valid():
print(f.cleaned_data)
else:
print(type(f.errors),f.errors)
return render(request,'form1.html',{'error':f.errors,'form':f})
else:
f = Form1()
return render(request,'form1.html',{'form':f})
views.py
在app01下新建一个文件forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*- from django import forms
from app01 import models class Form1(forms.Form):
# 用户名,给该标签添加一个class属性,还有空值的报错信息修改
user = forms.CharField(
widget=forms.TextInput(attrs={'class': 'c1'}),
error_messages={'required': '用户名不能为空'},) # 密码定义最大长度和最小长度
pwd = forms.CharField(max_length=4,min_length=2)
# 邮箱定义错误信息,required为空值错误信息,invalid为邮箱匹配错误信息
email = forms.EmailField(error_messages={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'})
# 生成多行文本编辑框
memo = forms.CharField(widget=forms.Textarea()) # 下拉菜单实时更新数据库
user_type_choice = models.BookType.objects.values_list('id','caption')
book_type = forms.CharField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class': "form-control"})) def __init__(self,*args, **kwargs):
super(Form1, self).__init__(*args, **kwargs)
self.fields['book_type'] = forms.CharField(
widget=forms.widgets.Select(choices=models.BookType.objects.values_list('id','caption'),attrs={'class': "form-control"}))
forms.py
HTML页面(form1.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.input-group{
position: relative;
padding: 20px;
width: 250px;
}
.input-group input{
width: 200px;
display: inline-block;
}
.input-group span{
display: inline-block;
position: absolute;
height: 12px;
font-size: 8px;
border: 1px solid red;
background-color: darksalmon;
color: white;
top: 41px;
left: 20px;
width: 202px;
}
</style>
</head>
<body> <form action="/form1/" method="post"> <div class="input-group">
{{ form.user }}
{% if error.user.0 %}
<span>{{ error.user.0 }}</span>
{% endif %}
</div>
<div class="input-group">
{{ form.pwd }}
{% if error.pwd.0 %}
<span>{{ error.pwd.0 }}</span>
{% endif %}
</div>
<div class="input-group">
{{ form.email }}
{% if error.email.0 %}
<span>{{ error.email.0 }}</span>
{% endif %}
</div>
<div class="input-group">
{{ form.memo }}
{% if error.memo.0 %}
<span>{{ error.memo.0 }}</span>
{% endif %}
</div>
<div class="input-group">
{{ form.book_type }}
{% if error.book_type.0 %}
<span>{{ error.book_type.0 }}</span>
{% endif %}
</div> <div>
<input type="submit" value="提交">
</div>
</form> </body>
</html>
form1.html
Django|第一部的更多相关文章
- Django知识(二)
上一部链接 django入门全套(第一部) 本章内容 Django model Model 基础配置 django默认支持sqlite,mysql, oracle,postgresql数据库. < ...
- 实战Django:官方实例Part1
[写在前面] 撰写这个实战系列的Django文章,是很久之前就有的想法,问题是手头实例太少,一旦开讲,恐有"无米下锅"之忧. 随着对Django学习的深入,渐渐有了些心得,把这些心 ...
- 转一篇:文档笔记之Django QuerySet
这个放着,说不定以后作一些更深入的查询时,用得着的. http://www.rapospectre.com/blog/7/ 今天刚刚答完辩体完检就跑来更新博客了!!! 先补上第一篇: 一般情况下,我们 ...
- django 配置URLconf和获取值
django中正确配置url匹配找到视图: 1 在项目下的settings.py中ROOT_URLCONF = "项目名.urls" 表示 前台发来请求会先去项目下的test3/u ...
- python框架之Django(10)-Form组件
介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来.与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入 ...
- 【转】django 与 vue 的完美结合 实现前后端的分离开发之后在整合
https://blog.csdn.net/guan__ye/article/details/80451318 最近接到一个任务,就是用django后端,前段用vue,做一个普通的简单系统,我就是 ...
- Django学习笔记之Django QuerySet的方法
一般情况下,我们在写Django项目需要操作QuerySet时一些常用的方法已经满足我们日常大多数需求,比如get.filter.exclude.delete神马的感觉就已经无所不能了,但随着项目但业 ...
- Django Query
Making Qeries 一旦创建了数据模型,Django就会自动为您提供一个数据库抽象API,允许您创建.检索.更新和删除对象.本文档解释了如何使用这个API. The models 一个clas ...
- python框架django中结合vue进行前后端分离
一:创建django项目 1.django-admin startproject mysite # 创建mysite项目 2.django-admin startapp app01# 创建app01应 ...
随机推荐
- HDU-1754-I Hate It(线段树,简单,不过好像有点问题)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1754 题目不难,不过开始我犯了一个低级错误,输入n,m,m代表操作的数目,我没有写了,写代码的时候,就 ...
- NSArray和NSSet的区别
NSSet到底什么类型? 其实它和NSArray功能性质一样,用于存储对象,属于集合: NSSet , NSMutableSet类声明编程接口对象,无序的集合,在内存中存储方式是不连续的 像NSAr ...
- Canvas arcTo绘制圆弧
arcTo(x1,y1,x2,y2,r); 当前点x0,y0;圆弧与(x0,y0-x1,y1)相切,与(x1,y1-x2,y2)相切: <!DOCTYPE html> <html l ...
- Android项目实战(二十九):酒店预定日期选择
先看需求效果图: 几个需求点: 1.显示当月以及下个月的日历 (可自行拓展更多月份) 2.首次点击选择"开始日期",再次点击选择"结束日期" (1).如果&qu ...
- XCode中设置字体大小
XCode中设置字体大小 1)打开Preferences,快捷键是“Command + ,”(注意,是三个键,按住command键,然后再快速地按“+”和“,”两个键即可) 2)选择“Fonts &a ...
- BZOJ-2768: [JLOI2010]冠军调查(超级裸的最小割)
2768: [JLOI2010]冠军调查 Time Limit: 10 Sec Memory Limit: 128 MB Description 一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段.随着 ...
- npm 不是内部命令
最近办公室流行给电脑装win10系统,于是在重新装好电脑系统后,再次运行thinkjs项目的时候,就发现了之前做过的项目打不开了,待再确认问题出在哪里的时候,才发现”nodejs以及npm不是内部或者 ...
- Python单元测试——深入理解unittest
单元测试的重要性就不多说了,可恶的是python中有太多的单元测试框架和工具,什么unittest, testtools, subunit, coverage, testrepository, nos ...
- 欢迎来到Devil_lixu的技术博客
Welcome to my blog 如果你觉得内容对你还有一点点的帮助,那就果断点赞吧^_^
- 转:微信开发获取地理位置实例(java,非常详细,附工程源码)
微信开发获取地理位置实例(java,非常详细,附工程源码) 在本篇博客之前,博主已经写了4篇关于微信相关文章,其中三篇是本文基础: 1.微信开发之入门教程,该文章详细讲解了企业号体验号免费申请与一 ...