基于 Django 与 Bootstrap 构建的现代化设备管理平台

整体步骤概览

  1. 创建项目和应用
  2. 设计模型(Model) - 定义设备的数据结构
  3. 配置用户认证(Auth) - 使用 Django 自带的强大用户系统
  4. 创建视图(View) - 处理业务逻辑:登录、列表、增删改查
  5. 编写模板(Template) - 设计前端页面
  6. 配置路由(URL) - 将 URL 映射到视图
  7. 运行测试

第一步:创建项目和应用

bash 复制代码
# 1. 在合适的位置创建项目目录并进入
mkdir my_device_manager
cd my_device_manager

# 2. 创建虚拟环境(推荐)
python -m venv venv

# 3. 激活虚拟环境
# On Windows:
venv\Scripts\activate
# On macOS/Linux:
source venv/bin/activate

# 4. 安装 Django
pip install django

# 5. 创建Django项目,名为 `my_site`
django-admin startproject my_site .

# 6. 创建一个名为 `devices` 的应用来处理设备相关的功能
python manage.py startapp devices

# 7. 将新应用 `devices` 和 Django 自带的 `auth` 应用添加到设置中
# 编辑 my_site/settings.py

编辑 my_site/settings.py:

python 复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth', # 用户认证系统
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'devices', # 添加你的应用
]

同时,在文件末尾配置数据库(默认使用 SQLite,无需修改即可用)和静态文件。


第二步:设计设备模型 (Model)

编辑 devices/models.py:

python 复制代码
from django.db import models
from django.contrib.auth.models import User

class Device(models.Model):
    # 设备类型选择
    TYPE_CHOICES = (
        ('router', '路由器'),
        ('switch', '交换机'),
        ('server', '服务器'),
        ('pc', '个人电脑'),
        ('other', '其他'),
    )

    name = models.CharField(max_length=100, verbose_name="设备名称")
    ip_address = models.GenericIPAddressField(verbose_name="IP地址")
    type = models.CharField(max_length=20, choices=TYPE_CHOICES, default='other', verbose_name="设备类型")
    description = models.TextField(blank=True, null=True, verbose_name="设备描述")
    # 添加创建时间和更新时间
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    # 将设备与用户关联(一个用户拥有多个设备)
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='devices', verbose_name="所属用户")

    def __str__(self):
        return f"{self.name} ({self.ip_address})"

    class Meta:
        verbose_name = "设备"
        verbose_name_plural = "设备"

创建数据库表:

bash 复制代码
# 生成迁移文件
python manage.py makemigrations
# 执行迁移,在数据库中创建表
python manage.py migrate

第三步:创建处理逻辑的视图 (View)

编辑 devices/views.py:

python 复制代码
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .models import Device
from .forms import DeviceForm # 我们稍后会创建这个表单

def user_login(request):
    """用户登录视图"""
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            messages.success(request, f'欢迎回来,{username}!')
            return redirect('device_list')
        else:
            messages.error(request, '用户名或密码错误!')
    return render(request, 'registration/login.html')

@login_required
def user_logout(request):
    """用户登出视图"""
    logout(request)
    messages.info(request, '您已成功登出。')
    return redirect('user_login')

@login_required
def device_list(request):
    """设备列表视图,只显示当前用户的设备"""
    devices = Device.objects.filter(owner=request.user)
    return render(request, 'devices/device_list.html', {'devices': devices})

@login_required
def device_create(request):
    """创建设备视图"""
    if request.method == 'POST':
        form = DeviceForm(request.POST)
        if form.is_valid():
            new_device = form.save(commit=False)
            new_device.owner = request.user # 自动设置设备所有者為当前用户
            new_device.save()
            messages.success(request, f'设备 {new_device.name} 创建成功!')
            return redirect('device_list')
    else:
        form = DeviceForm()
    return render(request, 'devices/device_form.html', {'form': form, 'title': '添加新设备'})

@login_required
def device_update(request, pk):
    """更新设备视图"""
    device = get_object_or_404(Device, pk=pk, owner=request.user) # 确保用户只能修改自己的设备
    if request.method == 'POST':
        form = DeviceForm(request.POST, instance=device)
        if form.is_valid():
            form.save()
            messages.success(request, f'设备 {device.name} 更新成功!')
            return redirect('device_list')
    else:
        form = DeviceForm(instance=device)
    return render(request, 'devices/device_form.html', {'form': form, 'title': '编辑设备'})

@login_required
def device_delete(request, pk):
    """删除设备视图"""
    device = get_object_or_404(Device, pk=pk, owner=request.user)
    if request.method == 'POST':
        device_name = device.name
        device.delete()
        messages.success(request, f'设备 {device_name} 已删除。')
        return redirect('device_list')
    return render(request, 'devices/device_confirm_delete.html', {'device': device})

第四步:创建表单 (Form)

Django 的表单可以简化 HTML 表单的创建和验证。

创建 devices/forms.py:

python 复制代码
from django import forms
from .models import Device

class DeviceForm(forms.ModelForm):
    class Meta:
        model = Device
        fields = ['name', 'ip_address', 'type', 'description']
        widgets = {
            'description': forms.Textarea(attrs={'rows': 4}),
        }
        labels = {
            'name': '设备名称',
            'ip_address': 'IP地址',
            'type': '设备类型',
            'description': '描述',
        }

第五步:设计前端页面 (Templates)

