You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中为租车系统构建权限差异化的多版本管理员?

Django实现车主专属权限管理方案

别再依赖is_superuser和is_admin了,这俩是给系统级管理员用的。咱们要实现的是基于用户与资源(车辆/订单)关联关系的数据隔离,配合自定义权限控制来打造车主专属管理界面,具体步骤如下:

一、扩展用户模型,标记车主身份

通过一对一关联给普通用户添加车主属性,用来区分普通用户、车主两类角色:

# models.py
from django.contrib.auth.models import User
from django.db import models

class OwnerProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='owner_profile')
    # 可补充车主专属字段,比如联系方式、证件信息等

    def __str__(self):
        return self.user.username

二、给业务模型绑定车主关联

让车辆、订单模型都关联到对应的车主,这是数据隔离的基础:

# models.py
class Car(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='cars')
    plate_number = models.CharField(max_length=20, verbose_name="车牌号")
    model = models.CharField(max_length=50, verbose_name="车型")
    # 其他车辆属性字段...

class Order(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='orders')
    status = models.CharField(
        max_length=20, 
        choices=[('pending', '待付款'), ('paid', '已完成付款')],
        verbose_name="订单状态"
    )
    # 其他订单属性字段...

三、自定义权限控制逻辑

1. 函数视图用装饰器控制权限

写一个装饰器,既验证用户是否是车主,又验证操作的资源是否属于当前用户:

# decorators.py
from django.http import HttpResponseForbidden

def owner_required(func):
    def wrapper(request, *args, **kwargs):
        # 验证是否是车主
        if not hasattr(request.user, 'owner_profile'):
            return HttpResponseForbidden("无访问权限")
        
        # 验证车辆归属(根据URL参数判断)
        if 'car_id' in kwargs:
            from .models import Car
            try:
                car = Car.objects.get(id=kwargs['car_id'])
                if car.owner != request.user:
                    return HttpResponseForbidden("无权访问该车辆")
            except Car.DoesNotExist:
                return HttpResponseForbidden("车辆不存在")
        
        # 验证订单归属
        if 'order_id' in kwargs:
            from .models import Order
            try:
                order = Order.objects.get(id=kwargs['order_id'])
                if order.car.owner != request.user:
                    return HttpResponseForbidden("无权访问该订单")
            except Order.DoesNotExist:
                return HttpResponseForbidden("订单不存在")
        
        return func(request, *args, **kwargs)
    return wrapper

在视图中使用装饰器,同时查询数据时自动过滤当前用户的资源:

# views.py
from django.shortcuts import render, redirect
from .decorators import owner_required
from .models import Car, Order
from django.contrib.auth.decorators import login_required

@login_required
@owner_required
def owner_dashboard(request):
    # 只加载当前车主的车辆和订单
    cars = request.user.cars.all()
    pending_orders = Order.objects.filter(car__owner=request.user, status='pending')
    paid_orders = Order.objects.filter(car__owner=request.user, status='paid')
    return render(request, 'owner/dashboard.html', {
        'cars': cars,
        'pending_orders': pending_orders,
        'paid_orders': paid_orders
    })

@login_required
@owner_required
def add_car(request):
    if request.method == 'POST':
        # 创建车辆时自动绑定当前车主
        Car.objects.create(
            owner=request.user,
            plate_number=request.POST['plate_number'],
            model=request.POST['model']
        )
        return redirect('owner_dashboard')
    return render(request, 'owner/add_car.html')

@login_required
@owner_required
def delete_car(request, car_id):
    car = Car.objects.get(id=car_id)
    car.delete()
    return redirect('owner_dashboard')

2. 类视图用Mixin控制权限

如果用类视图开发,写一个权限控制Mixin:

# mixins.py
from django.http import HttpResponseForbidden
from django.views.generic.base import ViewMixin

class OwnerAccessMixin(ViewMixin):
    def dispatch(self, request, *args, **kwargs):
        # 验证车主身份
        if not hasattr(request.user, 'owner_profile'):
            return HttpResponseForbidden("无访问权限")
        
        # 验证资源归属
        if hasattr(self, 'get_object'):
            obj = self.get_object()
            if hasattr(obj, 'owner') and obj.owner != request.user:
                return HttpResponseForbidden("无权访问该资源")
            elif hasattr(obj, 'car') and obj.car.owner != request.user:
                return HttpResponseForbidden("无权访问该资源")
        
        return super().dispatch(request, *args, **kwargs)

在类视图中使用Mixin,同时重写查询集过滤当前用户资源:

# views.py
from django.views.generic import ListView, CreateView, DeleteView
from .mixins import OwnerAccessMixin
from .models import Car
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin

class CarListView(LoginRequiredMixin, OwnerAccessMixin, ListView):
    model = Car
    template_name = 'owner/car_list.html'
    
    def get_queryset(self):
        return self.request.user.cars.all()

class CarCreateView(LoginRequiredMixin, OwnerAccessMixin, CreateView):
    model = Car
    fields = ['plate_number', 'model']
    template_name = 'owner/add_car.html'
    success_url = reverse_lazy('car_list')
    
    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super().form_valid(form)

四、路由层加固访问权限

给车主专属路由加上login_required,确保只有登录用户能访问,同时原生admin界面保持默认逻辑(仅超级用户可访问,不要给车主设置is_superuser权限):

# urls.py
from django.urls import path
from .views import owner_dashboard, add_car, delete_car, CarListView

urlpatterns = [
    path('owner/dashboard/', owner_dashboard, name='owner_dashboard'),
    path('owner/car/add/', add_car, name='add_car'),
    path('owner/car/delete/<int:car_id>/', delete_car, name='delete_car'),
    path('owner/cars/', CarListView.as_view(), name='car_list'),
]

这套方案能实现:

  • 车主仅能查看、操作自己的车辆和订单
  • 非车主用户无法进入车主管理界面
  • 车主无法访问原生admin界面

内容的提问来源于stack exchange,提问作者SIMBA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:54:56