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

基于Django搭建多公司库存管理系统的权限控制问题

Django多企业库存管理系统的权限与Auth实现方案

一、核心数据模型设计

先明确企业-用户-库存的关联逻辑,用OneToMany关系实现数据隔离:

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

class Company(models.Model):
    name = models.CharField(max_length=100, unique=True)
    # 可扩展企业信息:地址、联系人等
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

# 扩展Django用户模型,绑定所属企业
class User(AbstractUser):
    company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True)
    # 可选:区分企业内角色
    ROLE_CHOICES = (
        ('admin', '企业管理员'),
        ('staff', '普通员工'),
    )
    role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='staff')

class Inventory(models.Model):
    name = models.CharField(max_length=200)
    quantity = models.IntegerField()
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    # 可扩展库存信息:规格、入库时间等

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

记得在settings.py中配置自定义用户模型:

AUTH_USER_MODEL = 'your_app.User'

二、用户认证与注册逻辑

  1. 企业注册:先创建Company实例,再为该企业创建管理员账号并绑定企业。
  2. 员工注册:由企业管理员创建,或注册时强制选择所属企业(可限制仅企业管理员能添加员工)。
  3. 登录验证:直接使用Django自带认证系统,登录后用户对象会携带company属性,用于后续权限判断。

三、核心权限控制实现

1. 视图层:自定义Mixin实现自动数据过滤

创建通用Mixin,让需权限控制的视图继承,自动筛选当前用户所属企业的数据:

# mixins.py
from django.contrib.auth.mixins import LoginRequiredMixin

class CompanyPermissionMixin(LoginRequiredMixin):
    def get_queryset(self):
        # 过滤当前用户企业的所有数据
        queryset = super().get_queryset()
        return queryset.filter(company=self.request.user.company)

    # 表单提交时自动绑定当前企业
    def form_valid(self, form):
        form.instance.company = self.request.user.company
        return super().form_valid(form)

使用示例(库存列表/创建视图):

# views.py
from django.views.generic import ListView, CreateView
from .models import Inventory
from .mixins import CompanyPermissionMixin

class InventoryListView(CompanyPermissionMixin, ListView):
    model = Inventory
    template_name = 'inventory/list.html'

class InventoryCreateView(CompanyPermissionMixin, CreateView):
    model = Inventory
    fields = ['name', 'quantity']
    template_name = 'inventory/create.html'
    success_url = '/inventory/list/'

2. 模板层:角色权限判断(可选)

在模板中根据用户角色展示对应操作:

{% if user.role == 'admin' %}
    <a href="{% url 'inventory_create' %}">新增库存</a>
{% endif %}

{% for item in object_list %}
    <div>{{ item.name }} - 数量: {{ item.quantity }}</div>
{% endfor %}

3. 管理后台权限限制

修改Admin配置,让企业管理员仅能查看/操作本企业数据:

# admin.py
from django.contrib import admin
from .models import Company, User, Inventory

class UserAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # 超级管理员可见所有用户,企业管理员仅见本企业用户
        if request.user.is_superuser:
            return qs
        return qs.filter(company=request.user.company)

    # 限制企业管理员只能添加本企业员工
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'company' and not request.user.is_superuser:
            kwargs['queryset'] = Company.objects.filter(id=request.user.company.id)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

class InventoryAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(company=request.user.company)

admin.site.register(Company)
admin.site.register(User, UserAdmin)
admin.site.register(Inventory, InventoryAdmin)

四、额外优化点

  • 用Django的permission_required装饰器,为企业管理员分配特定操作权限(如新增/修改库存)。
  • 若开发API(基于DRF),可自定义权限类:
from rest_framework.permissions import BasePermission

class IsSameCompany(BasePermission):
    def has_object_permission(self, request, view, obj):
        return obj.company == request.user.company

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:23:17