每天40分玩转Django:实操图片分享社区

实操图片分享社区

一、今日学习内容概述

学习模块 重要程度 主要内容
模型设计 ⭐⭐⭐⭐⭐ 图片/用户模型、关系设计
视图开发 ⭐⭐⭐⭐⭐ 上传/展示/交互功能
用户系统 ⭐⭐⭐⭐⭐ 注册/登录/权限控制
前端交互 ⭐⭐⭐⭐ 界面设计/Ajax操作

二、模型设计

python 复制代码
# models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from PIL import Image
import uuid

def image_upload_path(instance, filename):
    ext = filename.split('.')[-1]
    return f'images/{uuid.uuid4()}.{ext}'

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField('个人简介', max_length=500, blank=True)
    avatar = models.ImageField('头像', upload_to='avatars/', blank=True)
    following = models.ManyToManyField('self', symmetrical=False, related_name='followers')
    
    def __str__(self):
        return f'{self.user.username}的个人资料'

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
    image = models.ImageField('图片', upload_to=image_upload_path)
    caption = models.TextField('描述', max_length=1000)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    likes = models.ManyToManyField(User, related_name='liked_posts', blank=True)
    
    class Meta:
        ordering = ['-created_at']
    
    def __str__(self):
        return f'{self.user.username}的图片 - {self.created_at}'
    
    def get_absolute_url(self):
        return reverse('post_detail', args=[str(self.id)])
    
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        
        # 处理图片大小
        with Image.open(self.image.path) as img:
            if img.height > 1080 or img.width > 1920:
                output_size = (1920, 1080)
                img.thumbnail(output_size)
                img.save(self.image.path)

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    text = models.TextField('评论内容')
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    
    class Meta:
        ordering = ['created_at']

三、视图实现

python 复制代码
# views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.core.paginator import Paginator
from .models import Post, Comment, Profile
from .forms import PostForm, CommentForm

@login_required
def upload_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save()
            return redirect('post_detail', post.id)
    else:
        form = PostForm()
    return render(request, 'posts/post_create.html', {'form': form})

def post_list(request):
    posts_list = Post.objects.select_related('user').prefetch_related('comments')
    paginator = Paginator(posts_list, 12)
    page = request.GET.get('page')
    posts = paginator.get_page(page)
    return render(request, 'posts/post_list.html', {'posts': posts})

def post_detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    comments = post.comments.select_related('user')
    
    if request.method == 'POST':
        comment_form = CommentForm(request.POST)
        if comment_form.is_valid():
            comment = comment_form.save(commit=False)
            comment.post = post
            comment.user = request.user
            comment.save()
            return redirect('post_detail', post_id=post.id)
    else:
        comment_form = CommentForm()
        
    return render(request, 'posts/post_detail.html', {
        'post': post,
        'comments': comments,
        'comment_form': comment_form
    })

@require_POST
@login_required
def like_post(request):
    post_id = request.POST.get('post_id')
    post = get_object_or_404(Post, id=post_id)
    
    if request.user in post.likes.all():
        post.likes.remove(request.user)
        liked = False
    else:
        post.likes.add(request.user)
        liked = True
        
    return JsonResponse({
        'liked': liked,
        'likes_count': post.likes.count()
    })

四、表单设计

python 复制代码
# forms.py
from django import forms
from .models import Post, Comment, Profile

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['image', 'caption']
        widgets = {
            'caption': forms.Textarea(attrs={'rows': 3}),
        }

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['text']
        widgets = {
            'text': forms.Textarea(attrs={
                'rows': 2,
                'placeholder': '写下你的评论...'
            })
        }

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

五、模板实现

html 复制代码
<!-- templates/posts/post_list.html -->
{% extends 'base.html' %}

{% block content %}
<div class="container mt-4">
    <div class="row">
        {% for post in posts %}
            <div class="col-md-4 mb-4">
                <div class="card">
                    <a href="{{ post.get_absolute_url }}">
                        <img src="{{ post.image.url }}" class="card-img-top" alt="{{ post.caption }}">
                    </a>
                    <div class="card-body">
                        <div class="d-flex align-items-center mb-2">
                            <img src="{{ post.user.profile.avatar.url }}" 
                                 class="rounded-circle me-2" 
                                 width="32" height="32">
                            <h6 class="card-title mb-0">{{ post.user.username }}</h6>
                        </div>
                        <p class="card-text text-truncate">{{ post.caption }}</p>
                        <div class="d-flex justify-content-between">
                            <button class="btn btn-sm like-button" 
                                    data-post-id="{{ post.id }}"
                                    data-liked="{{ user in post.likes.all|yesno:'true,false' }}">
                                <i class="fas fa-heart"></i>
                                <span class="likes-count">{{ post.likes.count }}</span>
                            </button>
                            <small class="text-muted">
                                {{ post.created_at|timesince }}前
                            </small>
                        </div>
                    </div>
                </div>
            </div>
        {% endfor %}
    </div>
    
    {% include 'includes/pagination.html' with page=posts %}
