关于自定义用户模型的Django最佳实践

3
这更像是一个通用的最佳实践问题。在Django中启动新项目时,您一般会创建自定义用户模型还是依赖默认模型?
个人而言,如果我不去修改默认的用户模型,那么它会更加清晰。如果我想要添加任何其他属性,我觉得添加一个具有与用户一对一/外键关系的“Profile”或“UserInfo”模型更简单。
然而,我读过许多关于Django的文章,它们并不同意这种做法。显然,建议构建自定义用户模型?我很好奇每个人都在做什么,以及如果我做出这些选择,究竟会错过什么。

从你需要额外字段的那一刻起,实现一个自定义用户模型通常更加清晰。只要你对默认的User模型存储的用户数据满意,使用User模型会更好。虽然你可以使用Profile模型,但通常会导致更多的查询,并且你需要实现逻辑来自动创建/更新个人资料,这通常不太优雅。 - undefined
因此,如果需要使用信号等功能,使用“Profile”并不是一个好主意,因为这些信号往往包含了使情况变得不太清晰的逻辑。此外,还有方法可以规避这些信号,从而降低了可靠性。 - undefined
@WillemVanOnsem 是的,你说得对,写所有更新Profile的信号有点麻烦,谢谢你的回答! - undefined
2个回答

3
自定义用户模型是一种好的实践,当您需要添加新字段或逻辑到用户模型时(例如使用电子邮件而不是用户名登录或添加新权限)。 如果您的应用程序很简单,而且不需要添加新字段,则可以使用默认用户模型。 另一种解决方案是保持用户模型不变,并创建一个“用户配置文件”模型,该模型具有与用户的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)

明白了,感谢你详细的回答! - undefined
我很高兴能够帮助。 - undefined

0
SOLID原则:单一职责设计模式建议拥有用户模型和个人资料模型,每个模型只应承担一个职责。这样可以更轻松地管理代码,并将潜在的错误最小化。
以下是一些关于SOLID设计原则的更多信息的优秀资源: https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/

https://www.tutorialspoint.com/design_pattern/singleton_pattern.htm

同时也是设计模式的绝佳资源: https://youtube.com/playlist?list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc

(基于Eric Freeman和Elisabeth Robson的《Head First Design Patterns:构建可扩展和可维护的面向对象软件》一书。

这些都是面向对象编程的一些重要原则。大多数示例都是使用Java编写的,但是这些概念可以应用于任何语言。我希望这些对您未来的项目有所帮助。这将使您更容易理解代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接