《Python 实用项目与工具制作指南》· 3.2 实战·开发密码管理器

3.2 实战·开发密码管理器

在本节中,我们将基于Django框架开发一个简易密码管理器,实现用户注册、网站密码存储、中英文切换等核心功能。该项目的完整代码可参考GitHub仓库:https://github.com/yangrenruiyrr/pm

3.2.1 项目概述与功能设计

核心功能

该密码管理器是一个Web应用,主要帮助用户安全存储不同网站的账号和密码,核心功能包括:

  • 用户注册与登录(基于Django内置认证系统)
  • 网站信息管理(添加、查看网站)
  • 账号密码管理(为网站添加、编辑、查看用户名和密码)
  • 中英文双语支持
  • 基础的错误处理(404、500页面自动跳转)

技术栈

  • 后端:Python 3.x + Django 5.0
  • 前端:Bootstrap 5(样式框架)
  • 数据库:SQLite(轻量嵌入式数据库,适合小型应用)
  • 静态文件处理:Whitenoise

3.2.2 项目结构搭建

初始化项目

  1. 创建虚拟环境并激活:
python -m venv venv
# Windows激活:venv\Scripts\activate
# Linux/Mac激活:source venv/bin/activate
  1. 安装依赖:
pip install django==5.0 django-bootstrap5 whitenoise
  1. 创建项目与应用:
django-admin startproject PM  # 项目根目录
cd PM
python manage.py startapp main  # 中文主应用
python manage.py startapp accounts  # 中文用户认证
python manage.py startapp EN_main  # 英文主应用
python manage.py startapp EN_accounts  # 英文用户认证

项目目录结构

最终项目结构如下(核心文件):

PM/
├── PM/                  # 项目配置目录
│   ├── settings.py      # 全局配置
│   ├── urls.py          # 主路由
│   └── wsgi.py          # WSGI配置
├── main/                # 中文主应用
│   ├── models.py        # 数据模型
│   ├── views.py         # 视图函数
│   ├── forms.py         # 表单定义
│   └── templates/main/  # 中文模板
├── EN_main/             # 英文主应用(结构同main)
├── accounts/            # 中文用户认证(注册等)
├── EN_accounts/         # 英文用户认证(结构同accounts)
├── templates/           # 全局模板(404.html、500.html)
├── static/              # 静态文件(CSS、JS、图片)
└── manage.py            # 项目管理脚本

3.2.3 核心配置(settings.py)

PM/settings.py中配置项目核心参数,关键配置如下:

# 应用注册(包含中英文应用)
INSTALLED_APPS = [
    'main',
    'accounts',
    'EN_main',
    'EN_accounts',
    'django_bootstrap5',  # Bootstrap支持
    'django.contrib.admin',
    # ... 其他内置应用
]

# 模板配置(支持全局模板和应用内模板)
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],  # 全局模板目录
        'APP_DIRS': True,  # 允许应用内模板
        # ... 其他配置
    },
]

# 静态文件配置
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfile')  # 静态文件收集目录
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'  # Whitenoise处理
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]  # 静态文件源目录

# 认证配置
LOGIN_REDIRECT_URL = 'main:index'  # 登录后跳转首页
LOGOUT_REDIRECT_URL = 'main:index'  # 登出后跳转首页
LOGIN_URL = 'accounts:login'  # 未登录时跳转的登录页

3.2.4 数据模型设计(models.py)

密码管理器的核心数据是“网站”和“账号密码”,在main/models.py中定义:

from django.db import models
from django.contrib.auth.models import User  # 关联Django内置用户模型

class Website(models.Model):
    """用户添加的网站(如"GitHub"、"知乎")"""
    text = models.CharField(max_length=200)  # 网站名称
    date_added = models.DateTimeField(auto_now=True)  # 最后修改时间
    owner = models.ForeignKey(User, on_delete=models.CASCADE)  # 关联用户(用户删除时,网站也删除)

    def __str__(self):
        return self.text  # 打印时显示网站名称

