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

Django中预设用户外键值并禁止修改、隐藏于Admin的实现方案

解决方案:无需第三方库实现自动赋值与Admin字段隐藏

一、调整模型定义

先移除django-currentuser相关依赖,将created_by和modified_by改为普通外键,后续通过Admin方法或模型信号自动赋值当前用户。

修改后的模型代码

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.contrib.auth import get_user_model

User = get_user_model()

class Company(models.Model):
    created_by = models.ForeignKey(User, related_name='company_created_by', on_delete=models.CASCADE, blank=True, null=True)
    modified_by = models.ForeignKey(User, related_name='company_modified_by', on_delete=models.CASCADE, blank=True, null=True)
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)  # 自动更新修改时间
    name = models.CharField(max_length=150, unique=True)

    class Meta:
        verbose_name = "Company"
        verbose_name_plural = "Companies"        
    def __str__(self):
        return self.name   

class UserProfile(models.Model):
    created_by = models.ForeignKey(User, related_name='userprofile_created_by', on_delete=models.CASCADE, blank=True, null=True)
    modified_by = models.ForeignKey(User, related_name='userprofile_modified_by', on_delete=models.CASCADE, blank=True, null=True)
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"Profile for {self.user.username}"  # 可根据实际关联字段调整

二、自动赋值当前用户的两种方式

方式1:Admin层重写save_model(仅后台场景生效,简单直接)

在admin.py中配置模型管理类,重写save_model方法自动赋值,同时隐藏目标字段:

from django.contrib import admin
from .models import Company, UserProfile

@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
    list_display = ('name', 'created_by', 'modified_by', 'created_date', 'modified_date')  # 列表页展示字段
    exclude = ('created_by', 'modified_by')  # 新增/编辑页隐藏字段

    def save_model(self, request, obj, form, change):
        if not change:  # 新建记录时设置创建人
            obj.created_by = request.user
        obj.modified_by = request.user  # 每次更新都设置修改人
        super().save_model(request, obj, form, change)

@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
    list_display = ('user', 'created_by', 'modified_by', 'created_date', 'modified_date')  # 根据实际字段调整
    exclude = ('created_by', 'modified_by')

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        obj.modified_by = request.user
        super().save_model(request, obj, form, change)

方式2:模型信号(全局生效,适用于所有创建/更新场景)

如果需要在Admin以外的场景(如API、命令行)也自动赋值,可使用Django信号,同时借助中间件获取当前用户:
在模型文件末尾添加信号接收器:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.contrib.auth.middleware import get_user
from django.http import HttpRequest

# 为Company绑定信号
@receiver(pre_save, sender=Company)
def set_company_user(sender, instance, **kwargs):
    request = HttpRequest()
    user = get_user(request)
    if user.is_authenticated:
        if not instance.pk:  # 新建记录
            instance.created_by = user
        instance.modified_by = user  # 更新记录

# 为UserProfile绑定信号
@receiver(pre_save, sender=UserProfile)
def set_userprofile_user(sender, instance, **kwargs):
    request = HttpRequest()
    user = get_user(request)
    if user.is_authenticated:
        if not instance.pk:
            instance.created_by = user
        instance.modified_by = user

三、关键细节说明

  • modified_date用auto_now=True可自动更新修改时间,无需手动处理。
  • 若需在编辑页展示created_by但禁止修改,可替换exclude为readonly_fields = ('created_by', 'modified_by'),并将字段加入fields或fieldsets配置。
  • 信号方式需注意:命令行等非HTTP请求场景无用户上下文,需额外判断避免赋值失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 02:55:29