Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django reg extend - current transaction is aborted, commands ignored until end of transaction block

I am trying to extend the django-registration register form according to:

Python/Django django-registration add an extra field

but I am getting:

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

In debugging I have added a breakpoint in the suggested regbackend.py which suggests the broken code is at:

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)

The problem (below), may have something to do with the way user profiles are created as defined in my 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])

In the shell arising from the regbackend.py breakpoint listed above, I can produce:

    > /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>

and in the verbose trace (incl. sql) up to that point, I get:

[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', '', '', '[email protected]', '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'[email protected]', '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" = '[email protected]', "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'[email protected]', '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')

I have tried feeding these commands in separately to dbshell, but I can't see the problem.

Any ideas?

like image 555
KindOfGuy Avatar asked May 16 '14 13:05

KindOfGuy


1 Answers

When I face with something like adding special fields, or do any special action when creating an user I prefer to avoid overwrite User model and do like:

  • You create a new model, for example Profile with a OneToOneField to user
  • Add your desired fields to that profile model, such as (tlf, country, language,log...)
  • Add any special action on create, such as save a log, store more info....
  • Create admin.py to manage this model (profile) at the same time you manage users in django admin

Profile Model Example

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 example

# -*- 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 an user and attach a profile to him

# Create user
username = 'TestUser'
email = '[email protected]'
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()

Now you'll have this Profile model attached to each user, and you could add the fields you wish to Profile Model, and for example if you make:

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

you can access to his profile doing:

user.profile

and to call any function

user.profile.function_name

You can also get the profile and do profile.user


I know you're trying to overwrite User model but I'm pretty sure this is way is less complex and easy to manage, add new fields,actions or whatever you need

like image 155
AlvaroAV Avatar answered Oct 30 '22 20:10

AlvaroAV