五、视图层(一)

一、URLconf配置(正向传参)
#### Django如何处理一个请求
当一个用户通过网页发送一个请求给Django网站,Django执行过程如下:
1. 首先访问项目下的settings.py文件中 ROOT_URLCONF = 'test1.urls'
2. 执行项目包下的urls.py文件中的urlpatterns列表
3. 执行应用包下的urls.py文件中的urlpatterns列表
4. 根据匹配的url正则调用相应的视图函数/通用视图
5. 如果没有匹配的正则,将会自动调用Django错误处理页面
#### url函数配置方式
- 方式1
```
#student/urls.py
#coding=utf-8
from django.conf.urls import url
from . import views
urlpatterns=[
    url(r'^query$',views.queryAll)
]
#student/views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def queryAll(request):
    return HttpResponse('hello world')
#访问地址
http://127.0.0.1:8000/student/query

```
- 方式2:位置传参
```
#student/urls.py
#coding=utf-8
from django.conf.urls import url
from . import views
urlpatterns=[
    url(r'^query$',views.queryAll),
    url(r'^query/(d{2})$',views.queryAll),
]

#student/views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def queryAll(request,sno):
    print sno
    return HttpResponse('hello world')

#访问地址
http://127.0.0.1:8000/student/query/12
```
- 方式3:关键字传参
```
urlpatterns=[
    url(r'^query$',views.queryAll),
    url(r'^query/(d{2})$',views.queryAll),
    url(r'^query/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.queryAll),
]

def queryAll(request,year,day,month):
    print year,month,day
    return HttpResponse('hello world')

#访问地址
http://127.0.0.1:8000/student/query/2008/10/12/   
```
- 方式4:加载其他映射文件
```
from django.conf.urls import include, url
urlpatterns = [
    
    url(r'^community/', include('aggregator.urls')),
]
```
- 方式5:传参(参数名必须保持一致)
```
urlpatterns=[
    url(r'^query$',views.queryAll),
    url(r'^query/(d{2})$',views.queryAll),
    url(r'^query/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.queryAll),
    url(r'^query/(?P<num1>d{3})/$',views.queryAll,{'hello':'123'}),
]
 
def queryAll(request,num1,hello):
    print num1,hello
    return HttpResponse('hello world')
   
#访问地址  
http://127.0.0.1:8000/student/query/888/
```
 
二、URLConf配置 (反向传参)
#### 逆向解析(防止硬编码)
```
方式一
‘’‘’‘
#student/urls.py
from django.conf.urls import url
from . import views
urlpatterns=[
    url(r'^query$',views.queryAll),
    url(r'^query/(d{2})$',views.queryAll),
    url(r'^query/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.queryAll),
    url(r'^query/(?P<num1>d{3})/$',views.queryAll,{'hello':'123'}),
    url(r'^query1/([0-9]{4})/$', views.queryAll, name='hello'),
    url(r'^$', views.index_view),
]
#student/views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def queryAll(request,num1):
    print num1
    return HttpResponse('hello world')
#通过模板页面逆向访问
def index_view(request):
    return render(request,'index.html')
#通过Python代码逆向访问
def index_view(request):
    # return render(request,'index.html')
    return HttpResponseRedirect(reverse('hello',args=(2018,)))
    
#templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="{% url 'hello' 2008 %}">访问</a>
</body>
</html>
 
```
  方式2
```
#项目包/urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^student/', include('student.urls',namespace='stu',app_name='student')),
]
#应用包/urls.py
#coding=utf-8
from django.conf.urls import url
from . import views
urlpatterns=[
    url(r'^$', views.Index.as_view()),
    url(r'^query2/',views.Login.as_view(),name='login')
]

#应用包/views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
 

from django.views import View
class Index(View):
    def get(self,request):
        return render(request,'index.html')

class Login(View):
    def get(self,request):
        return HttpResponse('hello')

#templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="{% url 'stu:login' %}">访问</a>
</body>
</html>

```
 三、文件上传