</div>
{% endblock %}

<!-- templates/posts/post_detail.html -->
{% extends 'base.html' %}

{% block content %}
<div class="container mt-4">
    <div class="row">
        <div class="col-md-8">
            <img src="{{ post.image.url }}" class="img-fluid">
        </div>
        <div class="col-md-4">
            <div class="card">
                <div class="card-header">
                    <div class="d-flex align-items-center">
                        <img src="{{ post.user.profile.avatar.url }}"
                             class="rounded-circle me-2"
                             width="32" height="32">
                        <h6 class="mb-0">{{ post.user.username }}</h6>
                    </div>
                </div>
                <div class="card-body">
                    <p>{{ post.caption }}</p>
                    <hr>
                    <div class="comments-section">
                        {% for comment in comments %}
                            <div class="comment mb-2">
                                <strong>{{ comment.user.username }}</strong>
                                {{ comment.text }}
                                <small class="text-muted d-block">
                                    {{ comment.created_at|timesince }}前
                                </small>
                            </div>
                        {% endfor %}
                    </div>
                    {% if user.is_authenticated %}
                        <form method="post" class="mt-3">
                            {% csrf_token %}
                            {{ comment_form }}
                            <button type="submit" class="btn btn-primary btn-sm mt-2">
                                发表评论
                            </button>
                        </form>
                    {% endif %}
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

六、流程图

七、JavaScript交互

javascript 复制代码
// static/js/main.js
document.addEventListener('DOMContentLoaded', function() {
    // 图片点赞功能
    document.querySelectorAll('.like-button').forEach(button => {
        button.addEventListener('click', function() {
            const postId = this.dataset.postId;
            const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
            
            fetch('/posts/like/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'X-CSRFToken': csrftoken
                },
                body: `post_id=${postId}`
            })
            .then(response => response.json())
            .then(data => {
                const icon = this.querySelector('i');
                const count = this.querySelector('.likes-count');
                
                if (data.liked) {
                    icon.classList.add('text-danger');
                } else {
                    icon.classList.remove('text-danger');
                }
                count.textContent = data.likes_count;
            });
        });
    });
    
    // 图片上传预览
    const imageInput = document.querySelector('input[type="file"]');
    if (imageInput) {
        imageInput.addEventListener('change', function() {
            const file = this.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    document.querySelector('#preview-image').src = e.target.result;
                }
                reader.readAsDataURL(file);
            }
        });
    }
});

八、常见功能扩展

  1. 图片过滤器
python 复制代码
from PIL import Image, ImageEnhance

def apply_filter(image, filter_name):
    """应用图片滤镜"""
    img = Image.open(image)
    
    if filter_name == 'grayscale':
        return img.convert('L')
    elif filter_name == 'brightness':
        enhancer = ImageEnhance.Brightness(img)
        return enhancer.enhance(1.5)
    # 添加更多滤镜...
    
    return img
  1. 图片标签系统
python 复制代码
class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)
    
    def __str__(self):
        return self.name

class Post(models.Model):
    # ... 其他字段 ...
    tags = models.ManyToManyField(Tag, blank=True)
  1. 收藏功能
python 复制代码
class Collection(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    posts = models.ManyToManyField(Post, related_name='collections')
    name = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)

通过本章学习,你应该能够:

  1. 设计和实现图片分享系统
  2. 处理用户认证和权限
  3. 实现图片上传和处理
  4. 开发社交互动功能

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关推荐
IT古董32 分钟前
【深度学习】常见模型-Transformer模型
人工智能·深度学习·transformer
沐雪架构师1 小时前
AI大模型开发原理篇-2:语言模型雏形之词袋模型
人工智能·语言模型·自然语言处理
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS体育馆管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
python算法(魔法师版)2 小时前
深度学习深度解析:从基础到前沿
人工智能·深度学习
小王子10243 小时前
设计模式Python版 组合模式
python·设计模式·组合模式
kakaZhui3 小时前
【llm对话系统】大模型源码分析之 LLaMA 位置编码 RoPE
人工智能·深度学习·chatgpt·aigc·llama
LUCIAZZZ3 小时前
简单的SQL语句的快速复习
java·数据库·sql
struggle20254 小时前
一个开源 GenBI AI 本地代理(确保本地数据安全),使数据驱动型团队能够与其数据进行互动,生成文本到 SQL、图表、电子表格、报告和 BI
人工智能·深度学习·目标检测·语言模型·自然语言处理·数据挖掘·集成学习
佛州小李哥4 小时前
通过亚马逊云科技Bedrock打造自定义AI智能体Agent(上)
人工智能·科技·ai·语言模型·云计算·aws·亚马逊云科技
Mason Lin4 小时前
2025年1月22日(网络编程 udp)
网络·python·udp