【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>,並返回一個正整數或零值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章