django reg extend - 当前事务被中止,命令被忽略直到事务块结束

时间:2014-05-16 13:03:58

标签: python django postgresql transactions registration

我正在尝试根据以下内容扩展django-registration注册表单。

Python/Django django-registration add an extra field

但我得到了:

current transaction is aborted, commands ignored until end of transaction block

在调试中,我在建议的regbackend.py中添加了断点,表明损坏的代码位于:

from crewcal.models import UserProfile
from forms import *

def user_created(sender, user, request, **kwargs):
    form = CustomRegistrationForm(request.POST)
    data = UserProfile(user=user)
    import ipdb; ipdb.set_trace();
    data.locality = form.data["locality"]
    data.save()

from registration.signals import user_registered
user_registered.connect(user_created)

问题(如下)可能与我models.py中定义的创建用户个人资料的方式有关:

def create_user_profile(sender, instance, created, raw, **kwargs):
    if created and not raw:
        print vars(instance)
        UserProfile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)

User.profile = property(lambda u: UserProfile.\
     objects.get_or_create(user=u)[0])

在上面列出的regbackend.py断点产生的shell中,我可以产生:

    > /Users/project/app/regbackend.py(8)user_created()
      7     import ipdb; ipdb.set_trace();
----> 8     data.locality = form.data["locality"]
      9     data.save()

ipdb> data
<UserProfile: gub>
ipdb> vars(data)
{'user_id': 81, 'locality': None, '_user_cache': <User: gub>, '_state': <django.db.models.base.ModelState object at 0x103eb6990>, 'receive_email': True, 'id': None}
ipdb> form.data['locality']
u'BERLIN'
ipdb> data.locality = form.data['locality']
ipdb> vars(data)
{'user_id': 81, 'locality': u'BERLIN', '_user_cache': <User: gub>, '_state': <django.db.models.base.ModelState object at 0x103eb6990>, 'receive_email': True, 'id': None}
ipdb> data.save()
DEBUG (0.001) INSERT INTO "crewcal_userprofile" ("user_id", "receive_email", "locality") VALUES (81, true, 'BERLIN') RETURNING "crewcal_userprofile"."id"; args=(81, True, u'BERLIN')
*** InternalError: current transaction is aborted, commands ignored until end of transaction block

ipdb>

并且在详细的跟踪(包括sql)之前,我得到:

[16/May/2014 07:53:50] "GET /register/ HTTP/1.1" 200 163203
DEBUG (0.003) SELECT (1) AS "a" FROM "auth_user" WHERE UPPER("auth_user"."username"::text) = UPPER('gub')  LIMIT 1; args=(u'gub',)
DEBUG (0.001) SELECT "django_site"."id", "django_site"."domain", "django_site"."name" FROM "django_site" WHERE "django_site"."id" = 1 ; args=(1,)
DEBUG (0.001) INSERT INTO "auth_user" ("username", "first_name", "last_name", "email", "password", "is_staff", "is_active", "is_superuser", "last_login", "date_joined") VALUES ('gub', '', '', 'a@a.com', 'pbkdf2_sha256$10000$E2ZiaXLRtm0k$WrmqtRAhayt8w24Jpc8FYLTwRMbzDZIWhro/n/+hLpw=', false, true, false, '2014-05-16 07:54:00.398831', '2014-05-16 07:54:00.398831') RETURNING "auth_user"."id"; args=(u'gub', '', '', u'a@a.com', 'pbkdf2_sha256$10000$E2ZiaXLRtm0k$WrmqtRAhayt8w24Jpc8FYLTwRMbzDZIWhro/n/+hLpw=', False, True, False, u'2014-05-16 07:54:00.398831', u'2014-05-16 07:54:00.398831')
DEBUG (0.001) INSERT INTO "crewcal_userprofile" ("user_id", "receive_email", "locality") VALUES (81, true, NULL) RETURNING "crewcal_userprofile"."id"; args=(81, True, None)
DEBUG (0.001) INSERT INTO "crewcal_mycustomprofile" ("about_me", "facebook_id", "access_token", "facebook_name", "facebook_profile_url", "website_url", "blog_url", "date_of_birth", "gender", "raw_data", "image", "user_id") VALUES (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '', 81) RETURNING "crewcal_mycustomprofile"."id"; args=(None, None, None, None, None, None, None, None, None, None, u'', 81)
DEBUG (0.001) SELECT (1) AS "a" FROM "auth_user" WHERE "auth_user"."id" = 81  LIMIT 1; args=(81,)
DEBUG (0.002) UPDATE "auth_user" SET "username" = 'gub', "first_name" = '', "last_name" = '', "email" = 'a@a.com', "password" = 'pbkdf2_sha256$10000$E2ZiaXLRtm0k$WrmqtRAhayt8w24Jpc8FYLTwRMbzDZIWhro/n/+hLpw=', "is_staff" = false, "is_active" = false, "is_superuser" = false, "last_login" = '2014-05-16 07:54:00.398831', "date_joined" = '2014-05-16 07:54:00.398831' WHERE "auth_user"."id" = 81 ; args=(u'gub', '', '', u'a@a.com', 'pbkdf2_sha256$10000$E2ZiaXLRtm0k$WrmqtRAhayt8w24Jpc8FYLTwRMbzDZIWhro/n/+hLpw=', False, False, False, u'2014-05-16 07:54:00.398831', u'2014-05-16 07:54:00.398831', 81)
DEBUG (0.001) INSERT INTO "registration_registrationprofile" ("user_id", "activation_key") VALUES (81, 'f4ace49b34e503f271f252cb317bfbcc86be2238') RETURNING "registration_registrationprofile"."id"; args=(81, 'f4ace49b34e503f271f252cb317bfbcc86be2238')

