Django 圖片上傳功能完整代碼解析

更新日期: 2024 年 12 月 16 日

Django 提供了內建的 User 模型來管理用戶相關的資訊。

不過,若需要擴展更多自定義的用戶資料,如個人簡介和頭像,則可以透過建立一個與 User 關聯的 Profile 模型來實現。

本篇將為新手提供完整的邏輯與實作一覽概念,而不僅僅專注於代碼細節。


建立 Profile 模型

首先,新增一個 Profile 模型,作為 User 模型的擴展,儲存額外的用戶資料。

from django.contrib.auth.models import User
from django.db import models

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    photo = models.ImageField(upload_to='profile_photos/', blank=True, null=True)
    bio = models.TextField(max_length=500, blank=True)

    def __str__(self):
        return f"{self.user.username}'s Profile"

關鍵點

  • 使用 OneToOneFieldProfileUser 模型關聯。
  • 定義 photobio 欄位,允許存儲個人頭像和簡介資訊。

自動建立與更新 Profile

為了讓每個新建的 User 都能自動創建對應的 Profile,可以使用 Django 的 signals

設定 Signals

新增一個 signals.py 檔案來處理自動建立與更新 Profile 的邏輯。

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

載入 Signals

確保在應用的 apps.py 中載入該檔案。

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app'

    def ready(self):
        import your_app.signals

管理後台的 Profile

讓管理者能方便地在後台檢視與編輯 Profile 資料。

from django.contrib import admin
from .models import Profile

@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
    list_display = ('user', 'bio', 'photo')

用戶資料更新功能

建立用戶更新表單與對應的視圖,讓用戶能在前端頁面更新其個人資料。

建立表單

forms.py 中新增兩個表單類別,分別用於更新 UserProfile 資料。

from django import forms
from django.contrib.auth.models import User
from .models import Profile

class UserUpdateForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']

class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['photo', 'bio']

建立視圖

views.py 中新增處理用戶資料更新的邏輯。

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import UserUpdateForm, ProfileUpdateForm

@login_required
def profile(request):
    if request.method == 'POST':
        user_form = UserUpdateForm(request.POST, instance=request.user)
        profile_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            return redirect('profile')
    else:
        user_form = UserUpdateForm(instance=request.user)
        profile_form = ProfileUpdateForm(instance=request.user.profile)

    context = {
        'user_form': user_form,
        'profile_form': profile_form
    }
    return render(request, 'users/profile.html', context)

設計模板

templates/users/profile.html 中建立表單介面。

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <div>
        <h3>更新用戶資料</h3>
        {{ user_form.as_p }}
    </div>
    <div>
        <h3>更新個人資料</h3>
        {{ profile_form.as_p }}
    </div>
    <button type="submit">更新</button>
</form>

新增路由

urls.py 中設定對應的路徑。

from django.urls import path
from . import views

urlpatterns = [
    path('profile/', views.profile, name='profile'),
]

支援媒體檔案上傳

配置 settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

配置 URL 設定

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

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

測試與驗證

  1. 執行資料庫遷移: python manage.py makemigrations python manage.py migrate
  2. 啟動開發伺服器並登入: python manage.py runserver
  3. 訪問 http://127.0.0.1:8000/profile/,測試用戶資料更新功能。

結語

以上的實現展示了如何以清晰的邏輯擴展 Django 的 User 模型,並建立完善的 Profile 管理功能。這不僅增強了應用的靈活性,也為未來的功能擴展提供了堅實的基礎。

Similar Posts