Search code examples
djangodjango-allauth

How to customise user profile fields in allauth after signup


I used allauth to signup function in my web application. In the socialaccount signup is collected from users e-mail, password, first and last name. In the sign in form I just collect e-mail and password from users.

Once logged, my app redirects the user to a profile page where is supposed to him/her update her profile (including new and customised fields, as the "institution" I added), if him/she wants to do so.

The question as a beginner in django-allauth, I'd like to know how to add these new customised fields to my user profile, and how to update those data once the user signed up.

what I did till now:

In settings.py

AUTH_USER_MODEL = 'auth.User'

In my_project/models.py

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

class UserProfile(models.Model):

    institution = models.TextField(max_length=254)

In profile_page.html

{% extends 'base.html' %}
{% block title %}Profile Page{%endblock title%}

{% if user.is_authenticated %}

{%block body%}

    <div class="col-md-6" >
        <div class="panel panel-default">
            <div class="panel-body">
                <h1 class="text-center"><b>MY ONTOLOGIES</b></h1><br>
            </div>
        </div>
    </div>
    <div class="col-md-6" >
        <div class="panel panel-default">
            <div class="panel-body">
                <h1 class="text-center"><b>MY PROFILE</b></h1><br>
                    <div class="form-group">
                        {% csrf_token %}
                        <label for="id_login" class="col-sm-2 control-label">E-mail:</label>
                        <div class="col-sm-10">
                            <input type="email" id="asd" value="{{user.email}}" name="login"   class="form-control" required />
                        </div><br><br>
                        <label for="first_name" class="col-sm-2 control-label">First Name:</label>
                        <div class="col-sm-10">
                            <input type="text" id="id_first_name" value="{{user.first_name}}" name="first_name" class="form-control" required />
                        </div><br><br>
                        <label for="last_name" class="col-sm-2 control-label">Last Name:</label>
                        <div class="col-sm-10">
                            <input type="text" id="id_last_name" value="{{user.last_name}}" name="last_name" class="form-control" required />
                        </div><br><br>
                        <label for="institution" class="col-sm-2 control-label">Institution:</label>
                        <div class="col-sm-10">
                            <input type="text" id="id_institution" value="{{user.institution}}" name="institution" class="form-control" placeholder="University/Company" required />
                        </div><br><br>
                        <label for="id_password1" class="col-sm-2 control-label">New Password:</label>
                        <div class="col-sm-10">
                            <input class="form-control" id="id_password1" name="password1" placeholder="New Password" type="password" />
                        </div><br><br>
                        <label class="col-sm-2" for="id_password2">New Password (again):</label>
                        <div class="col-sm-10">
                            <input class="form-control" id="id_password2" name="password2" placeholder="New Password (again)" type="password" />
                        </div>

                    </div>
            </div>
        </div>
    </div>

{%endblock body%}

{% endif %}

The code is clearly incomplete, because I didn't find a way to add the fields and save them properly as I requested. Thanks


Solution

  • I solved this problem in two steps, and involve to refactor the code I post in my question:

    1. First step (Create the custom field to user_table):

    First of all I added an app to my project called CustomUser where I handle any issue related to allauth user.

    in settings.py

    INSTALLED_APPS = [
        ...
        'CustomUser.apps.CustomuserConfig',
    ]
    
    AUTH_USER_MODEL = 'CustomUser.CustomUser'
    

    in CustomUser/models.py

    from __future__ import unicode_literals
    
    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    class CustomUser(AbstractUser):
        add_your_custom_fields_here 
    

    in CustomUser/apps.py

    from __future__ import unicode_literals
    
    from django.apps import AppConfig
    
    
    class CustomuserConfig(AppConfig):
        name = 'CustomUser'
    

    in CustomUser/admin.py

    from django.contrib import admin
    from .models import CustomUser
    
    admin.site.register(CustomUser)
    

    After configuration your custom fields to the user table, you need to run the migrate command in shell to add these fields. In my case it didn't work, then I needed to flush my database and populate it again.

    1. The second step is to create a updateform with the new user table.

    First you need to override the User class from allauth. Creating a form.py in CustomUser folder we have:

    from django import forms from .models import CustomUser

    class UpdateUserForm(forms.ModelForm):
        class Meta:
            model = CustomUser
            # Add here the fields you want to be present in the update form
            fields = ('first_name', 'last_name', 'institution')
    

    in CustomUser/templates/profile.html you need to create the form for your app. In my case I created a primitive one:

    Update your data <br><br>
    
    <form action="." method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit" />
    </form> 
    

    in CustomUser/views.py you're gonna configuration the behaviour of your profile.html page

    from django.shortcuts import render
    from .forms import UpdateUserForm
    from django.http import HttpResponseRedirect
    from django.views.generic import UpdateView
    from django.core.urlresolvers import reverse_lazy
    
    def profile(UpdateView):
        if request.method == 'POST':
            form = UpdateUserForm(request.POST)
            if form.is_valid():
                return HttpResponseRedirect('/accounts/profile/')
        else:
            form = UpdateUserForm()
    
        return render(request, 'profile.html', {'form':form})
    
    class UserUpdate(UpdateView):
            form_class = UpdateUserForm
            template_name = 'profile.html'
            success_url = reverse_lazy('profile')
    
            #get object
            def get_object(self, queryset=None): 
                return self.request.user
    

    Finally, just add the profile.html page to urls.py and voilà:

    from CustomUser import views
    
    url(r'^accounts/profile/$',  views.UserUpdate.as_view() , name='profile'), 
    

    Hope it helps someone... Thanks