【问题标题】:Django best practices regarding custom User models关于自定义用户模型的 Django 最佳实践
【发布时间】:2021-10-20 07:57:45
【问题描述】:

这更像是一个一般性的最佳实践问题。在 Django 中启动新项目时,一般是创建自定义的 User 模型,还是依赖默认的?

如果我不弄乱默认的用户模型,我个人觉得它看起来更干净。如果我想添加任何其他属性,我觉得添加与用户具有一对一/外键关系的ProfileUserInfo 模型会更简单。

我读过很多关于 Django 的文章,但是不同意这一点。显然建议构建自定义用户模型?我很好奇每个人都在做什么,以及如果我做出这些选择中的任何一个,我到底错过了什么。

【问题讨论】:

  • 从需要额外字段的那一刻起,实现自定义用户模型通常会更干净。只要您对默认的User 模型存储的用户数据感到满意,使用User 模型会更好。虽然您可以使用 Profile 模型,但它通常会导致更多查询,并且您需要实现自动创建/更新配置文件的逻辑,这通常不是那么优雅。
  • 使用Profile 因此是否应该使用信号等不是一个好主意,因为这些信号等通常包含使发生的事情不太清楚的逻辑,此外还有一些方法规避这些信号,从而降低可靠性。
  • @WillemVanOnsem 是的,你是对的,写所有更新Profile的信号有点麻烦,谢谢你的回答!

标签: django django-models usermanager


【解决方案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)

【讨论】:

  • 有道理,感谢详细解答!
  • 我很乐意提供帮助
猜你喜欢
  • 2014-12-02
  • 2014-07-05
  • 2011-10-05
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-29
  • 1970-01-01
相关资源
最近更新 更多