当前位置: 首页 > article >正文

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

实操图片分享社区

一、今日学习内容概述

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

二、模型设计

# 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']

三、视图实现

# 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()
    })

四、表单设计

# 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']

五、模板实现

<!-- 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交互

// 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. 图片过滤器
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. 图片标签系统
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. 收藏功能
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大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!


http://www.kler.cn/a/450815.html

相关文章:

  • 【时间之外】IT人求职和创业应知【74】-运维机器人
  • 如何完全剔除对Eureka的依赖,报错Cannot execute request on any known server
  • http协议的状态码
  • 注意力机制详解
  • 密码学期末考试笔记
  • 用 gdbserver 调试 arm-linux 上的 AWTK 应用程序
  • css 编写注意-1-命名约定
  • selenium执行js
  • 2024年12月CCF-GESP编程能力等级认证Python编程四级真题解析
  • sqoop抽数报错Every derived table must have its own alias
  • 最长正则括号序列算法详解
  • ElementUI 的 form 表单校验
  • 深度学习——神经网络中前向传播、反向传播与梯度计算原理
  • 计算机网络B重修班-期末复习
  • 《探索PyTorch计算机视觉:原理、应用与实践》
  • 【数据可视化案列】白葡萄酒质量数据的EDA可视化分析
  • uniapp实现获取用户定位信息、手机号信息、蓝牙、设备、相册、相机、声音等,请你完善展示所有信息
  • 用VBA将word文档处理成支持弹出式注释的epub文档可用的html内容
  • Docker Compose 安装 Harbor
  • vue3标签中的ref属性如何使用$refs获取元素
  • postman关联接口用于登录(验证码会变情况)
  • QT:QLabel的LED透明跑马灯
  • 《信管通低代码信息管理系统开发平台》Linux环境安装说明
  • es 3期 第18节-分页查询使用避坑的一些事
  • UML 建模实验
  • 全国硕士研究生入学考试(考研)择校择专业之择校主要因素