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

Django模型save()方法如何获取request.user 或在视图中拿到生成的随机密码

解决方案

以下提供两种可行实现思路,同时会修正原代码中存在的明文存储密码的潜在问题。

方案1:传递request到save方法

Django模型层默认不持有请求上下文,你可以手动将request作为自定义参数传入save方法:

修改save方法

def save(self, *args, request=None, **kwargs):
    if self._state.adding:
        super(Machine, self).save(*args, **kwargs)
        username = f"machine_{slugify(self.site.client.name).lower()}_{self.id}"
        password = User.objects.make_random_password()
        # 注意:不要用create,要用create_user才会自动对密码做哈希处理
        self.user = User.objects.create_user(
            username=username,
            password=password
        )
        # 将生成的密码存为实例临时属性,方便外部调用时获取
        self.generated_password = password
        
        super(Machine, self).save(update_fields=['user'])

        # 传入了request才执行发邮件逻辑
        if request:
            send_mail(
                f'Password of {username}',
                f'Password: {password}',
                settings.DEFAULT_FROM_EMAIL,
                [request.user.email],
                fail_silently=True,
            )
    else:
        super(Machine, self).save(*args, **kwargs)

视图/Admin中调用时传参

  • 普通视图调用示例:
# 视图层创建实例时传入当前request
machine = Machine(字段名=字段值)
machine.save(request=request)
# 直接从实例属性获取生成的随机密码
pwd = machine.generated_password
  • 如果你使用Django Admin操作,需要重写Admin类的save_model方法传递request:
from django.contrib import admin
from .models import Machine

class MachineAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(request=request)

admin.site.register(Machine, MachineAdmin)

方案2:抽离业务逻辑到模型层外(更推荐)

Django设计原则中模型层本就应该和请求上下文解耦,把创建关联用户、发邮件的逻辑从save方法中抽离到视图层/服务层,耦合性更低、后续维护更方便:

简化模型save方法

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)

视图层实现完整业务逻辑

def create_machine(request):
    # 1. 创建Machine实例
    machine = Machine(
        site=你的site实例,
        # 其他字段填充
    )
    machine.save()

    # 2. 生成关联用户
    username = f"machine_{slugify(machine.site.client.name).lower()}_{machine.id}"
    password = User.objects.make_random_password()
    machine.user = User.objects.create_user(username=username, password=password)
    machine.save(update_fields=['user'])

    # 3. 直接在视图层发邮件,无需传递request
    send_mail(
        f'Password of {username}',
        f'Password: {password}',
        settings.DEFAULT_FROM_EMAIL,
        [request.user.email],
        fail_silently=True,
    )
    # 可直接获取密码做其他业务处理
    return HttpResponse(f"实例创建完成,关联用户密码为:{password}")

重要提醒:原代码中直接使用User.objects.create传入password参数会导致密码明文存储在数据库中,既不符合安全要求也会导致后续用户无法正常登录,必须替换为User.objects.create_user方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:36:04