Friday, May 30, 2014

Registration extend nightmare

I am trying to add an extra user profile registration field using registration. Should be so simple but this is bringing me to the edge.

Here's my stackoverflow question with bounty: https://stackoverflow.com/questions/23695713/django-reg-extend-current-transaction-is-aborted-commands-ignored-until-end-o


Basically I want to add a 'city' field to the registration form. I have tried many solutions, but am currently attempting versions of this: http://dmitko.ru/django-registration-form-custom-field/

In my app I have a backend regbackend.py relying on django-registration's signals:

______________________________________________

from forms import *
from models import UserProfile
from django.db.models.signals import post_save


def user_created(sender, user, request, **kwargs):
new_user = RegistrationProfile.objects.get(us)
    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
import crewcal.models
user_registered.connect(user_created)
______________________________________________


The related models:

______________________________________________

class Locality(models.Model):
    locality = models.CharField(max_length=50)

    def __unicode__(self):
        return self.locality

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    event_commitments = models.ManyToManyField(Event,
        null=True, blank=True)
    receive_email = models.BooleanField(default=True)
    locality = models.ManyToManyField(Locality,
        null=True, blank=True)

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

    @property
    def url(self):
        return self.get_absolute_url()

    @models.permalink
    def get_absolute_url(self):
        return ('crewcal.views.profile', [str(self.id)])

userprofile_created = django.dispatch.Signal(providing_args=["user", "request"])

def create_user_profile(sender, instance, created, raw, **kwargs):
    if created and not raw:
        UserProfile.objects.create(user=instance)
        profile = UserProfile.objects.get(user=instance)
        userprofile_created.send(sender=UserProfile,
            user=instance, request=request)

post_save.connect(create_user_profile, sender=User)

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


I get a mixture of errors (dependent on the slight tweaks I make), such as:

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

and:

"<UserProfile: ppokkutt>" needs to have a value for field "userprofile" before this many-to-many relationship can be used.

This last message suggests to me that the UserProfile is not saved before the signal is sent (from the django-registration plugin) to the custom backend (regbackend.py above) which attempts to update that non-existent entry with the locality. Here is the relevant code from django-registration views.py:
______________________________________________

    def register(self, request, **cleaned_data):

        """

        Given a username, email address and password, register a new

        user account, which will initially be inactive.


        Along with the new ``User`` object, a new

        ``registration.models.RegistrationProfile`` will be created,

        tied to that ``User``, containing the activation key which

        will be used for this account.


        After the ``User`` and ``RegistrationProfile`` are created and the activation email is sent, the signal

        ``registration.signals.user_registered`` will be sent, with

        the new ``User`` as the keyword argument ``user`` and the

        class of this backend as the sender.

        """

        username, email, password = cleaned_data['username'], cleaned_data['email'], cleaned_data['password1']

        if Site._meta.installed:

            site = Site.objects.get_current()

        else:

            site = RequestSite(request)

        new_user = RegistrationProfile.objects.create_inactive_user(username, email, password, site)

        signals.user_registered.send(sender=self.__class__,

                                     user=new_user,

                                     request=request)

        return new_user

______________________________________________
and from models.py:

______________________________________________

    def create_inactive_user(self, username, email, password,

                             site, send_email=True):

        """

        Create a new, inactive ``User``, generate a

        ``RegistrationProfile`` and email its activation key to the

        ``User``, returning the new ``User``.

        By default, an activation email will be sent to the new

        user. To disable this, pass ``send_email=False``.

        """

        new_user = User.objects.create_user(username, email, password)

        new_user.is_active = False

        new_user.save()

        registration_profile = self.create_profile(new_user)

        if send_email:

            registration_profile.send_activation_email(site)

        return new_user

    create_inactive_user = transaction.commit_on_success(create_inactive_user)

______________________________________________


Any thoughts would be much appreciated!
Matt

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/32e0edb8-5ff8-427f-bc69-6766b774011d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment