基于Django开发多企业Web应用的两级用户架构实现方案咨询
Hey there! Let's work through this two-tier user structure problem in Django—since you already started with AbstractUser, we can build a clean, scalable solution right on top of that. Here's a step-by-step implementation that fits your requirements:
1. Model Structure: Separate Company + Linked Custom Users
First, we'll create a dedicated Company model to store enterprise details, then link your extended CustomUser model to it. We'll also add a flag to distinguish company admins (the users who can log in to manage the enterprise) from regular internal users.
# your_app/models.py from django.db import models from django.contrib.auth.models import AbstractUser class Company(models.Model): name = models.CharField(max_length=255, unique=True) address = models.TextField(blank=True, help_text="Enterprise physical address") contact_email = models.EmailField(blank=True, help_text="Official enterprise contact") # Add any other enterprise-specific fields you need def __str__(self): return self.name class CustomUser(AbstractUser): # Link user to their parent company (null=True only for initial setup) company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True) # Flag to mark if this user is the company's admin (can manage internal users) is_company_admin = models.BooleanField(default=False) # Add your existing custom fields here (phone, etc.) phone_number = models.CharField(max_length=20, blank=True) # Don't forget to update your settings to use this custom user model! # In settings.py: # AUTH_USER_MODEL = 'your_app.CustomUser'
2. Restrict Enterprise Admin Permissions
We need to ensure only company admins can access the dashboard and create internal users. We'll use a helper function and Django's user_passes_test decorator to enforce this.
# your_app/views.py from django.contrib.auth.decorators import login_required, user_passes_test # Helper to check if user is a company admin def is_company_admin(user): return user.is_authenticated and user.is_company_admin
3. Build the Company Dashboard & User Creation Flow
Next, create views for the admin dashboard (showing enterprise info and internal users) and a form to create new internal users (auto-linked to the admin's company).
Custom User Creation Form
This form will automatically assign the new user to the admin's company, and prevent setting admin privileges for internal users.
# your_app/forms.py from django import forms from django.contrib.auth.forms import UserCreationForm from .models import CustomUser class InternalUserCreationForm(UserCreationForm): class Meta: model = CustomUser fields = ('username', 'email', 'phone_number', 'password1', 'password2') def __init__(self, *args, **kwargs): # Grab the admin's company from the view context self.company = kwargs.pop('company') super().__init__(*args, **kwargs) def save(self, commit=True): user = super().save(commit=False) # Auto-link to the admin's company user.company = self.company # Ensure internal users can't become admins user.is_company_admin = False if commit: user.save() return user
Dashboard & User Creation Views
# your_app/views.py from django.shortcuts import render, redirect from .models import CustomUser from .forms import InternalUserCreationForm @login_required @user_passes_test(is_company_admin) def company_dashboard(request): # Get the admin's linked company and its internal users company = request.user.company internal_users = CustomUser.objects.filter(company=company) return render(request, 'company_dashboard.html', { 'company': company, 'internal_users': internal_users }) @login_required @user_passes_test(is_company_admin) def create_internal_user(request): if request.method == 'POST': # Pass the admin's company to the form form = InternalUserCreationForm(request.POST, company=request.user.company) if form.is_valid(): form.save() return redirect('company_dashboard') else: form = InternalUserCreationForm(company=request.user.company) return render(request, 'create_internal_user.html', {'form': form})
4. URL Configuration
Map the views to URLs, plus add login/logout routes.
# your_app/urls.py from django.urls import path from . import views from django.contrib.auth import views as auth_views urlpatterns = [ path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), path('dashboard/', views.company_dashboard, name='company_dashboard'), path('create-internal-user/', views.create_internal_user, name='create_internal_user'), ]
5. Template Examples
Company Dashboard (templates/company_dashboard.html)
<h1>{{ company.name }} Dashboard</h1> <div class="company-details"> <h2>Enterprise Info</h2> <p><strong>Address:</strong> {{ company.address }}</p> <p><strong>Contact:</strong> {{ company.contact_email }}</p> </div> <div class="internal-users"> <h2>Your Team Members</h2> {% if internal_users %} <ul> {% for user in internal_users %} <li>{{ user.username }} - {{ user.email }}</li> {% endfor %} </ul> {% else %} <p>No internal users added yet.</p> {% endif %} <a href="{% url 'create_internal_user' %}" class="btn">Add New Team Member</a> </div>
Create Internal User (templates/create_internal_user.html)
<h1>Add New Team Member for {{ request.user.company.name }}</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit" class="btn">Create User</button> </form> <a href="{% url 'company_dashboard' %}">Back to Dashboard</a>
6. Initial Setup (No Enterprise Registration)
Since you don't want public enterprise registration:
- Create your
Companyentries manually via the Django admin. - Create company admin users via the admin, link them to their company, and check the
is_company_adminflag. - These admin users can then log in and create internal users for their enterprise.
Bonus: Custom Login Redirect
To send admins to the dashboard and regular users to their profile, create a custom login view:
# your_app/views.py from django.contrib.auth.views import LoginView from django.urls import reverse class CustomLoginView(LoginView): template_name = 'login.html' def get_success_url(self): if self.request.user.is_company_admin: return reverse('company_dashboard') # Redirect regular users to their profile page return reverse('user_profile')
Then update your urls.py to use this view instead of the default.
This solution keeps your model structure clean, enforces proper permissions, and aligns perfectly with your requirements. Let me know if you need help tweaking any part!
内容的提问来源于stack exchange,提问作者Ranu Vijay