创建以下模板文件目录结构和内容。

  1. 基础模板 devices/templates/base.html:

    html 复制代码
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>设备管理系统</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container-fluid">
                <a class="navbar-brand" href="{% url 'device_list' %}">设备管理</a>
                <div class="navbar-nav ms-auto">
                    {% if user.is_authenticated %}
                        <span class="navbar-text me-3">你好,{{ user.username }}</span>
                        <form method="post" action="{% url 'user_logout' %}">
                            {% csrf_token %}
                            <button type="submit" class="btn btn-outline-light btn-sm">登出</button>
                        </form>
                    {% else %}
                        <a class="nav-link" href="{% url 'user_login' %}">登录</a>
                    {% endif %}
                </div>
            </div>
        </nav>
    
        <div class="container mt-4">
            <!-- 消息提示 -->
            {% if messages %}
                {% for message in messages %}
                    <div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
                        {{ message }}
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    </div>
                {% endfor %}
            {% endif %}
    
            <!-- 主要内容 -->
            {% block content %}
            {% endblock %}
        </div>
    
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    </body>
    </html>
  2. 登录页面 devices/templates/registration/login.html:

    html 复制代码
    {% extends 'base.html' %}
    
    {% block content %}
    <div class="row justify-content-center">
        <div class="col-md-6">
            <h2 class="mb-4">用户登录</h2>
            <form method="post">
                {% csrf_token %}
                <div class="mb-3">
                    <label for="username" class="form-label">用户名</label>
                    <input type="text" class="form-control" id="username" name="username" required>
                </div>
                <div class="mb-3">
                    <label for="password" class="form-label">密码</label>
                    <input type="password" class="form-control" id="password" name="password" required>
                </div>
                <button type="submit" class="btn btn-primary">登录</button>
            </form>
        </div>
    </div>
    {% endblock %}
  3. 设备列表页 devices/templates/devices/device_list.html:

    html 复制代码
    {% extends 'base.html' %}
    
    {% block content %}
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h2>我的设备列表</h2>
        <a href="{% url 'device_create' %}" class="btn btn-success">+ 添加新设备</a>
    </div>
    
    {% if devices %}
    <div class="table-responsive">
        <table class="table table-striped table-hover">
            <thead class="table-dark">
                <tr>
                    <th>设备名称</th>
                    <th>IP地址</th>
                    <th>类型</th>
                    <th>创建时间</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                {% for device in devices %}
                <tr>
                    <td>{{ device.name }}</td>
                    <td>{{ device.ip_address }}</td>
                    <td>{{ device.get_type_display }}</td>
                    <td>{{ device.created_at|date:"Y-m-d H:i" }}</td>
                    <td>
                        <a href="{% url 'device_update' device.pk %}" class="btn btn-sm btn-outline-primary">编辑</a>
                        <a href="{% url 'device_delete' device.pk %}" class="btn btn-sm btn-outline-danger">删除</a>
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
    {% else %}
    <div class="alert alert-info">您还没有添加任何设备。 <a href="{% url 'device_create' %}">点击添加</a></div>
    {% endif %}
    {% endblock %}
  4. 设备表单页(创建/编辑共用) devices/templates/devices/device_form.html:

    html 复制代码
    {% extends 'base.html' %}
    
    {% block content %}
    <h2 class="mb-4">{{ title }}</h2>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn-primary">保存</button>
        <a href="{% url 'device_list' %}" class="btn btn-secondary">取消</a>
    </form>
    {% endblock %}
  5. 删除确认页 devices/templates/devices/device_confirm_delete.html:

    html 复制代码
    {% extends 'base.html' %}
    
    {% block content %}
    <h2 class="mb-4">确认删除</h2>
    <p>你确定要删除设备 <strong>{{ device.name }}</strong> ({{ device.ip_address }}) 吗?此操作不可逆。</p>
    <form method="post">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">是的,删除</button>
        <a href="{% url 'device_list' %}" class="btn btn-secondary">取消</a>
    </form>
    {% endblock %}

第六步:配置路由 (URL)

  1. 应用级路由 devices/urls.py (需要创建这个文件):

    python 复制代码
    from django.urls import path
    from . import views
    
    app_name = 'devices'
    
    urlpatterns = [
        path('', views.device_list, name='device_list'),
        path('login/', views.user_login, name='user_login'),
        path('logout/', views.user_logout, name='user_logout'),
        path('new/', views.device_create, name='device_create'),
        path('<int:pk>/edit/', views.device_update, name='device_update'),
        path('<int:pk>/delete/', views.device_delete, name='device_delete'),
    ]
  2. 项目级路由 my_site/urls.py:

    python 复制代码
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', include('devices.urls')), # 将根路径指向 devices 应用的路由
    ]

第七步:运行测试

bash 复制代码
# 创建超级用户,用于登录后台和管理用户(可选,但推荐)
python manage.py createsuperuser
# 按照提示输入用户名、邮箱和密码

# 启动开发服务器
python manage.py runserver
  1. 打开浏览器访问 http://127.0.0.1:8000
  2. 你应该会被重定向到登录页面。你可以使用刚刚创建的超级用户登录。
  3. 登录成功后,你会看到设备列表页(初始为空)。
  4. 点击"添加新设备"进行测试。

功能清单验证:

· ✅ 用户登录/登出

· ✅ 设备列表显示(只显示当前用户的)

· ✅ 创建设备

· ✅ 编辑设备

· ✅ 删除设备(有确认提示)

这个系统已经具备了核心功能。你可以在此基础上继续扩展,比如添加更复杂的设备字段、实现搜索过滤、添加分页功能等。Django Admin 后台 (/admin) 也可以直接管理所有设备和用户数据。

相关推荐
嘉伟桑1 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
我叫黑大帅1 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
AskHarries2 小时前
文件上传系统
后端
止语Lab3 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活3 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困3 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn3 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530143 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908403 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端