0

Ok, so I've built a basic Django Project and successfuly installed the django-registration app - http://www.michelepasin.org/blog/2011/01/14/setting-up-django-registration/

I want to expand a User to include information like Birthday, Profile Picture etc. I created an app called user_profile. This is the signals.py inside the registration app:

from django.dispatch import Signal
user_activated = Signal(providing_args=["user", "request"])

From inside my new app, user_profile, what is the way to listen for this signal? I think I should create a signals.py file, but what should I write inside? a from registration.signals import user_activated statement and what else? This new app which I've created also has a model.py which I want to automatically populate with some data when a new account has been activated.

And another secondary question: when I link a URL with a class based view, which method of that class is triggered? If I have 4 methods inside inside the class based view, how django decides which one to use? Thanks

Mihai Zamfir
  • 2,167
  • 4
  • 22
  • 37
  • What are you trying to do with this signal exactly ? create a a UserProfile object when a new User is added to database ? – Agate Mar 17 '14 at 11:38
  • Yes. The UserProfile has some fields like Profile Photo, Gender, Birthday (which will not be required and will not be completed at initalization), but fields like creation_time and update_time need to be initialized. – Mihai Zamfir Mar 17 '14 at 11:46

2 Answers2

2

OKay, if I understand your problem, you'll have put something like this at the end of your user_profile/models.py file :

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

def create_user_profile(sender, instance, **kwargs):
    """ 
        Function to create user profile. 
        sender is the model class that sends the signal,
        while instance is an actual instance of that class
    """

    # your own logic here, for example :

    user = instance
    profile = UserProfile()
    profile.user = user  # link the profile to the user
    profile.save()

# connect the function to the signal, for User instances)
post_save.connect(create_user_profile, sender=User)

For your second question, many methods are called during class based views execution. In order to use class based views, your URLconf should look like this :

from myapp import views
from django.conf.urls import patterns, url

urlpatterns = patterns('',
    url(r'list_something', views.YourListView.as_view(), name="list_something"),
)

But you should not override as_view() method in your view. Depending on what you're trying to do, you'll have other methods to overwrite. I can maybe help you if you provide more info.

Agate
  • 3,152
  • 1
  • 19
  • 30
  • yes, but what if "YourListView" has 3 methods A,B and C? which one is getting executed? – Mihai Zamfir Mar 17 '14 at 12:11
  • Most of the time, if you use generic class based views, you should not have to write custom methods in your view. Please, create a new question for this point, copy paste your view code in it, and provide the link here, I'll answer you. – Agate Mar 17 '14 at 12:17
  • OK, I have edited my post. Is it ok now how my models.py looks like? – Mihai Zamfir Mar 17 '14 at 12:40
  • You miss the `post_save` import from my snippet, and you have a typo : `import datime` should be `import datetime`. Apart from that, it seems ok. Maybe you should consider adding a `related_name` ([see the docs](https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name)) attribute to your `UserProfile.user` field, to be able to query a profile from a User object. – Agate Mar 17 '14 at 12:45
  • The big picture is that I want to have a /edit_profile page for the website I am trying to build and play with. And there will be modifiable fields like first_name and last_name which will affect the User Table and Gender, Birthday etc which will affect UserProfile Table. So I connected these two tables. And I will have to combine the forms together(they'll have only 1 submit button) – Mihai Zamfir Mar 17 '14 at 12:55
  • In order to handle two forms on the same view, I think the easier solution is to create your own Class Based View (subclassing an existing one). See [this question](http://stackoverflow.com/questions/11891605/looking-for-django-class-based-views-and-having-multiple-forms-on-a-single-page) for a code sample. However, it may be better for you to split these two forms, as described in these [this answer](http://stackoverflow.com/a/6278275/2844093) – Agate Mar 17 '14 at 13:03
0

Thanks Eliot, here is what I have so far:

signals.py is now removed.

models.py:

    import datime

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

try:
    from django.utils.timezone import now as datetime_now
except ImportError:
    datetime_now = datetime.datetime.now

class UserProfileManager(models.Manager):

    def create_user_profile(self, user):
        user_profile = self.create(user = user)
        return user_profile

class UserProfile(models.Model):

    YEARS = tuple(zip(range(1900, datetime_now.year)), zip(range(1900, datetime_now.year)))
    MONTHS = (
              ('January','January'),('February','February'),('March','March'),('April','April'),
              ('May','May'), ('June','June'),('July','July'),('August','August'),
              ('September','September'),('October','October'),('November','November'), ('December', 'December')

             )
    GENDERS = (('M', 'Male'), ('F', 'Female'))

    user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
    birthday_year = models.CharField(max_length=1, blank = True,  null = True, choices=YEARS)
    birthday_month = models.CharField(max_length=1, blank = True,  null = True, choices=MONTHS)
    gender = models.CharField(max_length=1, blank = True,  null = True, choices=GENDERS)
    creation_time = models.DateTimeField(auto_now_add = True, auto_now = False)
    update_time = models.DateTimeField(auto_now_add = False, auto_now = True)

    class Meta:
            verbose_name = _('user profile')
            verbose_name_plural = _('user profiles')

    objects = UserProfileManager()

def create_user_profile(sender, instance, **kwargs):
    profile = UserProfile.objects.create_user_profile(user=instance)
    profile.save()

post_save.connect(create_user_profile, sender=User)
Mihai Zamfir
  • 2,167
  • 4
  • 22
  • 37
  • In your signal, you are not linking the UserProfile instance to a UserInstance. Please try to user the snippet I provide (copy paste it in your models.py) – Agate Mar 17 '14 at 12:15