【Django框架】项目框架、视图层(view.py)、URL映射(urls.py )和APP的模板层(index.html)

运行Django项目:

  1. 通过命令行的方式: python manage.py runserver 。在本地浏览器 http://127.0.0.1:8000/  来访问自己写的网站啦。
  2. 如果想要修改端口号,在运行的时候可以指定端口号, python manage.py runserver 9000 这样就可以通过 9000 端口来访问啦。另外,这样运行的项目只能在本机上能访问。
  3. 如果想要在其他电脑上也能访问本网站,那么需要指定 ip 地址为 0.0.0.0 。终端运行示例为: python manage.py runserver 0.0.0.0:8000 。pycharm运行,右上角项目配置修改,如下:

        

   4. 通过 pycharm 运行。直接点击右上角的绿色箭头按钮即可运行。

注意:其他电脑必须和该电脑的iP在同一个局域网,也就是能ping通;且要关闭自己电脑的防火墙。除此之外,还要设置ALLOWED_HOSTS:这里设置为本机的ip

 ALLOWED_HOSTS是为了限定请求中的host值,以防止黑客构造包来发送请求。只有在列表中的host才能访问。 

如果设置为*,则所有网址都可以访问。

 

Django项目中project和app的关系:

appdjango 项目的组成部分。一个app 代表项目中的一个模块,所有 URL 请求的响应都是 由 app 来处理。比如豆瓣,里面有图书,电影,音乐,同城等许许多多的模块,如果站 在 django 的角度来看,图书,电影这些模块就是 app ,图书,电影这些app 共同组成豆瓣这个 项目。因此这里要有一个概念,django 项目由许多app组成,一个app 可以被用到其他项目,django 也能拥有不同的 app

 

项目结构:

  • manage.py :以后和项目交互基本上都是基于这个文件。一般都是在终端输入 python manage.py [子命令] 。可以输入 python manage.py help 看下能做什么事情,一般情况下不要随便编辑这个文件。
  • settings.py :本项目的设置项,以后所有和项目相关的配置都是放在这个里面。
  • urls.py :这个文件是用来配置URL路由的。比如访问 http://127.0.0.1/news/ 是访问新闻 列表页,这些东西就需要在这个文件中完成。
  • wsgi.py :项目与 WSGI 协议兼容的 web 服务器入口,部署的时候需要用到的,一般情况下也是不需要修改的。
  • APP下的index.thml:主要包含前端显示和处理的代码:h5(主要包含前端的显示代码,如:div块、链接、table表格等)和js(用于处理前端后端交互时,前端的一下处理,如:查询、填写页面数据、按钮触发、Ajax请求处理等)
  • APP下的models.py:这个模块就比较简单、主要是用来定义项目所涉及的数据库中表名和各字段类型,限制等。
  • APP下视图层view.py:这个模块是用来定义后端处理的函数:如:后端查询数据库、详情页面请求数据、新增、删除后端处理等等。

 

Django项目执行流程:

index.html为前端显示的页面,里面包含用户处理的操作:如查询、新增、删除等等,当用户触发页面的操作按钮时,系统会去urls.py里找路由(route),在urls.py匹配到对应的路径后,就会去view.py执行后端代码(后端的函数里的参数时前端操作时带过来的),执行完后端的操作,前端再接收,完成相应的前端处理。

 

详解urls.py、index.thml、models.py及view.py

一. view.py

  • 视图一般都写在 app views.py 中。并且视图里所有函数的第一个参数永远且必须是 request (一个 HttpRequest)对象。这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息 等。
  • 在视图中,一般是完成逻辑相关的操作。比如这个请求是添加一篇博客,那么可以通过 request来接收到这些数据,然后存储到数据库中,最后再把执行的结果返回给浏览器。视图函数的返回结果必须是 HttpResponseBase 对象或者子类的对象。
  • 我们常用的HttpResponseBase对象或者子类对象有:JsonResponse HttpResponse,其中HttpResponse是用的最多的子类;JsonResponse继承了HttpResponse对象并进行二次封装。

