创建扩展用户配置文件

Kai*_*Kai 46 django django-registration

我在django中有一个扩展的UserProfile模型:

class UserProfile(models.Model):
  user = models.ForeignKey(User, unique=True)
  #other things in that profile
Run Code Online (Sandbox Code Playgroud)

还有一个signals.py:

from registration.signals import user_registered
from models import UserProfile
from django.contrib.auth.models import User

def createUserProfile(sender, instance, **kwargs):
  profile = users.models.UserProfile()
  profile.setUser(sender)
  profile.save()

user_registered.connect(createUserProfile, sender=User)
Run Code Online (Sandbox Code Playgroud)

我确保信号通过以下方式注册__init__.py:

import signals
Run Code Online (Sandbox Code Playgroud)

那么应该为每个注册的用户创建一个新的UserProfile,对吧?但事实并非如此.我尝试登录时总是得到"UserProfile匹配查询不存在"错误,这意味着数据库条目不存在.

我应该说我使用django-registration,它提供user_registered信号.

重要应用程序的结构是,我有一个名为"users"的应用程序,我有:models.py,signals.py,urls.py和views.py(以及其他一些在这里无关紧要的事情) ).UserProfile类在models.py中定义.

更新:我将signals.py更改为:

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile()
        profile.user = user
        profile.save()

post_save.connect(create_profile, sender=User)
Run Code Online (Sandbox Code Playgroud)

但现在我得到了"IntegrityError":

"列user_id不是唯一的"

编辑2:

我找到了.看起来我以某种方式注册了两次信号.此处描述了解决方法:http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

我不得不添加一个dispatch_uid,现在我的signals.py看起来像这样并正在工作:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from models import UserProfile
from django.db import models

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile(user=user)
        profile.save()

post_save.connect(create_profile, sender=User, dispatch_uid="users-profilecreation-signal")
Run Code Online (Sandbox Code Playgroud)

Ago*_*gos 30

您可以使用post_save在用户上实现它:

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        profile = users.models.UserProfile()
        profile.setUser(sender)
        profile.save()

post_save.connect(create_profile, sender=User)
Run Code Online (Sandbox Code Playgroud)

编辑:
另一个可能的解决方案,经过测试和工作(我在我的网站上使用它):

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        up = UserProfile(user=user, stuff=1, thing=2)
        up.save()
post_save.connect(create_profile, sender=User)
Run Code Online (Sandbox Code Playgroud)

  • 我想必须是“profile.setUser(user)”。但后来我得到“列 user_id 不是唯一的”。对此有什么想法吗? (2认同)
  • @Agos描述如何在`create_profile`中获取`stuff`和`thing`的值是非常有帮助的. (2认同)

Tim*_*ell 6

您可以在首次访问每个用户时获取要创建的扩展配置文件:

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    additional_info_field = models.CharField(max_length=50)

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
Run Code Online (Sandbox Code Playgroud)

然后用

from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.profile.additional_info_field
Run Code Online (Sandbox Code Playgroud)

参考:http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/


小智 6

这对我有帮助:primary_key = True

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True, primary_key=True, related_name="user")
    phone = models.CharField(('phone'),max_length=30, blank=False, null=True)
    user_building = models.ManyToManyField(Building, blank=True)
    added_by = models.ForeignKey(User, blank=True, null=True, related_name="added")
Run Code Online (Sandbox Code Playgroud)

  • primary_key = True表示null = False且unique = True.https://docs.djangoproject.com/en/dev/ref/models/fields/ (2认同)

Ben*_*mes 5

当你打电话时profile.setUser(),我想你想要传递instance而不是sender作为参数.

user_registered信号文档中,sender引用User类; instance是已注册的实际用户对象.