Django用户资料

42

当向用户配置文件添加额外字段时,如位置、性别、雇主等,我应该向django.contrib.auth.models.User添加额外列并将其保存在那里吗?还是应该创建一个新表来保存用户配置文件信息?

另外,当用户上传个人资料图片时,我应该将其保存在同一表中吗?(请注意这不是生产服务器,我只是在本地运行服务器以解决问题)。谢谢。


可能是 在 Django 中使用自定义字段扩展用户模型 的重复问题。 - Ciro Santilli OurBigBook.com
9个回答

48

你需要为用户配置文件建立一个模型:

class UserProfile(models.Model):  
    user = models.ForeignKey(User, unique=True)
    location = models.CharField(max_length=140)  
    gender = models.CharField(max_length=140)  
    employer = models.ForeignKey(Employer)
    profile_picture = models.ImageField(upload_to='thumbpath', blank=True)

    def __unicode__(self):
        return u'Profile of user: %s' % self.user.username

然后在 settings.py 中进行配置:

AUTH_PROFILE_MODULE = 'accounts.UserProfile'

谢谢,这让我成功了。但是我该如何在admin.py中访问User的字段呢?我正在尝试为UserProfile设置ModelAdmin,并尝试像这样访问User字段:'user__last_name'。但是我收到了这个错误:'user__last_name'不是'UserAdmin'的可调用或属性,也没有在模型'UserProfile'中找到。我该如何访问这些元素? - Matt
10
或许值得一提的是,在这种情况下,与用户使用OneToOne的方式比使用ForeignKey(unique=True)更好。 - Dmitry
12
使用ForeignKey而不是OneToOne被扣除1分,@Dmitry给出了更好的答案。同时,AUTH_PROFILE_MODULE是一个遗留设置,在Django 1.5及以上版本中不需要。 - Tom
7
AUTH_PROFILE_MODULE已被弃用。 - Flimm
请问 class UserProfile 应该定义在哪个文件中?目前,我们的 class MyUser(AbstractBaseUser) 已经定义在 models.py 文件中。UserProfile 是否应该放在同一个文件中? - Cheok Yan Cheng

39

从概念上讲,OneToOneField与带有unique = True的ForeignKey类似,但关系的“反向”端将直接返回单个对象。这是扩展User类的推荐方式。

class UserProfile(models.Model):  
    user = models.OneToOneField(User)
    ...

非常干净的解决方案 - semaph0r
1
建议使用 settings.AUTH_USER_MODEL 而不是 User。 - Klaas van Schelven

18

目前的Django版本为1.9,下面是对过时的被接受答案的一些更新:

  1. 使用 models.OneToOneField(User)
  2. 添加 related_name='profile'
  3. 对于Python 3,使用.__str__().format()

如下所示:

class UserProfile(models.Model):  
    user = models.OneToOneField(User, related_name='profile')
    location = models.CharField(max_length=140)  
    gender = models.CharField(max_length=140)  
    ...

    def __str__(self):
        return 'Profile of user: {}'.format(self.user.username)

通过使用related_name,您可以轻松访问用户的个人资料,例如 request.user

request.user.profile.location
request.user.profile.gender

无需额外查找。


它能够工作,但是当我登录到Django管理面板时,显示错误,用户没有配置文件。我的函数正常工作,但我无法访问我的管理面板。 - usman imtiaz


11

从Django 1.5开始,您可以使用一个简单的设置项将默认的用户替换为自定义用户对象:

AUTH_USER_MODEL = 'myapp.MyUser'

详细信息请查看Django文档条目


4
每个人都应该注意“auth”部分。头像和简介不应该在AUTH_USER_MODEL中。除非你想将类似kerberos的东西集成到用户认证中,否则我建议使用django.contrib.auth。在Django 1.5+中,一个与User一对一的模型应该是处理方式。地点、性别、雇主等不是有效的认证参数,不应该添加到自定义用户模型中。 - Tom
点赞链接到官方文档(目前最新版本)。我很感激这一点,因为这是一个问题,似乎互联网存储曾经好的框架答案的巨大能力导致了混乱的杂乱无章。 :) - John Lockwood
1
@JohnLockwood 刚刚更新了链接,所以它应该可以使用多年了 :P - Nicu Surdu

5
我找到了一个解决方案在这里。基本上,您只需扩展默认表单UserCreationForm,但保持相同的名称。这与Django文档中告诉您如何进行UserProfiles操作的方式完全兼容。

2

答案可以更新以添加信号接收器,如果配置文件不存在,则创建配置文件,如果已存在,则进行更新。

@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

这篇https://simpleisbetterthancomplex.com/tutorial/2016/11/23/how-to-add-user-profile-to-django-admin.html文章还介绍了如何在管理面板中编辑和列出自定义配置文件。


2

当前的两个最佳答案已经过时。

如果您直接引用User(例如通过在外键中引用它),则您的代码将无法在将AUTH_USER_MODEL设置更改为不同用户模型的项目中工作。[..] 不要直接引用User [..] 当您定义对用户模型的外键或多对多关系时,应使用AUTH_USER_MODEL设置指定自定义模型。

from django.conf import settings
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="userprofile",
    )

https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#referencing-the-user-model


2
如果您想从用户对象中获取用户配置文件数据。
from django.contrib.auth.models import User
request.user.profile

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