1、view.py里的render方法、HttpResponse方法、JsonResponse方法

  • render:可接收三个参数,一是request参数,二是待渲染的html模板文件,三是保存具体数据的字典参数。它的作用就是将数据填充进模板文件,最后把结果返回给浏览器。
  • HttpResponse:它是作用是内部传入一个字符串参数,然后发给浏览器,不能渲染html。 (如果是Ajax请求,建议永远让服务器返回一个字典(return HttpResponse(json.dumps(字典)),可以修改返回的数据类型(如前面那个json.dumps就是修改返回类型),比较适合返回图片,视频,音频等二进制文件。
return HttpResponse(json.dumps(result), content_type="application/json")

#其中result是需要处理的字典键值对

return HttpResponse("请求路径:{}".format(request.path))
#也可以设置固定返回数据
  • JsonResponse:是HttpResponse的子类,内部强制做了json转换,所以返回的一定是json,同时也支持了list的输出
return JsonResponse(result, safe=False)

return JsonResponse('{"result": "删除成功"}', safe=False)

三、视图层request对象:

1. Request对象简单实例

# views.py
from django.http import HttpResponse
def index(request):
    return HttpResponse("Hello world")

# urls.py
from django.urls import re_path
from . import views
app_name = "Myapp"
urlpatterns = [
    re_path(r'^index/$', views.index, name='index'),
]

因为我们本例种不需要使用数据库,所以不需要创建模型(models)。当你访问http: // 127.0.0.1:8000 / index / 你就应该能看到hello world字样。因为这里的index函数其实是没有用到request的参数的,所以在编辑器里面就是灰色的。

2. 现在我们将视图函数稍微改下,使用request变量打印出请求路径。

 # views.py 
from django.http import HttpResponse 
def index(request):     
    return HttpResponse("请求路径:{}".format(request.path))

3. Request对象方法和属性

(1)request.method:获取请求方法(e.g.GET, POST).

(2)request.GET or request.POST:获取GET or POST请求参数,字典形式。

(3)request.POST.get('name', default=None):获取POST请求参数

(4)request.GET.getlist('name', default=None): 获取GET参数列表

(5)request.META:包含当前HTTP请求的Headers头部信息, 字典形式。键值KEY  都是大写。如:request.META['REMOTE_ADDR']可获取用户远程IP地址。

(6)request.user:获取当前访问用户的所有信息。

(7)request.path:获取当前访问路径

4. 常用Request.META属性

是一个Python字典,包含了所有本次HTTP请求的Header信息,常用属性包括: REQUEST_METHOD: 当前请求方法, GET或POST

(1)request.META.get('HTTP_USER_AGENT', 'unknown'): 用户浏览器的字符串, 比如Mozilla / 5.0(WindowsNT10.0;Win64;x64) AppleWebKit / 537.36。防止抛出错误异常。

(2)REMOTE_ADDR:客户端IP地址,比如54.489.10201

(3)PATH_INFO: 当前路径信息,如"/index", 等同于request.path

(4)如果想要知道META的所有属性,可以在view.py里写一个函数:

def index(request):
        values = request.META.items()
        html = []
         for k, v in values:
              html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))
        return HttpResponse('<table>%s</table>' % '\n'.join(html))

5.完整的例子

# urls.py app级别的url
from django.urls import re_path
from . import views
app_name = "request_demo"
urlpatterns = [
    re_path(r'^index/$', views.index, name='index'),
]

# views.py  这里就是系统的后端的实现
from django.shortcuts import render
def index(request):
    user = request.user
    user_agent = request.META.get('HTTP_USER_AGENT', 'unknown')
    ip = request.META['REMOTE_ADDR']
    context = {'user': user, 'user_agent': user_agent, 'ip': ip, }
    return render(request, "request_demo/index.html", context)

# MyApp/index.html
{% block content %}
<h3>MyApp</h3>
<ul>
    <li>User: {{ user }}</li>
    <li>User_Agent: {{ user_agent }}</li>
    <li>IP Address: {{ ip }}</li>
</ul>
{% endblock %}

理解:view.py里面的user,user_agent和ip都来自index.html;而index.html的这些数据是用户一旦点击该页面,系统自动获取到的。

二. index.html

  • 前端界h5代码和JS前端请求处理函数等,都存放在HTML里
  • 下面这段h5代码,实现删除界面
    <!--    删除模态框-->
    <div class="modal fade" id="delete-modal" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">删除</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <p>是否删除?</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                    <button type="button" id="delete-btn" class="btn btn-danger">删除</button>
                </div>
            </div>
        </div>
    </div>
  • 下面这段JS代码是实现:点击删除模态框,实现删除功能
$("#delete-modal").on('show.bs.modal', function (event) {
    var btnThis = $(event.relatedTarget); //触发事件的按钮
    var currentDataId = btnThis.closest('tr').find('td').eq(0).text();//获取某一列的内容eq后面表示列数\

    $("#delete-btn").on('click',function() {
        $.ajax({
            url: "{% url 'mysite:delete' %}"+"?usrNm="+"{{usr_Nm}}"+"&usrId="+"{{usr_Id}}",
            type: "POST",
            data: {'IIID': currentDataId, csrfmiddlewaretoken: '{{ csrf_token }}'},
            dataType: "JSON",
            success:function (data) {
                $('#delete-modal').modal('hide');
                toastr.success(JSON.parse(data)['result']);
                oTable.draw(false);
            }
        })
    });
});

// 关闭删除模态框时,解绑事件
$('#delete-modal').on('hide.bs.modal', function () {
    $('#delete-btn').off('click');
});

三. models.py

models.py路径在:APP下,主要用于存放数据库信息,定义表名和字段名及类型,Meta是给这个类起的表名。

下面是其中一张表及字段名的定义

from django.db import models


class Bugs(models.Model):
    filedagainst = models.CharField(db_column='filedAgainst', max_length=100, blank=True, null=True)  # Field name made lowercase.
    plannedfor = models.CharField(db_column='plannedFor', max_length=100, blank=True, null=True)  # Field name made lowercase.
    parentworkitemid = models.CharField(db_column='parentWorkitemId', max_length=100, blank=True, null=True)  # Field name made lowercase.
    workitemid = models.CharField(db_column='workItemId', primary_key=True, max_length=100)  # Field name made lowercase.
    summary = models.CharField(max_length=2000, blank=True, null=True)
    description = models.CharField(max_length=2000, blank=True, null=True)
    discover = models.CharField(max_length=100, blank=True, null=True)
    resolvedby = models.CharField(db_column='resolvedBy', max_length=100, blank=True, null=True)  # Field name made lowercase.
    defecttype = models.CharField(db_column='defectType', max_length=100, blank=True, null=True)  # Field name made lowercase.
    creationdate = models.DateTimeField(db_column='creationDate', blank=True, null=True)  # Field name made lowercase.
    status = models.CharField(max_length=100, blank=True, null=True)
    severity = models.CharField(max_length=100, blank=True, null=True)
    update_time = models.DateTimeField(blank=True, null=True)
    bug_file = models.CharField(max_length=300, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'bugs'

四、urls.py:

专门用于与视图函数view.py映射的,如果来了一个请求,就会从这个文件中找到匹配的视图函数。

在一个网站,比如个人信息存放的页面:/profile;新闻列表页存放的页面路径是:/list;详情页面是:/content

这些信息都是在urls.py配置的;

1.  视图写完后,要与URL进行映射,在 urls.py 文件中有一个 urlpatterns 变量,该变量在url文件中是一个url映射列表。

2.  在用户输入了某个 url ,请求到我们的网站的时候,django 会在项目的urls.py文件中,遍历urlpatterns列表来查找对应的处理函数(视图)。当url有重复的情况则以找到的第一个为准,成功匹配后,就会执行该url后面的path方法,也就是用户可以看到的页面;如果匹配不成功则会报错。

3. Urlpatterns常用函数:pathurl

1. URL嵌套:

在一个项目中,通常不会只有一个app,如果把所有的 app 的 views 中的视图都放在 urls.py 中进行映射,会让代码显得非常乱。因此 django 给我们提供了一个方法,可以在 app 内部包含自己的 url 匹配规则,而在项目的 urls.py 中再统一包含这个 app 的 urls 。使用这个技术需要借助 include 函数。

  • URL分为项目URL和app的URL
  • 我们一般定义的都会放在app的url里,然后把整个app的url放到项目的url中进行路由

下面是项目级别的url

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'', include('mysite.urls')),
    url(r'^admin/', admin.site.urls),
]