class Username(models.Model):
    """网站对应的账号密码"""
    website = models.ForeignKey(Website, on_delete=models.CASCADE)  # 关联网站(网站删除时,账号也删除)
    text = models.CharField(max_length=200)  # 用户名
    text2 = models.CharField(max_length=200)  # 密码
    date_added = models.DateTimeField(auto_now=True)  # 最后修改时间

    def __str__(self):
        return f"Username:{self.text}\nPassword:{self.text2}"  # 打印时显示账号密码

定义完成后执行数据库迁移:

python manage.py makemigrations main  # 生成迁移文件
python manage.py migrate  # 应用迁移

3.2.5 表单设计(forms.py)

使用Django的ModelForm快速生成表单,在main/forms.py中定义:

from django import forms
from .models import Website, Username

class WebsiteForm(forms.ModelForm):
    """添加网站的表单"""
    class Meta:
        model = Website  # 关联Website模型
        fields = ['text']  # 仅包含网站名称字段
        labels = {'text': ''}  # 不显示字段标签

class UsernameForm(forms.ModelForm):
    """添加账号密码的表单"""
    class Meta:
        model = Username  # 关联Username模型
        fields = ['text', 'text2']  # 包含用户名(text)和密码(text2)
        labels = {'text': '', 'text2': ''}  # 不显示字段标签

3.2.6 视图函数实现(views.py)

视图函数处理用户请求并返回响应,以main/views.py为例,核心逻辑包括:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required  # 登录验证装饰器
from django.http import Http404
from .models import Website, Username
from .forms import WebsiteForm, UsernameForm

def index(request):
    """首页视图"""
    return render(request, 'main/index.html')

def help(request):
    """帮助页视图"""
    return render(request, 'main/help.html')

@login_required  # 仅登录用户可访问
def websites(request):
    """网站列表页(显示当前用户的所有网站)"""
    websites = Website.objects.filter(owner=request.user).order_by('date_added')
    context = {'websites': websites}
    return render(request, 'main/websites.html', context)

@login_required
def website(request, website_id):
    """网站详情页(显示该网站的所有账号密码)"""
    website = Website.objects.get(id=website_id)
    # 权限验证:确保用户只能访问自己的网站
    if website.owner != request.user:
        raise Http404
    usernames = website.username_set.order_by('-date_added')  # 按时间倒序
    context = {'website': website, 'usernames': usernames}
    return render(request, 'main/website.html', context)

@login_required
def new_website(request):
    """添加新网站"""
    if request.method != 'POST':
        # GET请求:显示空表单
        form = WebsiteForm()
    else:
        # POST请求:处理表单数据
        form = WebsiteForm(data=request.POST)
        if form.is_valid():
            new_website = form.save(commit=False)  # 暂不保存到数据库
            new_website.owner = request.user  # 设置所属用户
            new_website.save()  # 保存
            return redirect('main:websites')  # 跳转到网站列表
    context = {'form': form}
    return render(request, 'main/new_website.html', context)

# 其他视图:new_username(添加账号密码)、edit_username(编辑账号密码)
# 逻辑类似,需注意权限验证(仅允许所有者操作)

3.2.7 用户认证(注册功能)

使用Django内置的UserCreationForm实现注册功能,在accounts/views.py中:

from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm

def register(request):
    """用户注册"""
    if request.method != 'POST':
        # GET请求:显示空注册表单
        form = UserCreationForm()
    else:
        # POST请求:处理注册数据
        form = UserCreationForm(data=request.POST)
        if form.is_valid():
            new_user = form.save()  # 创建用户
            login(request, new_user)  # 自动登录
            return redirect('main:index')  # 跳转到首页
    context = {'form': form}
    return render(request, 'registration/register.html', context)

英文注册功能在EN_accounts/views.py中实现,逻辑相同,仅模板和跳转路由不同。

3.2.8 模板开发(前端页面)

使用模板继承减少重复代码,以中文基础模板main/templates/main/base.html为例:

<!doctype html>
<html lang="zh-CN">
<head>
  {% load static %}  <!-- 加载静态文件 -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>密码管理器 V1.1.2</title>
  <link rel="icon" href="/static/image/favicon.ico">  <!-- 网站图标 -->
  <!-- 引入Bootstrap CSS -->
  <link crossorigin="anonymous" href="/static/css/bootstrap.min.css" 
    integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
    rel="stylesheet">
  <!-- 引入Bootstrap JS -->
  <script crossorigin="anonymous" 
    integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
    src="/static/js/bootstrap.min.js"></script>
</head>
<body>
  <!-- 导航栏 -->
  <nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
    <div class="container-fluid">
      <a class="navbar-brand" href="/">密码管理器 V1.1.2</a>
      <!-- 移动端菜单按钮 -->
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
        data-bs-target="#navbarCollapse" aria-controls="navbarCollapse"
        aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <!-- 导航菜单 -->
      <div class="collapse navbar-collapse" id="navbarCollapse">
        <ul class="navbar-nav me-auto mb-2 mb-md-0">
          <li class="nav-item">
            <a class="nav-link" href="/websites/">网站</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="/help/">帮助</a>
          </li>
        </ul>
      </div>
    </div>
  </nav>

  <!-- 页面内容(由子模板填充) -->
  <div class="container">
    {% block page_header %}{% endblock page_header %}
    {% block content %}{% endblock content %}
  </div>
</body>
</html>

子模板(如首页index.html)通过extends继承基础模板,并填充内容:

{% extends 'main/base.html' %}
{% block page_header %}
  <div class="p-3 mb-4 bg-light border rounded-3">
    <div class="container-fluid py-4">
      <h1 class="display-3">保管你的密码</h1>
      <p class="lead">登记需要保管密码的网站,并登记用户名和密码。</p>
      <a class="btn btn-primary btn-lg mt-1" href="{% url 'accounts:register' %}">注册 &raquo;</a>
    </div>
  </div>
{% endblock page_header %}

3.2.9 中英文国际化支持

通过创建独立的英文应用(EN_mainEN_accounts)和模板实现双语支持:

  • 英文模板放在EN_main/templates/EN_main/目录,如EN_main/templates/EN_main/index.html
  • 英文路由独立配置(如/EN对应英文首页,/EN/websites/对应英文网站列表)
  • 视图逻辑复用,仅模板和跳转路径不同(如英文注册后跳转到英文首页)

3.2.10 错误处理

自定义404和500错误页面(templates/404.htmltemplates/500.html),实现自动跳转:

<!-- 404.html -->
<!doctype html>
<html lang="en">
<head>
  {% load static %}
  <meta charset="utf-8">
  <title>密码管理器</title>
  <!-- 3秒后自动跳转到首页 -->
  <script language="javascript">
    setTimeout("javascript:location.href='/'", 3000);
  </script>
  <!-- 引入Bootstrap资源(同基础模板) -->
</head>
<body>
  <!-- 导航栏(同基础模板) -->
  <div class="container">
    <h1>404 - 页面未找到</h1>
    <p>3秒后自动返回首页...</p>
  </div>
</body>
</html>

3.2.11 运行与测试

  1. 创建超级用户(可选,用于管理后台):
python manage.py createsuperuser
  1. 启动开发服务器:
python manage.py runserver
  1. 访问测试:
  • 首页:http://127.0.0.1:8000/
  • 英文首页:http://127.0.0.1:8000/EN/
  • 管理后台:http://127.0.0.1:8000/admin/

3.2.12 项目扩展方向

  1. 安全性增强:

    • 密码加密存储(当前明文存储,可使用Django加密工具或第三方库如cryptography
    • 添加CSRF保护(已通过Django内置中间件实现)
    • 登录验证码
  2. 功能扩展:

    • 密码生成器(自动生成强密码)
    • 数据导出/导入(如CSV格式)
    • 密码过期提醒
  3. 体验优化:

    • 密码显示/隐藏切换
    • 搜索功能(按网站名称搜索)
    • 响应式布局优化

通过本项目,我们掌握了Django Web开发的核心流程:模型设计、表单处理、视图逻辑、模板渲染、用户认证等。同时,通过中英文版本的实现,理解了多语言应用的基本架构思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值