整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          掌握Django文件處理:一步步構建上傳功能

          掌握Django文件處理:一步步構建上傳功能

          建模型

          首先先進入我們的testsite項目下,打開members/models.py文件,先添加我們保存文件的數據模型:

          class Document(models.Model):
              name=models.CharField(max_length=255)
              file=models.FileField(upload_to='uploads/')  # 'uploads/' 是文件上傳的相對路徑
              uploaded_at=models.DateTimeField(auto_now_add=True)

          這里的文件存儲目錄可以自定義我們需要存儲文件的目錄,也可以在我們的 env文件 做配置,這里直接讀取相應的配置 env字段 就可以了。

          進入testsite根目錄執行更新遷移文件命令,這一步前面有說到,是為了更新遷移文件,

          py manage.py makemigrations

          可以看到我們的migrations目錄增加了新的遷移文件

          執行遷移

          py manage.py migrate

          我們新增加的文件模型表就在數據庫生成好了。

          使用模型

          進入testsite/members目錄,新增form.py表單文件,這里會定義文件上傳的字段。

          from django import forms
          from .models import Document
          
          class UploadFileForm(forms.ModelForm):
              class Meta:
                  model=Document
                  fields=['name', 'file']  # 包含你想要用戶填寫的字段

          接下來將上傳的文件綁定到表單中,打開testsite/members/views.py視圖文件:

          from .forms import UploadFileForm #需要我們引入上一步建立好的表單文件
          
          def upload_file(request):
              if request.method=="POST":
                  form=UploadFileForm(request.POST, request.FILES)
                  if form.is_valid():
                      form.save()  # 保存表單數據到數據庫
                      return HttpResponse("上傳成功")
              else:
                  form=UploadFileForm()
              return render(request, "polls/upload.html", {"form": form})
          

          我們傳遞request.FILES 到表單的構造函數;這就是文件數據綁定到表單的方式。

          請注意,request.FILES僅當請求方法為POST,實際發送了至少一個文件字段且<form>表單有發送請求的并且具有enctype="multipart/form-data"屬性時。否則request.FILES將為空。

          最后一步,添加上傳頁面,進入members/templates/members目錄,新增upload.html文件,注意跟我們的視圖里面指向的文件名保持一致。

          <form method="post" enctype="multipart/form-data">
              {% csrf_token %}
              {{ form.as_p }}
              <button type="submit">提交</button>
          </form>

          打開地址http://127.0.0.1:8000/polls/upload/進入文件上傳頁面

          點寫完表單點擊提交

          這個時候我們的文件上傳就完成了,可以打開我們的testsite目錄,進入我們設置的uploads目錄,就看到我們上傳好的文件:

          在這里插入圖片描述

          然后我們再打開數據庫,進入模型對應的members_document表,也可以看到文件上傳生成的數據。

          在這里插入圖片描述

          批量上傳

          為了使用一個表單字段上傳多個文件,創建該字段的子類并將其allow_multiple_selected類屬性設置為True

          進入表單文件forms.py

          class MultipleFileInput(forms.ClearableFileInput):
              allow_multiple_selected=True
          
          class MultipleFileField(forms.FileField):
              def __init__(self, *args, **kwargs):
                  kwargs.setdefault("widget", MultipleFileInput())
                  super().__init__(*args, **kwargs)
          
              def clean(self, data, initial=None):
                  single_file_clean=super().clean
                  if isinstance(data, (list, tuple)):
                      result=[single_file_clean(d, initial) for d in data]
                  else:
                      result=[single_file_clean(data, initial)]
                  return result
          
          
          class FileFieldForm(forms.Form):
              file_field=MultipleFileField()

          然后進入view.py視圖文件重寫子類form_valid()的方法 FormView來處理多個文件上傳:

          from .forms import FileFieldForm  # 確保導入正確的表單定義
          from .models import Document  # 引入Document模型
          def batch_upload_view(request):
              if request.method=='POST':
                  form=FileFieldForm(request.POST, request.FILES)
                  if form.is_valid():
                      # 獲取表單中title的值
                      title=form.cleaned_data['title']
                      # 處理文件上傳
                      for file in request.FILES.getlist('file_field'):
                          document=Document(file=file, name=title)  # 假設title作為文件的名稱或描述
                          document.save()
          
                  return HttpResponse("上傳成功")
              else:
                  # 請求方法為GET時,初始化表單
                  form=FileFieldForm()
          
              return render(request, "polls/uploads.html", {"form": form})

          假如你不想使用模型關聯上傳,則使用如下方式:

          from django.core.files.storage import default_storage
          #使用默認存儲引擎保存文件
          file_name=default_storage.save(file.name, file)

          然后重新渲染我們的批量上傳頁面,跟我們的forms django表單關聯

          <form method="post" enctype="multipart/form-data"> <!-- enctype 必須為 multipart/form-data 以支持文件上傳 -->
              {% csrf_token %} <!-- Django表單必須的安全令牌 -->
              {{ form.title }} 
              {{ form.file_field }} <!-- 渲染文件上傳字段,MultipleFileField將會生成相應的input元素 -->
          
              <button type="submit">上傳文件</button>
          </form>

          上面的 csrf_token django表單必須的安全令牌,form.file_field 也是我們form.py定義的批量上傳字段。

          打開members/urls.py,添加我們的路由

          path('uploads/', views.batch_upload_view, name='upload'),

          我們的批量上傳功能就已經寫好了,我們打開http://127.0.0.1:8000/polls/uploads/頁面

          填好表單,批量選擇文件,點擊上傳,這里我只是演示,沒有做頁面渲染樣式與字段驗證,感興趣的小伙伴可以加上自己喜歡的樣式。

          然后進入我們的數據庫可以看到我們與上傳模型的記錄被添加

          我們打開uploads目錄,也可以看到我們上傳好的文件。

          需要注意的是在保存上傳的文件之前,數據需要存儲在某個地方。

          默認情況下,如果上傳的文件小于 2.5 MBdjango 會將上傳的全部內容保存在內存中。

          這意味著保存文件僅涉及從內存讀取和寫入磁盤,因此速度非常快。

          但是,如果上傳的文件太大,django 會將上傳的文件寫入存儲在系統臨時目錄中的臨時文件。

          例如/tmp/tmpzfp6I6.upload。如果上傳的文件足夠大,您可以看到該文件的大小隨著 django 將數據傳輸到磁盤而增長

          總結

          文件上傳算是一種很常見的需求,幾乎構建很多項目系統,以及插件都需要用到。

          通過上面例子可以看到django通過forms表單的形式靈活定義文件上傳的頁面,字段,以及數據庫存儲。

          在實際項目中我們還要考慮到安全性,包括檢查文件大小(可通過FileFieldmax_length屬性設置)、防止路徑遍歷攻擊。

          還需注意服務器端的驗證,比如檢查文件類型、內容安全等。

          例子里面有提到,djangoFileSystemStorageDefaultStorage類提供了基本的文件存儲管理。

          自定義存儲后端可以提供更多靈活性,如自定義文件命名規則、存儲路徑等,以避免文件名沖突和優化組織結構。

          大量文件上傳或下載也會影響應用性能。最好采用云存儲服務、內容分發網絡(CDN)、以及對靜態和媒體文件的有效緩存策略,可以顯著提升用戶體驗。

          對于我們本地的存儲策略,需要考慮上傳文件的生命周期管理,包括舊文件的定期清理策略,以避免無限制增長占用存儲空間。


          – 歡迎點贊、關注、轉發、收藏【我碼玄黃】,gonghao同名

          道Django某一個功能的用途,比單純地知道怎么用更有用。

          今天我們要學習的內容是Django的頁面跳轉,重點講的是使用url里的name參數

          一、給url設置name屬性

          1. 我想修改路徑名

          根據前面做好的web項目,登錄頁面的url為: http://127.0.0.1:8000/login/;如果我們想把路徑名login換成signin,該怎么做呢? 這時候我們就想到了在urls的urlpatterns里直接修改path路徑名,

          2. 遇到麻煩了

          如果views里對應的方法有重定向跳轉就麻煩了,因為重定向跳轉的redirect方法里已經寫了我們改名之前的路徑名。如果我們在url里將login改成signin,做了一次改名操作了,那么在views里我們還要再改一次。如果有很多個頁面都做了重定向到login頁面,我們就需要對每一個函數進行修改操作,太麻煩了!有沒有什么辦法能讓我們做路徑修改的時候,只需要改一處就能搞定的呢?

          3. 解決方法:利用name屬性

          實際上Django給我們提供了URL的name屬性用來標記url,我們可以在path中給指定路徑設置一個name屬性,

          urlpatterns = [
              path('signin/', app01_views.login, name="login"),
          ]

          在views中做重定向時不直接寫死路徑名,而是通過reverse('屬性名')反向查出前面的url,這樣修改路徑名就很方便了,直接修改path就可以了。

          return redirect(reverse('login'))

          通常情況下,我們是根據path里的路徑名,找到views里的方法,然后渲染頁面。而這里的重定向反轉操作是根據路徑名的name屬性,反向找到路徑的名稱。 這樣我們需要修改路徑名的時候,views里都不要動的,反正它找的是指定的名稱。name屬性規定好了之后,url路徑名想怎么改就怎么改。

          注意:使用反轉路徑名的方法,需要導入包from django.shortcuts import reverse。

          4. 如何使用URL的name屬性

          當前階段我們主要用在兩處: 在View中使用redirect(reverse("login"))

          def index(request):
              username = request.GET.get('username')
              if username:
                  return render(request,'index.html')
              else:
                  return redirect(reverse('login'))

          在html中使用模板語言{% url 'login' %}

          <a href="{% url 'login'%}">登錄</a>

          5. 調用url的name時傳遞參數

          我們先復習一下url傳值的兩種常見方法:

          (1)直接使用url傳值

          以傳遞電影編號movie_id為例,如果想通過url傳值。在定義path的時候,使用path("movile_detail/<movie_id>",...),然后在views里定義方法來接收movie_id這個值,就定義成def movie_id(request,movie_id),瀏覽器中訪問的時候可以通過127.0.0.1:8000/movie_detail/8001就能把movie_id作為參數通過url傳過去。

          (2)使用查詢字符串傳值

          我們還是以傳遞電影編號為例,如果想通過url傳值。在定義path時,使用path("movie_detail/",...),在views里定義方法來接收就寫成

          def movie_id(request):
                  movie_id = request.GET.get(movie_id)

          在瀏覽器中訪問是,url需要輸入127.0.0.1:8000/?movie_id=8001。這樣也能完成url的傳值。

          (3)傳遞參數

          在views中,我們使用redirect重定向到一個新的url如果要傳遞參數該怎么辦呢? 有兩種方式:

          • 方式一: 使用tuple傳參數,args=(''rico', '123')
          • 方式二: 使用dict傳參數,kwargs={'username': 'rico', 'password': '123'}

          url設置如下:

          urlpatterns = [
              # 登錄url
              path('login/<username>/<password>',app01_views.login, name='login'),
          ]

          在views里定義login方法準備接收兩個參數:

          def login(request, username, password):
              return HttpResponse("用戶名:%s \t 密碼:%s" % (username, password))

          傳遞參數時:

          def index(request):
              username = request.GET.get('username')
              if username:
                  return HttpResponse('=== 這是首頁 ===')
              else:
                  return redirect(reverse('login', kwargs={'username': 'rico', 'password': '123'}))

          注意:是在reverse方法里添加參數,傳的如果是元組則注意前后順序,如果是字典就不用考慮前后順序。

          如果要在templates中通過模板語言調用url的名稱, 模板語言里使用url傳遞參數可以寫成這樣:

          {% url 'login' username='xiaoyu' password='123' %}

          二、多app環境下URL的命名

          在多app項目中,如果各自的name屬性相同,在重定向訪問的時候會出現無法訪問指定app下的url的問題。這時候我們就在各自app的urls中添加命名空間

          app_name = 'app01'

          然后在重定向訪問指定url名稱的時候,添加命名空間屬性即可。

          def index(request):
              username = request.GET.get('username')
              if username:
                  return render(request, 'app01/index.html')
              else:
                  return redirect(reverse('app01:login'))

          注意:項目總體url配置使用include關鍵字,將多個app配置到總路由中。

          urlpatterns = [
              path('admin/', admin.site.urls),
              path('app01/', include('app01.urls')),
              path('app02/',include('app02.urls')),
          ]

          最后

          這一節,我們主要介紹了Django中url路由跳轉的進階知識,下一節,我們將介紹Django下html頁面中的模板語言DTL,感謝大家的閱讀~


          主站蜘蛛池模板: 欧美日韩精品一区二区在线观看 | 亚洲一区AV无码少妇电影| 精品无码一区二区三区爱欲| 国产福利无码一区在线| 99久久国产精品免费一区二区| 一区二区中文字幕| 亚洲av区一区二区三| 亚洲午夜一区二区三区| 红桃AV一区二区三区在线无码AV| 精品无码国产一区二区三区51安| 国产成人精品一区二区三区免费| 日韩美女在线观看一区| 亚洲一区二区三区高清视频| 亚洲国产av一区二区三区| 国产一区二区好的精华液| 国产麻豆精品一区二区三区v视界| 国产综合无码一区二区色蜜蜜 | 日韩毛片一区视频免费| 91在线一区二区| 日本精品高清一区二区| 国产免费av一区二区三区| 在线精品视频一区二区| 一区二区三区在线免费看| 中文字幕一区二区三区四区| 国产乱子伦一区二区三区| 无码人妻精品一区二区蜜桃网站 | 农村乱人伦一区二区| 中文字幕一区二区三区日韩精品| 国产精品日韩一区二区三区| 国产日韩一区二区三区| 日产精品久久久一区二区| 亚洲色大成网站www永久一区| 视频一区视频二区日韩专区| 精品国产亚洲第一区二区三区| av无码免费一区二区三区| 亚洲爆乳精品无码一区二区三区| 成人免费区一区二区三区| 中文字幕一区二区三区在线播放 | 日本一区二区三区四区视频| 中文字幕人妻第一区| 国产经典一区二区三区蜜芽|