基于Django设计——流浪动物救助智能平台 (一)
项目概述
流浪动物救助智能平台,核心功能:
-
动物档案管理(发布待领养动物信息)
-
AI 动物识别(上传照片自动识别品种)
-
领养匹配(按体型、品种筛选)
-
地图定位(展示附近救助站)
-
领养申请(用户提交申请)
技术栈:Django 4.2 + SQLite + Bootstrap 5 + 百度AI API + 百度地图API
一、初步环境搭建与基础页设计
第一步:创建项目和应用
1.1 创建项目文件夹
cd C:\Users\25412
mkdir animal_rescue
cd animal_rescue
1.2 创建虚拟环境
python -m venv venv
venv\Scripts\activate
1.3 使用国内镜像源安装 Django
第一步:升级 pip(使用清华源)
python -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple

第二步:安装 Django(使用清华源)
pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple

1.4 创建 Django 项目
django-admin startproject core .
注意:最后的
.表示在当前目录创建项目,不要忘记。
1.5 创建应用
python manage.py startapp animals
python manage.py startapp adoptions
python manage.py startapp shelters
1.6 查看项目结构
dir
你应该看到:

1.7 在 VS Code 中打开项目
code .
1.8 注册应用到 settings.py
打开 core/settings.py,找到 INSTALLED_APPS,添加:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'animals', # 动物档案
'adoptions', # 领养申请
'shelters', # 救助站
]
1.9 添加媒体文件配置
在文件末尾添加:
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
第二步:设计数据模型
2.1 动物档案模型(animals/models.py)
打开 animals/models.py,删除原有内容,写入:
from django.db import models
from django.utils import timezone
class Animal(models.Model):
"""流浪动物档案"""
# 体型选项
SIZE_CHOICES = [
('S', '小型(10kg以下)'),
('M', '中型(10-25kg)'),
('L', '大型(25kg以上)'),
]
# 性格选项
PERSONALITY_CHOICES = [
('gentle', '温顺'),
('active', '活泼'),
('shy', '胆小'),
('independent', '独立'),
]
# 健康状况选项
HEALTH_CHOICES = [
('healthy', '健康'),
('vaccinated', '已疫苗'),
('neutered', '已绝育'),
('injured', '受伤治疗中'),
]
# 状态选项
STATUS_CHOICES = [
('available', '待领养'),
('adopted', '已领养'),
('reserved', '已被预定'),
]
# 基本信息
name = models.CharField(max_length=50, blank=True, help_text='动物昵称(可留空)')
species = models.CharField(max_length=20, help_text='物种:猫/狗/其他')
breed = models.CharField(max_length=100, blank=True, help_text='品种')
age = models.IntegerField(null=True, blank=True, help_text='年龄(月)')
# 特征信息
size = models.CharField(max_length=1, choices=SIZE_CHOICES, help_text='体型')
color = models.CharField(max_length=50, blank=True, help_text='毛色')
personality = models.CharField(max_length=20, choices=PERSONALITY_CHOICES, default='gentle')
# 健康信息
health_status = models.CharField(max_length=20, choices=HEALTH_CHOICES, default='healthy')
health_description = models.TextField(blank=True, help_text='详细健康描述')
# 位置信息
found_location = models.CharField(max_length=200, help_text='发现地点')
rescue_date = models.DateField(default=timezone.now, help_text='救助日期')
# 照片
photo = models.ImageField(upload_to='animals/%Y/%m/', help_text='动物照片')
# AI识别结果
ai_recognized_breed = models.CharField(max_length=100, blank=True, help_text='AI识别品种')
ai_confidence = models.FloatField(null=True, blank=True, help_text='AI识别置信度')
# 状态
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='available')
# 描述
description = models.TextField(blank=True, help_text='详细描述')
# 时间戳
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
if self.name:
return f"{self.species} - {self.name}"
return f"{self.species} - {self.id}"
class Meta:
ordering = ['-created_at']
verbose_name = '动物档案'
verbose_name_plural = '动物档案'
2.2 领养申请模型(adoptions/models.py)
notepad adoptions\models.py
写入:
from django.db import models
from animals.models import Animal
class AdoptionApplication(models.Model):
"""领养申请"""
STATUS_CHOICES = [
('pending', '待审核'),
('approved', '已通过'),
('rejected', '已拒绝'),
('completed', '已完成领养'),
]
# 关联的动物
animal = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name='applications')
# 申请人信息
applicant_name = models.CharField(max_length=50, help_text='姓名')
applicant_phone = models.CharField(max_length=20, help_text='联系电话')
applicant_email = models.EmailField(blank=True, help_text='电子邮箱')
applicant_address = models.CharField(max_length=200, help_text='居住地址')
# 领养条件
has_experience = models.BooleanField(default=False, help_text='是否有养宠经验')
has_other_pets = models.BooleanField(default=False, help_text='是否已有其他宠物')
house_type = models.CharField(max_length=50, choices=[
('apartment', '公寓'),
('house', '独立住宅'),
('other', '其他'),
], help_text='住房类型')
# 申请状态
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
review_notes = models.TextField(blank=True, help_text='审核备注')
# 时间戳
applied_at = models.DateTimeField(auto_now_add=True)
reviewed_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return f"{self.applicant_name} 申请领养 {self.animal}"
class Meta:
ordering = ['-applied_at']
verbose_name = '领养申请'
verbose_name_plural = '领养申请'
2.3 救助站模型(shelters/models.py)
notepad shelters\models.py
写入:
from django.db import models
class Shelter(models.Model):
"""救助站"""
name = models.CharField(max_length=100, help_text='救助站名称')
address = models.CharField(max_length=200, help_text='详细地址')
latitude = models.FloatField(help_text='纬度')
longitude = models.FloatField(help_text='经度')
phone = models.CharField(max_length=20, help_text='联系电话')
contact_person = models.CharField(max_length=50, help_text='联系人')
business_hours = models.CharField(max_length=100, blank=True, help_text='营业时间')
description = models.TextField(blank=True, help_text='简介')
def __str__(self):
return self.name
class Meta:
verbose_name = '救助站'
verbose_name_plural = '救助站'
2.4 生成数据库迁移
python manage.py makemigrations
python manage.py migrate
第三步:配置后台管理
3.1 注册动物档案(animals/admin.py)
notepad animals\admin.py
写入:
from django.contrib import admin
from .models import Animal
@admin.register(Animal)
class AnimalAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'species', 'breed', 'size', 'status', 'created_at']
list_filter = ['species', 'size', 'status', 'health_status']
search_fields = ['name', 'species', 'breed', 'found_location']
list_editable = ['status']
readonly_fields = ['ai_recognized_breed', 'ai_confidence']
fieldsets = (
('基本信息', {
'fields': ('name', 'species', 'breed', 'age', 'size', 'color')
}),
('健康与性格', {
'fields': ('personality', 'health_status', 'health_description')
}),
('位置与照片', {
'fields': ('found_location', 'rescue_date', 'photo')
}),
('AI识别', {
'fields': ('ai_recognized_breed', 'ai_confidence')
}),
('状态', {
'fields': ('status', 'description')
}),
)
3.2 注册领养申请(adoptions/admin.py)
notepad adoptions\admin.py
写入:
from django.contrib import admin
from .models import AdoptionApplication
@admin.register(AdoptionApplication)
class AdoptionApplicationAdmin(admin.ModelAdmin):
list_display = ['applicant_name', 'animal', 'applicant_phone', 'status', 'applied_at']
list_filter = ['status', 'has_experience', 'has_other_pets']
search_fields = ['applicant_name', 'applicant_phone', 'applicant_email']
list_editable = ['status']
readonly_fields = ['applied_at']
3.3 注册救助站(shelters/admin.py)
notepad shelters\admin.py
写入:
from django.contrib import admin
from .models import Shelter
@admin.register(Shelter)
class ShelterAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'phone', 'contact_person']
search_fields = ['name', 'address']
第四步:创建超级用户并测试后台
python manage.py createsuperuser
输入:
-
用户名:
admin -
邮箱:直接回车
-
密码:
admin123
python manage.py runserver
访问 http://127.0.0.1:8000/admin/
登录后应该能看到三个应用:Animals、Adoptions、Shelters
第五步:配置静态文件和媒体文件
5.1 修改 settings.py
notepad core\settings.py
在文件末尾添加:
import os
# 媒体文件配置(用于上传照片)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# 静态文件配置
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
5.2 配置主 URL
notepad core\urls.py
修改为:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
]
# 开发环境下提供媒体文件访问
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
第六步:创建前端页面(首页)
6.1 创建静态文件目录
mkdir static
mkdir static\css
mkdir static\js
6.2 创建基础模板目录
mkdir templates
mkdir templates\animals
6.3 创建 base.html 基础模板
notepad templates\base.html
写入:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}流浪动物救助平台{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="/">
<i class="bi bi-heart-fill text-danger"></i> 流浪动物救助平台
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="/">首页</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/animals/">待领养动物</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/shelters/">救助站地图</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- 主要内容 -->
<main>
{% block content %}{% endblock %}
</main>
<!-- 页脚 -->
<footer class="bg-dark text-white text-center py-4 mt-5">
<div class="container">
<p class="mb-0">© 2024 流浪动物救助平台 | 用爱温暖每一个生命</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
6.4 创建首页视图
在 animals/views.py 中添加首页视图:
notepad animals\views.py
写入:
from django.shortcuts import render
from .models import Animal
def home(request):
"""首页"""
# 获取最新3只待领养动物
recent_animals = Animal.objects.filter(status='available')[:3]
context = {
'recent_animals': recent_animals,
}
return render(request, 'animals/home.html', context)
6.5 配置 URL 路由
创建 animals/urls.py
notepad animals\urls.py
写入:
from django.urls import path
from . import views
app_name = 'animals'
urlpatterns = [
path('', views.home, name='home'),
]
修改主 URL 配置
notepad core\urls.py
修改为:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('animals.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
6.6 创建首页模板
notepad templates\animals\home.html
写入:
{% extends 'base.html' %}
{% load static %}
{% block title %}流浪动物救助平台 - 首页{% endblock %}
{% block content %}
<div class="container py-5">
<div class="text-center mb-5">
<h1 class="display-4">让爱不再流浪</h1>
<p class="lead">每一只动物都值得被温柔以待</p>
<a href="/animals/list/" class="btn btn-primary btn-lg">
<i class="bi bi-search-heart"></i> 寻找待领养伙伴
</a>
</div>
<div class="row mt-5">
<div class="col-md-4 mb-4">
<div class="card text-center h-100 shadow-sm">
<div class="card-body">
<i class="bi bi-dog" style="font-size: 48px; color: #0d6efd;"></i>
<h4 class="mt-3">动物档案</h4>
<p>查看所有待领养动物的详细信息和健康状况</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card text-center h-100 shadow-sm">
<div class="card-body">
<i class="bi bi-map" style="font-size: 48px; color: #0d6efd;"></i>
<h4 class="mt-3">救助站地图</h4>
<p>查找附近的救助站,了解其位置和联系方式</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card text-center h-100 shadow-sm">
<div class="card-body">
<i class="bi bi-file-text" style="font-size: 48px; color: #0d6efd;"></i>
<h4 class="mt-3">领养申请</h4>
<p>提交领养申请,给流浪动物一个温暖的家</p>
</div>
</div>
</div>
</div>
{% if recent_animals %}
<div class="mt-5">
<h2 class="text-center mb-4">最新待领养伙伴</h2>
<div class="row">
{% for animal in recent_animals %}
<div class="col-md-4 mb-4">
<div class="card h-100 shadow-sm">
{% if animal.photo %}
<img src="{{ animal.photo.url }}" class="card-img-top" alt="{{ animal.name }}" style="height: 200px; object-fit: cover;">
{% endif %}
<div class="card-body">
<h5 class="card-title">
{{ animal.name|default:animal.species }}
</h5>
<p class="card-text">
<small class="text-muted">{{ animal.get_size_display }} · {{ animal.get_personality_display }}</small>
</p>
<p class="card-text">{{ animal.description|truncatewords:20 }}</p>
<a href="#" class="btn btn-outline-primary">了解详情</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}
第七步:测试运行
python manage.py runserver
你应该能看到首页!
当前已完成
| 步骤 | 状态 | 说明 |
|---|---|---|
| 1. 创建项目和虚拟环境 | ✅ | 完成 |
| 2. 创建三个应用 | ✅ | animals, adoptions, shelters |
| 3. 设计数据模型 | ✅ | 三个模型已定义 |
| 4. 数据库迁移 | ✅ | 已执行 |
| 5. 配置后台管理 | ✅ | 可在 admin 中管理数据 |
| 6. 配置静态/媒体文件 | ✅ | 支持图片上传 |
| 7. 创建首页 | ✅ | 可访问 |
二、动物列表页设计(展示所有待领养动物,支持筛选(体型、品种、性格))
第一步:动物列表页(支持筛选)
1.1 创建视图函数
打开 animals/views.py,添加列表页视图:
notepad animals\views.py
替换为以下完整代码:
from django.shortcuts import render, get_object_or_404
from .models import Animal
def home(request):
"""首页"""
recent_animals = Animal.objects.filter(status='available')[:3]
return render(request, 'animals/home.html', {'recent_animals': recent_animals})
def animal_list(request):
"""动物列表页 - 支持筛选"""
# 获取所有待领养动物
animals = Animal.objects.filter(status='available')
# 筛选条件
species = request.GET.get('species', '')
size = request.GET.get('size', '')
personality = request.GET.get('personality', '')
if species:
animals = animals.filter(species=species)
if size:
animals = animals.filter(size=size)
if personality:
animals = animals.filter(personality=personality)
context = {
'animals': animals,
'species_choices': Animal.SPECIES_CHOICES,
'size_choices': Animal.SIZE_CHOICES,
'personality_choices': Animal.PERSONALITY_CHOICES,
'current_species': species,
'current_size': size,
'current_personality': personality,
}
return render(request, 'animals/animal_list.html', context)
def animal_detail(request, animal_id):
"""动物详情页"""
animal = get_object_or_404(Animal, id=animal_id, status='available')
return render(request, 'animals/animal_detail.html', {'animal': animal})
注意:需要在模型中添加
SPECIES_CHOICES,我们稍后补充。
1.2 修改模型添加物种选项
打开 animals/models.py,在 Animal 类中添加 SPECIES_CHOICES:
notepad animals\models.py
找到 SIZE_CHOICES 那一行,在它上面添加:
SPECIES_CHOICES = [
('cat', '猫'),
('dog', '狗'),
('other', '其他'),
]
同时修改 species 字段:
species = models.CharField(max_length=20, choices=SPECIES_CHOICES, default='cat')
保存文件。
1.3 生成数据库迁移
因为修改了模型,需要重新迁移:
python manage.py makemigrations
python manage.py migrate
1.4 配置 URL
打开 animals/urls.py:
mals\urls.py
替换为:
from django.urls import path
from . import views
app_name = 'animals'
urlpatterns = [
path('', views.home, name='home'),
path('list/', views.animal_list, name='list'),
path('<int:animal_id>/', views.animal_detail, name='detail'),
]
1.5 创建动物列表页模板
mkdir templates\animals
notepad templates\animals\animal_list.html
粘贴以下内容:
{% extends 'base.html' %}
{% load static %}
{% block title %}待领养动物列表 - 流浪动物救助平台{% endblock %}
{% block content %}
<div class="container py-4">
<div class="row">
<!-- 筛选侧边栏 -->
<div class="col-md-3">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">筛选条件</h5>
</div>
<div class="card-body">
<form method="get">
<!-- 物种筛选 -->
<div class="mb-3">
<label class="form-label">物种</label>
<select name="species" class="form-select">
<option value="">全部</option>
<option value="cat" {% if current_species == 'cat' %}selected{% endif %}>猫</option>
<option value="dog" {% if current_species == 'dog' %}selected{% endif %}>狗</option>
<option value="other" {% if current_species == 'other' %}selected{% endif %}>其他</option>
</select>
</div>
<!-- 体型筛选 -->
<div class="mb-3">
<label class="form-label">体型</label>
<select name="size" class="form-select">
<option value="">全部</option>
<option value="S" {% if current_size == 'S' %}selected{% endif %}>小型</option>
<option value="M" {% if current_size == 'M' %}selected{% endif %}>中型</option>
<option value="L" {% if current_size == 'L' %}selected{% endif %}>大型</option>
</select>
</div>
<!-- 性格筛选 -->
<div class="mb-3">
<label class="form-label">性格</label>
<select name="personality" class="form-select">
<option value="">全部</option>
<option value="gentle" {% if current_personality == 'gentle' %}selected{% endif %}>温顺</option>
<option value="active" {% if current_personality == 'active' %}selected{% endif %}>活泼</option>
<option value="shy" {% if current_personality == 'shy' %}selected{% endif %}>胆小</option>
</select>
</div>
<button type="submit" class="btn btn-primary w-100">
<i class="bi bi-search"></i> 筛选
</button>
<a href="{% url 'animals:list' %}" class="btn btn-outline-secondary w-100 mt-2">
<i class="bi bi-arrow-repeat"></i> 重置
</a>
</form>
</div>
</div>
</div>
<!-- 动物列表 -->
<div class="col-md-9">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3>待领养动物</h3>
<span class="text-muted">共 {{ animals|length }} 只</span>
</div>
{% if animals %}
<div class="row">
{% for animal in animals %}
<div class="col-md-6 col-lg-4 mb-4">
<div class="card h-100 shadow-sm">
{% if animal.photo %}
<img src="{{ animal.photo.url }}" class="card-img-top" alt="{{ animal.name }}" style="height: 200px; object-fit: cover;">
{% else %}
<div class="bg-light text-center py-5">
<i class="bi bi-camera" style="font-size: 48px; color: #ccc;"></i>
<p class="text-muted">暂无照片</p>
</div>
{% endif %}
<div class="card-body">
<h5 class="card-title">
{{ animal.name|default:animal.get_species_display }}
</h5>
<p class="card-text">
<span class="badge bg-secondary">{{ animal.get_size_display }}</span>
<span class="badge bg-info">{{ animal.get_personality_display }}</span>
</p>
<p class="card-text small text-muted">
<i class="bi bi-geo-alt"></i> {{ animal.found_location|truncatechars:20 }}
</p>
<p class="card-text">{{ animal.description|truncatewords:15 }}</p>
</div>
<div class="card-footer bg-white border-top-0">
<a href="{% url 'animals:detail' animal.id %}" class="btn btn-primary btn-sm w-100">
查看详情
</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="alert alert-info text-center">
<i class="bi bi-info-circle"></i> 暂无符合条件的动物,请稍后再来。
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}
1.6 修改导航栏,添加列表页链接
打开 templates/base.html,在导航栏中添加"待领养动物"链接:
notepad templates\base.html
找到导航栏部分,确保有:
<li class="nav-item">
<a class="nav-link" href="{% url 'animals:list' %}">待领养动物</a>
</li>
1.7 添加测试数据(通过后台)
-
运行服务器:
python manage.py runserver
-
登录(
admin/admin123) -
点击 Animals → Add Animal
-
添加几只测试动物:
-
第一只:物种-猫,体型-小型,性格-温顺,发现地点-上海浦东
-
第二只:物种-狗,体型-中型,性格-活泼,发现地点-北京朝阳
-
第三只:物种-狗,体型-大型,性格-胆小,发现地点-广州天河
-
1.8 测试列表页
访问 http://127.0.0.1:8000/animals/list/
你应该看到:
-
所有动物以卡片形式展示
-
左侧有筛选条件
-
选择筛选条件后点击"筛选",列表会更新
-
点击"重置"会清除所有筛选
✅ 第一步完成!
| 功能 | 状态 |
|---|---|
| 动物列表页 | ✅ |
| 按物种筛选 | ✅ |
| 按体型筛选 | ✅ |
| 按性格筛选 | ✅ |
| 卡片式展示 | ✅ |
下一步预告
接下来我们将依次完成:
-
动物详情页:展示完整信息,提供领养申请入口
-
领养申请功能:表单提交申请
-
救助站地图页:集成百度地图,展示救助站位置
-
AI 识别功能:上传照片自动识别品种
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)