首页 > 解决方案 > 在 Django 中为预注册用户创建用户帐户

问题描述

我有一个网站,它有一个注册系统和一个有一些注册用户的博客。昨天,我添加了一个新应用程序,为每个用户创建专用的个人资料页面。

问题是,没有为已经注册的用户创建个人资料页面。我猜这是因为用户配置文件创建逻辑仅允许在用户注册后创建配置文件。

下面是我的models.py中的代码

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_account(sender, instance, created, *args, **kwargs):
    if created:
        profile, new = UserAccount.objects.get_or_create(user=instance)

post_save.connect(create_account, sender=settings.AUTH_USER_MODEL)

那么,我可以做些什么来创建这些个人资料页面?

我尝试了以下方法:
1. 针对每个注册用户的用户名手动创建个人资料页面。(但这不是我想依靠的方式。这只是一个临时安排)

与此相关的问题是,当创建这些个人资料页面的超级用户调用他的私人个人资料页面 [at /u/] 时,代码会查看由超级用户而不是他自己创建的所有用户。

这是显示的错误:

MultipleObjectsReturned at /u/

get() returned more than one UserAccount -- it returned 2!

.
.
.
instance = get_object_or_404(UserAccount)

那么,这里的代码有什么问题?[我的意见.py]

# public user profile
def user_account(request, username):
    instance = get_object_or_404(UserAccount, user__username=username)
    context = {
    'instance'  : instance,
    'title'     : "User Account",       
    }
    template = "user_accounts/public_account.html"
    return render(request, template, context)

# private user profile.
@login_required
def self_user_account(request):
    if not request.user.is_authenticated:
        raise Http404

    instance = get_object_or_404(UserAccount)

    if not request.user == instance.user:
        raise Http404

    context = {
        'instance'  : instance,
        'title'     : 'Your Account',
    }   

    template = "user_accounts/self_account.html"
    return render(request, template, context)

# ability to update the user profile
@login_required
def update_user_account(request):
    if not request.user.is_authenticated:
        raise Http404

    instance = get_object_or_404(UserAccount)

    if not request.user == instance.user:
        raise Http404

    if request.method == 'POST':
        form = UserAccountForm(request.POST or None, request.FILES or None, instance=instance)
        if form.is_valid():
            instance = form.save(commit=False)
            instance.save()
            messages.success(request, "Account Updated.")
            return HttpResponseRedirect("/u/")
        else:
            messages.error(request, "Something went wrong. Profile not created.")
    else:
        form = UserAccountForm(instance=instance)

    context = {
        'title': 'Update Your Account',
        'form' : form,
    }
    template = "user_accounts/update.html"
    return render(request, template, context)

下面是我的urls.py这些是在主urls.py的 /u/ 之后填充的

urlpatterns = [
    # for updating
    url(r'^update/$', views.update_user_account, name="update_user_account"),
    # for outside world
    url(r'^(?P<username>[\w.@+-]+)/$', views.user_account, name="public_user_account"),
    # for the user himself 
    url(r'^$', views.self_user_account, name="self_user_account"),
]

下面是我的models.py脚本

# uploading profile photos
def upload_location(instance, filename):
    return "account_photos/%s/%s" %(instance.user, filename)

# Create your models here.
class UserAccount(models.Model):
    user            = models.OneToOneField(User)
    photo           = models.ImageField(
                        upload_to=upload_location, # there needs to be a upload location tho
                        # most probably a cdn server
                        blank=True,
                        null=True, 
                        width_field="width_field",
                        height_field="height_field")
    width_field     = models.IntegerField(default=0, null=True)
    height_field    = models.IntegerField(default=0, null=True)
    bio             = models.TextField(max_length=60, null=True, blank=True, verbose_name="You in 60 words.")
    phone           = PhoneNumberField(blank=True, verbose_name="Contact Number")
    status          = models.CharField(max_length=128, default="Student")
    totos           = models.IntegerField(default=0, verbose_name="Contribution")
    user_since      = models.DateTimeField(auto_now=True)

    # social links
    email           = models.EmailField(verbose_name="email address", 
                                        max_length=255,
                                        unique=True,
                                        null=True, blank=True)
    custom_link     = models.URLField(null=True, blank=True)
    facebook_link   = models.URLField(null=True, blank=True)
    twitter_link    = models.URLField(null=True, blank=True)
    linkedin_link   = models.URLField(null=True, blank=True)
    github_link     = models.URLField(null=True, blank=True)
    reddit_link     = models.URLField(null=True, blank=True)



    def __str__(self):
        return self.user.username

    def get_absolute_url(self):
        return self.reverse("accounts:public_user_account", kwargs={"username":self.user__username})

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User) # User is coming from the user=models.OneToOneField(<User>)
def create_account(sender, instance, created, *args, **kwargs):
    if created:
        profile, new = UserAccount.objects.get_or_create(user=instance)

post_save.connect(create_account, sender=settings.AUTH_USER_MODEL)

标签: pythondjangodjango-views

解决方案


使用get_object_or_404(UserAccount)使用所有用户帐户,因此MultipleObjectsReturned如果存在多个用户帐户,则会出错。

您需要过滤查询集,使其仅返回一个对象。您已经在使用用户名来执行此操作。只要用户名是唯一的并且每个用户只有一个用户帐户,这应该可以工作。

get_object_or_404(UserAccount, user__username=username)

如果要过滤登录用户,可以执行以下操作:

get_object_or_404(UserAccount, user=request.user)

或者,根据您的模型,您可能能够向后跟踪一对一字段,例如:

instance = request.user.useraccount

推荐阅读