Upload File trong lập trình Website với Python

Nội dung

Bài này sẽ giới thiệu những nội dung sau:

  • Tạo thêm field models để chứa thông tin file ảnh
  • Cách lưu trữ ảnh đã upload
  • Hiển thị ảnh lên trang web

Tạo thêm field models để chứa thông tin file ảnh

Trước tiên, hãy nhớ chuyển DEBUG TRUE để tiếp tục phát triển website.

Bây giờ, Kteam muốn mỗi bài viết sẽ có 1 bức ảnh đại diện mỗi bài, nên Kteam sẽ vào models chỉnh Post thêm field image như sau:

class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    image = models.ImageField(null=True)

    def __str__(self):
        return self.title

Ở đây thì Kteam cho phép field có giá trị null, nguyên nhân là trong các bài trước Kteamđã lỡ tạo 2 bài viết, nếu bây giờ không cho phép null thì sẽ dính lỗi logic vì 2 bài viết trước đó không có ảnh. Nếu không có null thì sẽ hiện lỗi như sau:

Lúc đó, nên chọn 2 thoát ra và chỉnh field mới làm cho phép null.

Lưu ý: Nếu khi chạy makemigrations mà thấy lỗi này thì do thiếu thư viện Pillow, bạn hãy chạy lệnh pip để cài thêm vào.

Sau khi tạo được file migrations, thì dùng lệnh migrate để cập nhật là Database:


Cách lưu trữ ảnh đã upload

Giờ ta thử vô admin, vào post và upload 1 file ảnh lên:

Sau khi upload xong, thử nhấn đường dẫn đến bức ảnh đã upload xem:

Ta sẽ thấy Django sẽ không hiểu được đường dẫn web đó

Giờ ta thử quay lại Project để xem bức ảnh đó ở đâu:

Ta sẽ thấy bức ảnh ngay trong project, có lẽ không nên để bức ảnh lộn xộn như vậy mà nên tập trung vào 1 folder lưu trữ.

Nguyên nhân lỗi ở trên là do Django không thể map đường url bức ảnh và folder chứa ảnh đó. Nhiệm vụ của chúng ta là nên map 2 cái đó lại để Django biết url này nên lấy bức ảnh nào.

  • Bước 1: Kteam sẽ tạo ra 1 folder media để chứa các bức ảnh upload, sau đó move ảnh upload lúc nãy vào folder này
  • Bước 2: Vào settings.py khai báo đường dẫn url media và folder media
  • Bước 3: Ta sẽ map url media và folder media này lại, ta sẽ qua urls.py tổng để khai báo:
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import handler404
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('home.urls')),
    path('blog/', include('blog.urls')),
] 

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

handler404 = 'home.views.error'
  • Đầu tiên là import static và settings.
  • Tiếp theo, ta sẽ kiểm tra xem Project có DEBUG bằng True không, vì ở chế độ DEBUG ta mới cần map giữa url media và folder media. Còn khi deploy lên server, thì web server sẽ chịu trách nhiệm các đường dẫn file ảnh, Django không cần thực hiện cái map này.
  • Nếu DEBUG là Trueurlpatterns sẽ thêm 1 url static, đó là đường dẫn /media/ mà ở đây là giá trị của biến MEDIA_URLfolder static chính là folder media mà mình xử lý ở biến MEDIA_ROOT.

Sau khi restart server, ta thử vào lại đường dẫn hình:

Ta thấy Django đã có đường dẫn /media/ và nó có thể lấy bức ảnh 1.jpg tương ứng đường dẫn /media/1.jpg.

Lưu ý: Nếu upload file trùng tên với một file đã có trong kho lưu trữ thì Django sẽ tự tạo 1 đoạn mã sau để phân biệt, Kteam sẽ upload chung 1 file ở bài viết thứ 2


Hiển thị ảnh lên trang web

Như vậy, sau khi upload xong, Kteam sẽ hiển thị bức ảnh đó ở mỗi bài viết như sau:

  • template post.html:
{% extends "pages/base.html" %}
 
{% block title %}Blog{% endblock %}
 
{% block content %}
{% for post in Posts %}
    <h4>{{post.date|date:"d-m-Y"}}<a href="/redirect?Id=bPkSKQqMZ9erlLi6p21Q4A%3d%3d" url 'post' post.id %}">{{post.title}}</a></h4>
    <img src="{{post.image.url}}" width="500px" height="300px" />
{% endfor %}
{% endblock %}

  • template blog.html:
{% extends "pages/base.html" %}
 
{% block title %}{{post.title}}{% endblock %}
 
{% block content %}
<h3><a href="/redirect?Id=duECimTrtcY%2f9%2fkQF45R8ricuL8rnN1W89bqLQLRmAR%2b2AE1Wuc2%2fsatIaeyTQ2SiSNKPWJ7vem62cw9ZxE2LzZQEtuy6DuaTgL6aoimSYA%3d"
<img src="{{post.image.url}}" width="500px" height="300px" />
<h6>on {{post.date}}</h6>
{{post.body|safe|linebreaks}}
{% endblock %}

Kteam sẽ phải dùng post.image.url để lấy được giá trị đường dẫn url bức ảnh rồi gán mà src của tag img.


Leave a Reply