#### Django文件上传
#### 需求
1. 完成学生信息注册操作
2. 将学生信息入库
3. 将上传文件存放至项目下media文件夹下
4. 显示所有学生信息
#### 创建模型类
```
class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    photo = models.ImageField(upload_to='imgs')
    class Meta:
        db_table = 't_stu'
    def __unicode__(self):
   
        return u'Student:%s'%self.sname

```
 
#### settings.py文件中文件上传相关设置
```
INSTALLED_APPS = [
    ...
    'stu'
]
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
 
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
```
#### 映射数据库表
```
#在终端中敲命令
python manage.py makemigrations stu
python manage.py migrate

```

#### 配置URL
- test13/urls.py
```
#coding=utf-8
from django.conf.urls import url, include
from django.contrib import admin
from test13.settings import DEBUG, MEDIA_ROOT
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^stu/', include('stu.urls')),
]
#配置路由读取后台上传文件
from django.views.static import serve
if DEBUG:
    urlpatterns+=url(r'^media/(?P<path>.*)/$', serve, {"document_root": MEDIA_ROOT}),

```
- stu/urls.py
```
#coding=utf-8
from django.conf.urls import url
import views
urlpatterns=[
    url(r'^$',views.index_view),
    url(r'^upload1/$',views.upload1_view),
    url(r'^showall/$',views.showall_view),
]
```
#### 创建视图
- stu/views.py
```
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
# Create your views here.
from stu.models import Student
#显示注册页面
def index_view(request):
    return render(request,'index.html')
     
#django文件上传
def upload1_view(request):
    #1.获取请求参数
    sname = request.POST.get('sname')
    photo = request.FILES.get('photo')
    #2.插入数据库
    stu = Student.objects.create(sname=sname,photo=photo)
    #3.判断是否注册成功
    if stu:
        return HttpResponse('注册成功!')
    return HttpResponseRedirect('/stu/')
#显示所有学生信息
def showall_view(request):
    #查询所有学生信息
    stus = Student.objects.all()
    return render(request,'show.html',{'stus':stus})  

```

#### 创建模板
- templates/index.html
```
    <form action="/stu/upload1/" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p>
            <label for="sname">姓名:</label><input type="text" name="sname" id="sname"/>
        </p>
        <p>
            <label for="photo">头像:</label><input type="file" name="photo" id="photo"/>
        </p>
        <p>
            &emsp;&emsp;<input type="submit" value="注册" />
        </p>
    </form>
```
- templates/show.html
```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        img{
            200px;
        }
    </style>
</head>
<body>
    <table border="1" width="500px" cellspacing="0">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>头像</th>
            <th>操作</th>
        </tr>
        {% for stu in stus %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ stu.sname }}</td>
                <td><img src="{{ MEDIA_URL }}{{ stu.photo }}"/></td>
                <td>操作</td>
            </tr>

        {% endfor %}

    </table>
</body>
</html>
```
#### 头像读取相关settings.py文件中的设置
```
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',
                'django.template.context_processors.media'#配置这句话
            ],
        },
    },
]
```
 
四、文件下载
 
#### 配置URL
```
#coding=utf-8
from django.conf.urls import url
from . import views
urlpatterns=[
    url(r'^$', views.Index.as_view()),
    url(r'^stulist/$', views.StuList.as_view()),
    url(r'^download/$', views.Download.as_view()),
]
```

#### 创建视图
```
class Download(View):
    def get(self,request):
        #获取文件存放位置
        filepath = request.GET.get('photo','')
        #获取文件名
        filename = filepath[filepath.rindex('/')+1:]
        #获取文件绝对路径
        path =  os.path.join(os.getcwd(),'media',filepath.replace('/','\'))
        with open(path,'rb') as fr:
            response = HttpResponse(fr.read())
            response['Content-Type']='image/png'
            #预览模式
            response['Content-Disposition']='inline;filename='+filename
            #附件模式
            # response['Content-Disposition']='attachment;filename='+filename
        return response
```
 
#### 文件名中文情况
```
from django.utils.encoding import escape_uri_path
response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name))

```
 
 
原文地址:https://www.cnblogs.com/dangjingwei/p/12872034.html