pythondjangoweb

Create a Profile model for a specific user (Django 4.0)?


Does anybody know how to create a Profile for the user upon completion of the registration form??? (Django)

views.py:

class UserRegisterView(generic.CreateView):
    form_class = SignUpForm #Imported from forms
    template_name = 'registration/register.html'
    success_url = reverse_lazy('login')

    def form_valid(self, form):
        response = super().form_valid(form)
        return response 

models.py


class Profile(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    #rpg_class = models.CharField(max_length=100)

    def __str__(self):
        return str(self.user)    

                                                                      
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

I tried this and it doesnt work, It says something like

Internal Server Error: /CodeRPGappMain/register/
Traceback (most recent call last):
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\base.py", line 328, in execute
    return super().execute(query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: CodeRPGappMain_profile.bio

Making a Profile manually in the admin isnt going to work So I need it to create itself automatically every time a user signs up, it already creates a user bc of Djangos built in stuff but I need to create its custom model Profile for the user upon completion


Solution

  • The reason this (likely) does not work is because your Profile has a bio field that is not null=True [Django-doc], and has no default=… [Django-doc], hence when creating your Profile, it has no value to fill in for bio.

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance, bio='')

    It is possible that there are additional fields that you will need to set manually, or you define a default=… value.

    Regardless, using signals is often not a good idea. Signals for example do not work when you create or update items in bulk. You can just use the view and override the admin, without signals:

    class UserRegisterView(generic.CreateView):
        form_class = SignUpForm  # Imported from forms
        template_name = 'registration/register.html'
        success_url = reverse_lazy('login')
    
        def form_valid(self, form):
            response = super().form_valid(form)
            Profile.objects.create(user=self.object, bio='')
            return response

    and in the admin with:

    # app_name/admin.py
    
    from django.contrib import admin
    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    
    admin.site.unregister(User)
    
    
    @admin.register(User)
    class ArticleAdmin(admin.ModelAdmin):
        def save_model(self, request, obj, form, change):
            super().save_model(request, obj, form, change)
            if obj._state.adding:
                Profile.objects.create(user=obj, bio='')