下面是app级别的url:二级路由

from django.conf.urls import url
from django.views import static
from django.conf import settings
from . import views

app_name = 'mysite'

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^add-ol-issue$', views.add_ol_issue, name='addolissue'),
    url(r'^search$', views.search, name='search'),
    url(r'^search2$', views.search2, name='search2'),
    url(r'get_project$', views.get_project, name="get_project"),
    url(r'^filldata$', views.filldata, name='filldata'),
    url(r'delete$', views.delete, name='delete'),
    url(r'^edit_online_page$', views.edit_online_page, name='edit_online_page'),
    url(r'^tr_filldata$', views.tr_filldata, name='tr_filldata'),
    url(r'^upload$', views.import_excel, name='upload'),
    url(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static'),
    url(r'^version$', views.version, name='version')
]

2.URL映射

假设后端view.py的有filldata函数,其路由流程为:

# View.py详情页面请求数据

def filldata(request):
    if request.is_ajax():  # filldata
        onlineproblem_id= int(request.POST['IIID'])
        content = OnlineProblem.objects.filter(id=onlineproblem_id)
        result = serializers.serialize("json", content)
        return JsonResponse(result, safe=False)
url函数:
# urls.py详情页面请求数据(^:从字符串开头进行匹配,$:从字符串末尾进行匹配)
from django.conf.urls import url
from django.views import static
from django.conf import settings
from . import views  
#从当前路径导入view,也可以用from app import views(app是自己定义的)
app_name = 'mysite'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^add-ol-issue$', views.add_ol_issue, name='addolissue'),
    url(r'^search$', views.search, name='search'),
    url(r'^filldata$', views.filldata, name='filldata')]

3.urls.py中urlpatterns中path函数、re_path函数和url函数

django1.x版本的from django.conf.urls import url,include,用url的路由:url()写的是正则表达式(regex)的路由

Django2.x版本的from django.urls import path, re_path, include用path和re_path路由:path()写的是非正则路由(route)

(1)django1.x中的url:

函数传递了四个参数,两个必需:regexview,以及两个可选:kwargs,和name。也就是正则表达式和视图是两个必填参数。

from django.conf.urls import url
from django.views import static
from django.conf import settings
from . import views

app_name = 'mysite'

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^add-ol-issue$', views.add_ol_issue, name='addolissue'),
    url(r'^search$', views.search, name='search'),
    url(r'^search2$', views.search2, name='search2'),
    url(r'get_project$', views.get_project, name="get_project"),
    url(r'^filldata$', views.filldata, name='filldata'),
    url(r'delete$', views.delete, name='delete'),
    url(r'^edit_online_page$', views.edit_online_page, name='edit_online_page'),
    url(r'^tr_filldata$', views.tr_filldata, name='tr_filldata'),
    url(r'^upload$', views.import_excel, name='upload'),
    url(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static'),
    url(r'^version$', views.version, name='version')
]

(2)Django2.1的path函数

 path()函数 具有四个参数,两个必须参数:route 和 view,两个可选参数:kwargs 和 name。即路由和视图是必填参数。

path()的route参数:

例如,URLconf在处理请求https://www.example.com/myapp/时,它会尝试匹配myapp/。处理请求https://www.example.com/myapp/?page=3 时,也只会尝试匹配 myapp/。

path()的view参数:

当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个HttpRequest对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入。

# 项目的url,路径为Myproject/urls.py 项目级别的中括号之前有,
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
 path('admin/', admin.site.urls),
 path('book/',include("book.urls")),]
# app为book的url,book/urls.py文件:以后在请求 book 相关的url
的时候都需要加一个 book 的前缀。App级别的中括号之前没有,
from django.urls import path
from . import views
urlpatterns = [
 path('list/',views.book_list),
 path('detail/<book_id>/',views.book_detail)]

带参数的url的入参值,是从view.py后端代码里获取的:

def peopleList(request,book_id)

第一个request是默认的,那么路径自动匹配该函数的第二个形参,匹配格式:<int:book_id>,并返回一个正整数或零值。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值