在Django 1.7中扩展用户配置文件

时间:2015-02-26 16:58:14

标签: django django-models

我知道,这个问题在SO中已经多次被问过,但我读到的大部分答案都已过时(建议现已弃用的AUTH__PROFILE_MODULE方法),或缺乏具体的例子。

所以,我阅读了Django文档[12],但我没有关于如何正确使用它的真实示例。

事实上,我的问题出现在通过表单创建(或更新)新用户时。显然创建了用户,但扩展中的字段都未设置。我知道Django文档说明:

  

这些配置文件模型在任何方面都不是特别的 - 它们只是恰好与User模型具有一对一链接的Django模型。因此,在创建用户时不会自动创建它们,但可以使用django.db.models.signals.post_save来创建或更新相关模型。

但是,我不知道如何在实践中做到这一点(我应该添加一个receiver,如果' ',哪一个)

目前,我有以下内容(为了简洁起见,摘自文档):

档案models.py

from django.contrib.auth.models import User

class Employee(models.Model):
  user = models.OneToOneField(User)
  department = models.CharField(max_length=100)

档案admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

from my_user_profile_app.models import Employee

# Define an inline admin descriptor for Employee model
class EmployeeInline(admin.StackedInline):
  model = Employee
  can_delete = False
  verbose_name_plural = 'employee'

# Define a new User admin
class UserAdmin(UserAdmin):
  inlines = (EmployeeInline, )

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

档案forms.py

class SignupForm(account.forms.SignupForm):
  department = forms.CharField(label="Department", max_length=100)

class SettingsForm(account.forms.SignupForm):
  department = forms.CharField(label="Department", max_length=100)

然后,在我的代码中,我像这样使用它:

u = User.objects.get(username='fsmith')
freds_department = u.employee.department

但是,注册和设置表单无法按预期运行,并且未记录departement的新值。

欢迎任何提示!

4 个答案:

答案 0 :(得分:16)

我已经查看了所有答案,但没有一个确实能解决我的问题(尽管你们中的一些人给了我很好的提示,以便找到正确的方向)。我将在这里总结一下我找到的解决问题的方法。

首先,我必须承认我没有告诉我关于我的问题的一切。我想在User模型中插入额外的字段,并使用其他应用程序,例如Django的默认身份验证方案。因此,通过继承扩展默认User并设置AUTH_USER_MODEL是一个问题,因为其他Django应用程序停止正常工作(我相信他们没有使用user = models.OneToOneField(settings.AUTH_USER_MODEL)但{{{ 1}})。

因为,我正在使用其他正在使用的应用程序进行正确重写太长了,我决定通过一对一字段添加这个额外的字段。但是,文档遗漏了几点,我想填写以下内容。

因此,这是一个完整的示例,使用相同模型向user = models.OneToOneField(User)模型添加额外字段和其他应用程序。

首先,编写模型的描述,收集要添加到User文件的额外字段:

models.py

然后,我们需要在每次创建from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User) extra_field = models.CharField(max_length=100) 时触发添加对象UserProfile。这是通过将此代码附加到User文件中的正确信号来完成的:

receiver.py

现在,如果您希望能够通过管理界面对其进行修改,只需将其与from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver from my_user_profile_app.models import UserProfile @receiver(post_save, sender=User) def handle_user_save(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) 文件中的常用UserAdmin表单进行叠加即可。

admin.py

然后,现在是时候尝试将此额外字段与默认的Django身份验证应用程序混合使用。为此,我们需要添加一个额外字段,以便在from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User from my_user_profile_app.models import UserProfile # Define an inline admin descriptor for UserProfile model class UserProfileInline(admin.StackedInline): model = UserProfile can_delete = False # Define a new User admin class UserAdmin(UserAdmin): inlines = (UserProfileInline, ) # Re-register UserAdmin admin.site.unregister(User) admin.site.register(User, UserAdmin) 文件中填充SignupFormSettingsForm继承:

forms.py

而且,我们还需要添加一些代码来显示并正确获取已添加到原始import account.forms from django import forms class SignupForm(account.forms.SignupForm): extra_field = forms.CharField(label="Extra Field", max_length=100) class SettingsForm(account.forms.SignupForm): extra_field = forms.CharField(label="Extra Field", max_length=100) 模型的数据。这是通过继承到User文件中的SignupViewSettingsView视图来完成的:

views.py

一旦一切就绪,它应该很好地工作(希望如此)。

答案 1 :(得分:7)

我在这个主题上挣扎了大约一年,直到我终于找到了一个我很满意的解决方案,而且我确切地知道你的意思是什么?有很多,但它没有&#39工作"。我曾尝试以不同的方式扩展User模型,我尝试过UserProfile方法,以及其他一些1-off解决方案。

我终于想出了如何简单地扩展AbstractUser类来创建我的自定义用户模型,这对我的许多项目都是一个很好的解决方案。

所以,让我澄清你上面的一条评论,你真的不应该在2个模型之间创建一个链接,这是普遍接受的" best"解决方案是根据您的需要使用一个继承自AbstractUser或AbstractBaseUser的模型。

让我感到兴奋的一件事是"扩展用户模型"没有把我带到我想要的地方,我需要Substitute the User Model,我确定你已经多次看过/读过,但可能没有吸收它(至少我知道我没有'吨)。

一旦掌握了它,那真的没有那么多代码,它也不是太复杂。

# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    '''
    Here is your User class which is fully customizable and
    based off of the AbstractUser from auth.models
    '''
    my_custom_field = models.CharField(max_length=20)

    def my_custom_model_method(self):
        # do stuff
        return True

此后有几件事需要注意,其中一些内容出现在django 1.7中。

首先,如果您希望管理页面看起来像以前一样,则必须使用UserAdmin

# admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin

# Register your models here.
admin.site.register(get_user_model(), UserAdmin)

另一件事是,如果您想要在模型文件中导入User类,则必须从设置中导入它,而不是使用get_user_model()。如果你碰到这个,它很容易修复,所以我只想给你一个抬头。

您可以查看我用于启动项目的seed project以获得使用自定义用户模型的完整但简单的项目。用户的东西在主应用程序中。

从那里所有注册和登录的工作方式与普通的Django用户相同,所以我不会详细介绍该主题。我希望这对你有所帮助,就像它帮助了我一样!

答案 2 :(得分:6)

我尽量避免扩展用户模型,如django docs中所述。

我用这个:

class UserExtension(models.Model):
    user=models.OneToOneField(User, primary_key=True)
    ... your extra model fields come here

OneToOneField的文档:https://docs.djangoproject.com/en/1.7/topics/db/examples/one_to_one/

我看到了这些好处:

  • 相同的模式适用于其他模型(例如,组)
  • 如果你有N个应用程序,每个应用程序都可以自己扩展模型。

应该可以在不提供参数的情况下创建UserExtension。所有字段都必须具有合理的默认值。

然后,您可以创建一个信号处理程序,在创建用户时创建UserExtension个实例。

答案 3 :(得分:1)

我更喜欢扩展用户模型。例如:

class UserProfile(User):
    def __unicode__(self):
         return self.last_name + self.first_name

    department = models.CharField(max_length=100)


class SignupForm(forms.Form):
    username = forms.CharField(max_length=30)
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    department = forms.CharField(label="Department", max_length=100)

保存数据

form = UserRegistrationForm(request.POST)
    if form.is_valid():

    client = UserProfile()
    client.username = username
    client.set_password(password)
    client.first_name = first_name
    client.department = department
    client.save()

检查验证表单后如何保存数据