我已尝试将这些命令单独提供给dbshel​​l,但我无法看到问题。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

当我面对添加特殊字段或在创建用户时执行任何特殊操作时,我更愿意避免覆盖User模型并执行以下操作:

  • 您创建了一个新模型,例如Profile带有OneToOneField的用户
  • 将您想要的字段添加到该配置文件模型,例如(tlf,country,language,log ...)
  • 在创建时添加任何特殊操作,例如保存日志,存储更多信息....
  • 在管理django admin中的用户的同时创建admin.py来管理此模型(配置文件)

个人资料模型示例

class Profile(models.Model):
    user = models.OneToOneField(User)
    phone = models.CharField(max_length=255, blank=True, null=True, verbose_name='phone')
    description = models.TextField(blank=True, verbose_name='descripction')
    ...
    ...
    def not_first_log(self):  
       # Just a tiny example of a function to mark user as first-logged
       self.first_log = False
       self.save()

    class Meta:
        ordering = ['user']
        verbose_name = 'user'
        verbose_name_plural = 'users'

admin.py示例

# -*- coding: utf-8 -*-
from __future__ import unicode_literals    
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User


class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False
    filter_horizontal = ['filter fields']  # example: ['tlf', 'country',...]
    verbose_name_plural = 'profiles'
    fk_name = 'user'

class UserAdmin(UserAdmin):
    inlines = (ProfileInline, )
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
    list_filter = ('is_staff', 'is_superuser', 'is_active')

admin.site.unregister(User)  # Unregister user to add new inline ProfileInline
admin.site.register(User, UserAdmin)  # Register User with this inline profile

创建用户并将个人资料附加给他

# Create user
username = 'TestUser'
email = 'test@example.com'
passw = '1234'  
new_user = User.objects.create_user(username, email, passw)

# Create profile
phone = '654654654'
desc = 'Test user profile'
new_profile = Profile(user=new_user, phone = phone, description=desc)
new_profile.profile_role = new_u_prole
new_profile.user = new_user

# Save profile and user
new_profile.save()
new_profile.not_first_log()
new_user.save()

现在您已将此个人资料模型附加到每个用户,您可以将您希望的字段添加到个人资料模型中,例如,如果您这样做:

user = User.objects.get(id=1)

您可以访问他的个人资料:

user.profile

并调用任何函数

user.profile.function_name

您还可以获取个人资料并执行profile.user


我知道您正在尝试覆盖User模型,但我非常确定这种方式不那么复杂且易于管理,添加新字段,操作或任何您需要的内容