关于自定义用户模型的 Django 最佳实践
Posted
技术标签:
【中文标题】关于自定义用户模型的 Django 最佳实践【英文标题】:Django best practices regarding custom User models 【发布时间】:2021-10-20 07:57:45 【问题描述】:这更像是一个一般性的最佳实践问题。在 Django 中启动新项目时,一般是创建自定义的 User 模型,还是依赖默认的?
如果我不弄乱默认的用户模型,我个人觉得它看起来更干净。如果我想添加任何其他属性,我觉得添加与用户具有一对一/外键关系的Profile
或UserInfo
模型会更简单。
我读过很多关于 Django 的文章,但是不同意这一点。显然建议构建自定义用户模型?我很好奇每个人都在做什么,以及如果我做出这些选择中的任何一个,我到底错过了什么。
【问题讨论】:
从需要额外字段的那一刻起,实现自定义用户模型通常会更干净。只要您对默认的User
模型存储的用户数据感到满意,使用User
模型会更好。虽然您可以使用 Profile
模型,但它通常会导致更多查询,并且您需要实现自动创建/更新配置文件的逻辑,这通常不是那么优雅。
使用Profile
因此是否应该使用信号等不是一个好主意,因为这些信号等通常包含使发生的事情不太清楚的逻辑,此外还有一些方法规避这些信号,从而降低可靠性。
@WillemVanOnsem 是的,你是对的,写所有更新Profile
的信号有点麻烦,谢谢你的回答!
【参考方案1】:
当您必须向用户模型添加新字段或逻辑(例如使用电子邮件而不是用户名登录或添加新权限)时,自定义用户模型是一种很好的做法。 如果您的应用程序很简单并且您不必添加新字段,则可以使用默认用户模型。 其他解决方案是保持用户模型完整并创建一个与用户具有 OneToOne 关系的“用户配置文件”模型,但您必须手动创建配置文件并将其添加到用户,或者可能使用 django 信号来创建用户配置文件每次创建新用户时。 我个人不推荐最后一个解决方案。 因此,如果您必须添加新字段或逻辑,则应创建自定义用户模型,否则请坚持使用默认用户模型。 如果您使用自定义模型,请记住将新字段添加到管理站点 这是一个例子
class User(AbstractUser):
worker = models.OneToOneField(WorkerModel, on_delete=models.CASCADE,
related_name="user", verbose_name=_("Trabajador"), null=True, blank=True)
job = models.CharField(verbose_name="Cargo",max_length=50, null=True, blank=True)
department = models.CharField(verbose_name="Departamento",max_length=50, null=True, blank=True)
avatar = models.ImageField(verbose_name="Imagen", upload_to="user_avatar",
null=True, blank=True)
class Meta:
default_permissions = ()
verbose_name="Usuario"
verbose_name_plural="Usuarios"
permissions = (
("secretario", "Secretario(a)"),
("director", "Director"),
)
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User #, UserProfileModel
from django.utils.translation import gettext, gettext_lazy as _
class UserAdminInherited(UserAdmin):
autocomplete_fields = ['worker']
fieldsets = (
(None, 'fields': ('username', 'password')),
(_('Personal info'), 'fields': ('first_name', 'last_name', 'email','job','department','avatar')),
(_('Worker info'), 'fields': ('worker',)),
(_('Permissions'),
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
),
(_('Important dates'), 'fields': ('last_login', 'date_joined')),
)
admin.site.register(User, UserAdminInherited)
【讨论】:
有道理,感谢详细解答! 我很乐意提供帮助以上是关于关于自定义用户模型的 Django 最佳实践的主要内容,如果未能解决你的问题,请参考以下文章
Django - 异常处理最佳实践和发送自定义错误消息 [关闭]