
Stable-Diffusion-V1-5 项目实战从零搭建个人AI艺术画廊网站你是不是也经常被AI生成的精美画作惊艳到然后默默保存到手机相册里时间一长就找不到了或者看着别人分享的AI艺术作品心里痒痒的也想自己动手生成却不知道从何开始今天我们就来解决这个问题。我将带你从零开始搭建一个属于你自己的AI艺术画廊网站。这个网站不仅能让你随时随地调用强大的Stable Diffusion模型生成画作还能把你的作品都整理在一个漂亮的画廊里甚至可以和朋友们分享、交流。整个过程我们会用到Python、JavaScript、MySQL这些主流技术并且把模型部署在云端确保生成速度。听起来有点复杂别担心我会用最直白的方式一步步拆解给你看。1. 项目蓝图你的画廊网站长什么样在动手写代码之前我们得先想清楚这个网站到底要做什么。一个完整的AI艺术画廊核心功能其实就围绕三件事生成、展示、互动。生成是起点。用户输入一段文字描述比如“一只戴着宇航员头盔的橘猫在月球表面看地球赛博朋克风格”网站后端就去调用Stable Diffusion模型把这段文字变成一张图片。展示是关键。生成的图片不能看一眼就没了。我们需要一个个人画廊像博物馆一样把所有的作品分门别类地陈列出来。你可以按风格、按时间、按喜好来整理。互动是灵魂。艺术需要交流。你的朋友来到你的画廊可以给喜欢的作品点赞留下评论甚至可能激发你新的创作灵感。基于这三点我们的网站架构就清晰了。前端也就是用户直接看到的网页部分我们用React来构建因为它灵活、高效能做出体验很好的交互界面。后端负责处理业务逻辑、调用AI模型、存取数据我们用Python的Django框架它功能全面能帮我们快速搭建起稳固的后台。数据比如用户信息、作品详情、评论内容就存在MySQL数据库里。而最核心的AI绘画能力我们通过API的方式调用部署在云端GPU服务器上的Stable Diffusion V1.5模型。整个项目的流程大概是这样的你在网页前端输入描述词点击生成前端把这个请求发给Django后端Django后端再调用云端的Stable Diffusion APIAPI生成图片后把图片地址返回给DjangoDjango把图片保存下来并把作品信息存入MySQL最后前端收到成功消息并在画廊页面刷新展示出你的新作品。接下来我们就从环境准备开始一步步把这个蓝图变成现实。2. 环境搭建与项目初始化工欲善其事必先利其器。我们先来把开发环境和项目架子搭好。2.1 后端环境准备Django首先确保你的电脑上安装了Python建议3.8以上版本和pip。然后我们创建一个独立的虚拟环境这样项目的依赖包不会互相干扰。打开你的终端或命令提示符执行以下命令# 创建项目目录并进入 mkdir ai_art_gallery cd ai_art_gallery # 创建Python虚拟环境 python -m venv venv # 激活虚拟环境 # 在Windows上 venv\Scripts\activate # 在MacOS/Linux上 source venv/bin/activate # 安装Django和必要的库 pip install django pip install requests # 用于调用API pip install pillow # 用于处理图片 pip install mysqlclient # 用于连接MySQL安装可能需系统依赖详情见其文档虚拟环境激活后你的命令行前面通常会显示(venv)表示你正在这个环境里工作。接下来创建我们的Django项目和应用# 创建Django项目项目名就叫 gallery_backend django-admin startproject gallery_backend . # 注意末尾的 . 号表示在当前目录创建 # 创建一个应用负责核心的业务逻辑比如作品、用户 python manage.py startapp gallery现在你的目录结构应该类似这样ai_art_gallery/ ├── venv/ ├── manage.py ├── gallery_backend/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── gallery/ ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py └── views.py2.2 前端环境准备React我们使用Create React App这个官方工具来快速初始化前端项目。确保你安装了Node.js建议16以上版本和npm。在ai_art_gallery目录下再打开一个新的终端窗口记得不要关闭后端的那个执行# 创建前端项目目录名为 frontend npx create-react-app frontend cd frontend # 安装一些我们需要的额外库 npm install axios # 用于向后端发送请求 npm install react-router-dom # 用于前端页面路由 npm install mui/material emotion/react emotion/styled # 使用Material-UI组件库让界面更美观创建完成后前端项目的结构就准备好了。2.3 数据库准备MySQL你需要安装并运行一个MySQL数据库。可以从MySQL官网下载安装包或者使用Docker等工具快速启动一个MySQL服务。安装好后登录MySQL创建一个给本项目用的数据库CREATE DATABASE ai_art_gallery CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;记住你设置的数据库名、用户名和密码稍后需要在Django配置里填写。3. 核心功能实现让网站“活”起来环境准备好了现在我们开始实现最核心的三个功能用户系统、AI生成图片、画廊展示。3.1 设计数据模型Models数据是应用的基石。我们打开后端的gallery/models.py文件定义几个核心的数据表。from django.db import models from django.contrib.auth.models import User import uuid import os def artwork_image_path(instance, filename): # 上传图片的路径artworks/年/月/唯一文件名 ext filename.split(.)[-1] filename f{uuid.uuid4()}.{ext} return os.path.join(artworks, filename) class Artwork(models.Model): # 作品模型 title models.CharField(max_length200) # 作品标题 prompt models.TextField() # 生成时用的提示词 image models.ImageField(upload_toartwork_image_path) # 生成的图片 style models.CharField(max_length100, blankTrue) # 风格标签如“赛博朋克” created_at models.DateTimeField(auto_now_addTrue) # 创建时间 author models.ForeignKey(User, on_deletemodels.CASCADE, related_nameartworks) # 作者关联用户 def __str__(self): return self.title class Comment(models.Model): # 评论模型 artwork models.ForeignKey(Artwork, on_deletemodels.CASCADE, related_namecomments) # 属于哪个作品 author models.ForeignKey(User, on_deletemodels.CASCADE) # 评论者 content models.TextField() # 评论内容 created_at models.DateTimeField(auto_now_addTrue) # 评论时间 def __str__(self): return fComment by {self.author} on {self.artwork.title} class Like(models.Model): # 点赞模型 artwork models.ForeignKey(Artwork, on_deletemodels.CASCADE, related_namelikes) user models.ForeignKey(User, on_deletemodels.CASCADE) created_at models.DateTimeField(auto_now_addTrue) class Meta: unique_together (artwork, user) # 确保一个用户对同一个作品只能点一次赞 def __str__(self): return f{self.user.username} likes {self.artwork.title}定义好模型后需要让Django知道它们。在gallery_backend/settings.py文件的INSTALLED_APPS列表里添加我们的应用gallery。然后配置数据库连接还是在settings.py里DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: ai_art_gallery, # 你的数据库名 USER: your_username, # 你的MySQL用户名 PASSWORD: your_password,# 你的MySQL密码 HOST: localhost, # 数据库地址本地就是localhost PORT: 3306, # 端口默认3306 } }最后在终端后端虚拟环境已激活运行以下命令让Django根据模型创建数据库表python manage.py makemigrations gallery python manage.py migrate3.2 集成Stable Diffusion APIViews这是最激动人心的部分——让网站拥有AI绘画的能力。我们假设你已经在一个云GPU服务比如星图上部署好了Stable Diffusion V1.5的API服务并获得了API的调用地址例如https://your-sd-api.com/generate和可能的密钥。我们在gallery/views.py中创建一个视图函数来处理生成请求from django.shortcuts import render from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework import status import requests from django.core.files.base import ContentFile import io from .models import Artwork from django.contrib.auth.models import User api_view([POST]) permission_classes([IsAuthenticated]) # 要求用户登录 def generate_artwork(request): 接收前端传来的提示词调用Stable Diffusion API生成图片并保存作品。 prompt request.data.get(prompt) title request.data.get(title, Untitled) # 默认标题 style request.data.get(style, ) if not prompt: return Response({error: Prompt is required.}, statusstatus.HTTP_400_BAD_REQUEST) # 1. 调用Stable Diffusion API api_url YOUR_STABLE_DIFFUSION_API_ENDPOINT # 替换为你的真实API地址 api_key YOUR_API_KEY # 如果有的话 payload { prompt: prompt, negative_prompt: low quality, blurry, bad anatomy, # 可选的负面提示词提升质量 steps: 20, width: 512, height: 512, } headers {} if api_key: headers[Authorization] fBearer {api_key} try: # 这里假设API返回的是图片的二进制数据 response requests.post(api_url, jsonpayload, headersheaders, timeout60) response.raise_for_status() # 如果请求失败会抛出异常 # 假设API直接返回图片数据 image_data response.content except requests.exceptions.RequestException as e: return Response({error: fFailed to call AI API: {str(e)}}, statusstatus.HTTP_503_SERVICE_UNAVAILABLE) # 2. 创建Artwork对象并保存图片 try: artwork Artwork.objects.create( titletitle, promptprompt, stylestyle, authorrequest.user ) # 将二进制图片数据保存到ImageField artwork.image.save(f{artwork.id}.png, ContentFile(image_data), saveTrue) # 3. 返回成功信息和新作品的数据比如ID和图片URL给前端 from django.urls import reverse image_url request.build_absolute_uri(artwork.image.url) return Response({ message: Artwork generated successfully!, artwork_id: artwork.id, image_url: image_url, title: artwork.title }, statusstatus.HTTP_201_CREATED) except Exception as e: # 如果保存过程出错也需要处理 return Response({error: fFailed to save artwork: {str(e)}}, statusstatus.HTTP_500_INTERNAL_SERVER_ERROR)注意你需要将YOUR_STABLE_DIFFUSION_API_ENDPOINT和YOUR_API_KEY替换成你实际部署的API信息。不同的API提供商返回的数据格式可能不同有的返回图片二进制流有的返回一个包含图片URL的JSON。你需要根据实际情况调整解析响应的代码。3.3 构建前端页面React Components后端逻辑通了现在来打造用户界面。我们主要创建三个页面生成页、画廊页、作品详情页。首先在frontend/src目录下我们创建一个components文件夹来存放组件。1. 生成页面 (GeneratePage.js)这是用户输入提示词并触发生成的地方。// frontend/src/components/GeneratePage.js import React, { useState } from react; import { TextField, Button, Box, Typography, CircularProgress, Alert } from mui/material; import axios from axios; function GeneratePage() { const [prompt, setPrompt] useState(); const [title, setTitle] useState(); const [style, setStyle] useState(); const [loading, setLoading] useState(false); const [message, setMessage] useState({ type: , text: }); const [generatedImage, setGeneratedImage] useState(null); const handleGenerate async () { if (!prompt.trim()) { setMessage({ type: error, text: Please enter a description for your artwork. }); return; } setLoading(true); setMessage({ type: , text: }); setGeneratedImage(null); try { const token localStorage.getItem(token); // 假设使用Token认证 const response await axios.post( http://localhost:8000/api/generate/, // 你的Django后端API地址 { prompt, title: title || Artwork: ${prompt.substring(0, 30)}..., style }, { headers: { Authorization: Bearer ${token} } } ); setMessage({ type: success, text: response.data.message }); setGeneratedImage(response.data.image_url); // 显示新生成的图片 // 可以在这里清空表单或做其他操作 setPrompt(); setTitle(); setStyle(); } catch (error) { console.error(Generation failed:, error); setMessage({ type: error, text: error.response?.data?.error || Failed to generate artwork. Please try again. }); } finally { setLoading(false); } }; return ( Box sx{{ maxWidth: 600, mx: auto, mt: 4, p: 3 }} Typography varianth4 gutterBottom Create Your AI Artwork /Typography TextField fullWidth labelArtwork Title (Optional) variantoutlined value{title} onChange{(e) setTitle(e.target.value)} marginnormal / TextField fullWidth labelDescribe your artwork... * variantoutlined multiline rows{4} value{prompt} onChange{(e) setPrompt(e.target.value)} marginnormal placeholdere.g., A serene landscape with a giant crystal tree under a purple sky, digital art required / TextField fullWidth labelStyle (e.g., Cyberpunk, Oil Painting) - Optional variantoutlined value{style} onChange{(e) setStyle(e.target.value)} marginnormal / Button variantcontained colorprimary onClick{handleGenerate} disabled{loading || !prompt.trim()} fullWidth sizelarge sx{{ mt: 2 }} {loading ? CircularProgress size{24} / : Generate Artwork} /Button {message.text ( Alert severity{message.type} sx{{ mt: 2 }} {message.text} /Alert )} {generatedImage ( Box sx{{ mt: 4, textAlign: center }} Typography varianth6 gutterBottom Your New Creation: /Typography img src{generatedImage} altGenerated Artwork style{{ maxWidth: 100%, maxHeight: 400px, border: 1px solid #ccc, borderRadius: 8px }} / /Box )} /Box ); } export default GeneratePage;2. 画廊页面 (GalleryPage.js)这里以网格形式展示所有作品。// frontend/src/components/GalleryPage.js import React, { useState, useEffect } from react; import { Grid, Card, CardMedia, CardContent, Typography, CardActions, Button, Box, Chip } from mui/material; import { Favorite, Comment } from mui/icons-material; import axios from axios; import { Link } from react-router-dom; function GalleryPage() { const [artworks, setArtworks] useState([]); const [loading, setLoading] useState(true); useEffect(() { fetchArtworks(); }, []); const fetchArtworks async () { try { const response await axios.get(http://localhost:8000/api/artworks/); // 获取作品列表的API setArtworks(response.data); } catch (error) { console.error(Failed to fetch artworks:, error); } finally { setLoading(false); } }; if (loading) { return Typography aligncenter sx{{ mt: 4 }}Loading gallery.../Typography; } return ( Box sx{{ flexGrow: 1, p: 3 }} Typography varianth4 gutterBottom aligncenter AI Art Gallery /Typography Grid container spacing{3} {artworks.map((artwork) ( Grid item xs{12} sm{6} md{4} lg{3} key{artwork.id} Card sx{{ height: 100%, display: flex, flexDirection: column }} CardMedia componentimg height200 image{artwork.image_url} alt{artwork.title} sx{{ objectFit: cover }} / CardContent sx{{ flexGrow: 1 }} Typography gutterBottom varianth6 componentdiv {artwork.title} /Typography Typography variantbody2 colortext.secondary noWrap Prompt: {artwork.prompt} /Typography {artwork.style ( Chip label{artwork.style} sizesmall sx{{ mt: 1 }} / )} Typography variantcaption displayblock sx{{ mt: 1 }} By {artwork.author_name} • {new Date(artwork.created_at).toLocaleDateString()} /Typography /CardContent CardActions Button sizesmall startIcon{Favorite /} {artwork.likes_count} Likes /Button Button sizesmall startIcon{Comment /} {artwork.comments_count} Comments /Button Button sizesmall component{Link} to{/artwork/${artwork.id}} Details /Button /CardActions /Card /Grid ))} /Grid /Box ); } export default GalleryPage;3. 配置路由和主应用 (App.js)最后我们把页面串联起来。// frontend/src/App.js import React from react; import { BrowserRouter as Router, Routes, Route, Link } from react-router-dom; import { AppBar, Toolbar, Typography, Button, Container } from mui/material; import GeneratePage from ./components/GeneratePage; import GalleryPage from ./components/GalleryPage; // 假设我们还有一个作品详情页组件 ArtworkDetailPage // import ArtworkDetailPage from ./components/ArtworkDetailPage; function App() { return ( Router AppBar positionstatic Toolbar Typography varianth6 componentdiv sx{{ flexGrow: 1 }} My AI Art Gallery /Typography Button colorinherit component{Link} to/ Gallery /Button Button colorinherit component{Link} to/generate Create /Button Button colorinherit component{Link} to/login Login /Button /Toolbar /AppBar Container maxWidthlg sx{{ mt: 4 }} Routes Route path/ element{GalleryPage /} / Route path/generate element{GeneratePage /} / {/* Route path/artwork/:id element{ArtworkDetailPage /} / */} {/* Route path/login element{LoginPage /} / */} /Routes /Container /Router ); } export default App;4. 前后端联调与部署上线代码写完了但项目还跑在本地。我们需要让前后端能通信并最终部署到服务器上让所有人都能访问。4.1 解决跨域问题与API对接前端运行在localhost:3000后端运行在localhost:8000浏览器出于安全考虑会阻止这种跨域请求。我们需要在后端Django中配置CORS跨域资源共享。在Django后端虚拟环境中安装django-cors-headerspip install django-cors-headers然后在gallery_backend/settings.py中配置INSTALLED_APPS [ # ... corsheaders, # 添加这行 # ... ] MIDDLEWARE [ corsheaders.middleware.CorsMiddleware, # 这个要放在最前面 # ... ] # 配置允许的前端地址 CORS_ALLOWED_ORIGINS [ http://localhost:3000, # 你的React前端地址 ] # 允许携带认证信息如cookies, token CORS_ALLOW_CREDENTIALS True同时我们需要为之前写的generate_artwork视图以及获取作品列表的视图配置URL。在gallery/urls.py需要创建和项目主urls.py中配置路由。4.2 部署考虑一个完整的部署涉及多个步骤后端部署将Django代码部署到云服务器如Ubuntu使用Gunicorn作为WSGI服务器Nginx作为反向代理和静态文件服务器。前端部署运行npm run build生成静态文件然后将build文件夹内的文件放到Nginx指定的目录下或者使用Netlify、Vercel等静态站点托管服务。数据库部署确保生产环境的MySQL服务正常运行并迁移数据。AI API服务确保Stable Diffusion API服务部署在星图GPU等平台稳定运行且生产环境的后端能访问到。环境变量与安全将数据库密码、API密钥等敏感信息从代码中移除改用环境变量管理。域名与HTTPS为你的网站绑定域名并配置SSL证书可以使用Let‘s Encrypt免费获取。部署是一个系统性的工程对于初学者可以先用简单的云服务器提供商如各大云厂商的轻量应用服务器尝试部署它们通常提供比较友好的管理面板。5. 总结与展望跟着走完这一趟一个具备核心功能的个人AI艺术画廊网站就初具雏形了。从设计数据库表到集成AI绘画API再到构建交互式的前端页面我们完成了一个小型全栈项目的闭环。这个过程里最重要的不是死记硬背代码而是理解数据如何流动前后端如何协作以及如何将一个复杂的想法拆解成一个个可实现的功能模块。这个项目还有很多可以完善和扩展的地方。比如可以增加用户收藏功能、作品分类标签、更复杂的搜索和筛选、个人主页展示甚至引入简单的社交关注机制。在AI生成方面也可以尝试集成更多参数控制比如采样器、CFG Scale等让资深玩家有更多创作空间。技术总是在迭代Stable Diffusion的模型也在不断更新。未来你可以很方便地将这个项目中的V1.5 API替换成更强大的SDXL或者最新的模型网站的架构不需要大改。搭建这样一个项目最大的收获或许不是代码本身而是你拥有了一个可以持续“玩”下去的数字画布一个能亲眼见证技术如何赋能创意的试验场。不妨就从这里开始动手搭建属于你自己的那个角落吧。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。