0

I have a users app in a Django project (version 2.1 and python 3.6). After an user signup (both front end and when added in the admin dashboard ideally), I'd like to insert data in one other table. I know how to insert data, but I didn't find out how to do it right after a successfull signup.

Ideal answer would just show me how to do something like print('hello') right after an user created his account.

# users/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin

from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomUser
    list_display = ['email', 'username',]

admin.site.register(CustomUser, CustomUserAdmin)

# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm):
        model = CustomUser
        fields = ('username', 'email')

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('username', 'email')

# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # add additional fields in here
    credit = models.IntegerField(default=200) # editable=False
    def __str__(self):
        return self.email

# users/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('signup/', views.SignUp.as_view(), name='signup'),
]

# users/views.py
from django.urls import reverse_lazy
from django.views import generic

from .forms import CustomUserCreationForm

class SignUp(generic.CreateView):
    form_class = CustomUserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'signup.html'
L. Faros
  • 1,754
  • 3
  • 16
  • 35

2 Answers2

0

I think the best approach would be overriding save method of CustomUser model. For example:

class CustomUser(AbstructUser):

    def save(self, *args, **kwargs):
         user = super(CustomUser, self).save(*args, **kwargs)
         print("Hello World")
         return user

Check here in Django documentation for more details: https://docs.djangoproject.com/en/2.1/topics/db/models/#overriding-predefined-model-methods.

ruddra
  • 50,746
  • 7
  • 78
  • 101
  • The problem with using that is that it would also be called when updating an user. But for now it sounds like a fine solution. However after searching the docs I've learnt a bit more about ` @receiver(post_save, sender=User)` which seems more usefull for this specific use case – L. Faros Nov 02 '18 at 22:08
0

Use a post-save signal

https://docs.djangoproject.com/en/2.1/ref/signals/

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

@receiver(post_save, sender=User)
def say_hello(sender, instance, **kwargs):
     if instate._state.adding:
        print('hello')

Signal is better than a method on the view because the User may be created some way other than through the view e.g , via the shell, a management command, a migration, a different view, etc.

Note the _state is not "private" so don't feel bad about using it, it's just named that way to avoid clashing with field names.

Check _state instead of more common checking instance.pk because instance.pk is always present when primary key is a natural key rather than AutoField

Rich Tier
  • 9,021
  • 10
  • 48
  • 71
  • This seems like the solution for me but sadly it doesn't seems to works, I put this code in users/models.py and changed `sender=User` to `sender=CustomUser`. (Also you have a typo on `instate._state.adding:`, guess you meant `instance` :) – L. Faros Nov 03 '18 at 14:59
  • Well got it partially working : the `instance._state` doesn't seems to be `True` since the `hello` is not printed but calling `print` before it works. Would like to figure out why before accepting this answer – L. Faros Nov 03 '18 at 15:13
  • Well, found out I can do this : `say_hello(sender, instance, created, **kwargs):` and then use `created` in place of `instate._state.adding` – L. Faros Nov 03 '18 at 15:20