├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── requirements.txt ├── setup.py └── userprofiles2 ├── __init__.py ├── apps.py ├── forms.py ├── locale └── fr │ └── LC_MESSAGES │ ├── django.mo │ └── django.po ├── migrations ├── 0001_initial.py └── __init__.py ├── models.py ├── signals.py ├── templates └── userprofiles2 │ ├── email_form.html │ ├── home.html │ ├── identity_form.html │ └── personal_infos_form.html ├── urls.py └── views.py /.gitignore: -------------------------------------------------------------------------------- 1 | *node_modules/ 2 | settings.py 3 | *.sqlite3 4 | .project 5 | .pydevproject 6 | .settings 7 | 8 | __pycache__/ 9 | *.py[cod] 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | env/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *,cover 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 synw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include userprofiles/templates * 2 | recursive-include userprofiles/migrations * 3 | recursive-include userprofiles/locale * -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django Userprofiles 2 | 3 | User profiles management that work with [Django Allauth](https://github.com/pennersr/django-allauth) 4 | 5 | To install clone and: 6 | 7 | ```bash 8 | pip install django-allauth django-avatar 9 | mkdir media/userprofiles 10 | mkdir media/userprofiles/avatars 11 | ``` 12 | 13 | Installed apps: 14 | 15 | ```python 16 | 'django.contrib.sites', 17 | 'allauth', 18 | 'allauth.account', 19 | 'allauth.socialaccount', 20 | 'avatar', 21 | 'userprofiles2', 22 | ``` 23 | 24 | Be sure to have ``SITE_ID = 1`` in settings. 25 | 26 | Urls: 27 | 28 | ```python 29 | path('avatar/', include('avatar.urls')), 30 | path('account/', include('allauth.urls')), 31 | path('profile/', include('userprofiles2.urls')), 32 | ``` 33 | 34 | Example settings for Allauth: 35 | 36 | ```python 37 | LOGIN_URL = '/account/login/' 38 | LOGIN_REDIRECT_URL = '/' 39 | LOGOUT_URL = "/account/logout/" 40 | 41 | #~ Allauth settings 42 | ACCOUNT_EMAIL_REQUIRED = True 43 | ACCOUNT_EMAIL_VERIFICATION = 'optional' 44 | SOCIALACCOUNT_EMAIL_REQUIRED = False 45 | SOCIALACCOUNT_EMAIL_VERIFICATION = False 46 | ACCOUNT_PASSWORD_MIN_LENGTH = 8 47 | ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = '/' 48 | ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/account/' 49 | ``` 50 | 51 | Note: the templates use font-awesome 52 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django-allauth 2 | django-avatar -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | version = __import__('userprofiles2').__version__ 5 | 6 | setup( 7 | name='django-userprofiles2', 8 | packages=find_packages(), 9 | include_package_data=True, 10 | version=version, 11 | description='User profiles that work with Django Allauth', 12 | author='synw', 13 | author_email='synwe@yahoo.com', 14 | url='https://github.com/synw/django-userprofiles2', 15 | download_url='https://github.com/synw/django-userprofiles2/releases/tag/' + version, 16 | keywords=['django', 'user-profiles'], 17 | classifiers=[ 18 | 'Development Status :: 3 - Alpha', 19 | 'Framework :: Django :: 2.1', 20 | 'Intended Audience :: Developers', 21 | 'License :: OSI Approved :: MIT License', 22 | 'Programming Language :: Python :: 3.6', 23 | ], 24 | install_requires=[ 25 | "django-allauth", 26 | "django-avatar", 27 | ], 28 | zip_safe=False 29 | ) 30 | -------------------------------------------------------------------------------- /userprofiles2/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = 'userprofiles2.apps.Userprofiles2Config' 2 | __version__ = "0.2" 3 | -------------------------------------------------------------------------------- /userprofiles2/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | from django.urls import reverse_lazy as _ 3 | 4 | 5 | class Userprofiles2Config(AppConfig): 6 | name = 'userprofiles2' 7 | verbose_name = _(u'User profiles') 8 | 9 | def ready(self): 10 | from userprofiles2 import signals 11 | -------------------------------------------------------------------------------- /userprofiles2/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django import forms 4 | from django.http import Http404 5 | from django.contrib.auth.models import User 6 | from .models import UserProfile 7 | 8 | 9 | class IdentiteForm(forms.ModelForm): 10 | first_name = forms.CharField(max_length=256) 11 | last_name = forms.CharField(max_length=256) 12 | 13 | class Meta: 14 | model = UserProfile 15 | fields = ('first_name', 'last_name', 'gender', 'phone',) 16 | widgets = {'phone': forms.TextInput()} 17 | 18 | def __init__(self, *args, **kwargs): 19 | super(IdentiteForm, self).__init__(*args, **kwargs) 20 | try: 21 | self.fields['first_name'].initial = self.instance.user.first_name 22 | self.fields['last_name'].initial = self.instance.user.last_name 23 | except User.DoesNotExist: 24 | raise Http404 25 | self.fields['first_name'].required = True 26 | self.fields['last_name'].required = True 27 | self.fields['gender'].required = True 28 | self.fields['phone'].required = True 29 | return 30 | 31 | 32 | class EmailForm(forms.ModelForm): 33 | 34 | class Meta: 35 | model = User 36 | fields = ['email'] 37 | 38 | def __init__(self, *args, **kwargs): 39 | super(EmailForm, self).__init__(*args, **kwargs) 40 | self.fields['email'].required = True 41 | -------------------------------------------------------------------------------- /userprofiles2/locale/fr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synw/django-userprofiles2/255454e600866170e7c80db898872e388e22d72e/userprofiles2/locale/fr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /userprofiles2/locale/fr/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2016-10-25 16:17+0000\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 | 21 | #: apps.py:7 models.py:22 22 | msgid "User profiles" 23 | msgstr "Profil utilisateur" 24 | 25 | #: models.py:12 26 | msgid "User" 27 | msgstr "Utilisateur" 28 | 29 | #: models.py:14 30 | msgid "Gender" 31 | msgstr "Sexe" 32 | 33 | #: models.py:15 34 | msgid "Avatar" 35 | msgstr "" 36 | 37 | #: models.py:16 38 | msgid "Profile completion percentage" 39 | msgstr "Pourcentage de complétion du profil" 40 | 41 | #: models.py:17 42 | msgid "Email is verified" 43 | msgstr "Email vérifié" 44 | 45 | #: models.py:18 46 | msgid "Personal info completed" 47 | msgstr "Infos personnelles complétées" 48 | 49 | #: models.py:21 50 | msgid "User profile" 51 | msgstr "Profil utilisateur" 52 | 53 | #: templates/account/base.html:12 54 | msgid "My account" 55 | msgstr "Mon compte" 56 | 57 | #: templates/account/base.html:16 58 | msgid "E-mail Addresses" 59 | msgstr "Adresse email" 60 | 61 | #: templates/account/base.html:19 templates/account/password_change.html:6 62 | #: templates/account/password_change.html:14 63 | #: templates/account/password_reset_from_key.html:6 64 | #: templates/account/password_reset_from_key.html:9 65 | #: templates/account/password_reset_from_key.html:21 66 | msgid "Change Password" 67 | msgstr "Changer le mot de passe" 68 | 69 | #: templates/account/base.html:24 70 | msgid "Associated social accounts" 71 | msgstr "Comptes sociaux associés" 72 | 73 | #: templates/account/email.html:13 74 | msgid "The following e-mail addresses are associated with your account:" 75 | msgstr "Les emails suivants sont associés à votre compte:" 76 | 77 | #: templates/account/email.html:22 78 | msgid "E-mail" 79 | msgstr "Email" 80 | 81 | #: templates/account/email.html:25 82 | msgid "Status" 83 | msgstr "Status" 84 | 85 | #: templates/account/email.html:40 86 | msgid "Verified" 87 | msgstr "Vérifiéé" 88 | 89 | #: templates/account/email.html:42 90 | msgid "Unverified" 91 | msgstr "Non vérifié" 92 | 93 | #: templates/account/email.html:44 94 | msgid "Primary" 95 | msgstr "Principal" 96 | 97 | #: templates/account/email.html:52 98 | msgid "Make Primary" 99 | msgstr "Rendre principal" 100 | 101 | #: templates/account/email.html:53 102 | msgid "Re-send Verification" 103 | msgstr "Réenvoyer la vérification" 104 | 105 | #: templates/account/email.html:54 106 | msgid "Remove" 107 | msgstr "Enlever" 108 | 109 | #: templates/account/email.html:61 110 | msgid "Warning:" 111 | msgstr "Attention:" 112 | 113 | #: templates/account/email.html:61 114 | msgid "" 115 | "You currently do not have any e-mail address set up. You should really add " 116 | "an e-mail address so you can receive notifications, reset your password, etc." 117 | msgstr "Vous n'avez aucune adresse email enregistrée." 118 | 119 | #: templates/account/email.html:66 120 | msgid "Add E-mail Address" 121 | msgstr "Ajouter une adresse email" 122 | 123 | #: templates/account/email.html:72 124 | msgid "Add E-mail" 125 | msgstr "Ajouter un email" 126 | 127 | #: templates/account/email.html:77 128 | msgid "Back to profile" 129 | msgstr "Retour au profil" 130 | 131 | #: templates/account/email.html:86 132 | msgid "Do you really want to remove the selected e-mail address?" 133 | msgstr "Voulez vous enlever les adresses email sélectionnées?" 134 | 135 | #: templates/account/email_confirm.html:6 136 | #: templates/account/email_confirm.html:10 137 | msgid "Confirm E-mail Address" 138 | msgstr "Confirmer l'email" 139 | 140 | #: templates/account/email_confirm.html:17 141 | #, python-format 142 | msgid "" 143 | "Merci de confirmer que l'adresse \n" 144 | "\t%(email)s est bien l'adresse de " 145 | "l'utilisateur %(user_display)s." 146 | msgstr "" 147 | 148 | #: templates/account/email_confirm.html:23 149 | msgid "Confirm" 150 | msgstr "" 151 | 152 | #: templates/account/email_confirm.html:30 153 | #, python-format 154 | msgid "" 155 | "Ce lien a expiré ou est invalide. Merci de redemander un envoi de mail de confirmation." 157 | msgstr "" 158 | 159 | #: templates/account/login.html:7 templates/account/login.html:12 160 | #: templates/account/login.html:42 161 | msgid "Sign In" 162 | msgstr "" 163 | 164 | #: templates/account/login.html:31 templates/account/signup.html:6 165 | msgid "Signup" 166 | msgstr "" 167 | 168 | #: templates/account/login.html:43 169 | msgid "Forgot Password?" 170 | msgstr "" 171 | 172 | #: templates/account/logout.html:5 templates/account/logout.html:8 173 | #: templates/account/logout.html:16 174 | msgid "Sign Out" 175 | msgstr "" 176 | 177 | #: templates/account/logout.html:9 178 | msgid "Are you sure you want to sign out?" 179 | msgstr "" 180 | 181 | #: templates/account/password_reset.html:7 182 | #: templates/account/password_reset.html:11 183 | msgid "Password Reset" 184 | msgstr "" 185 | 186 | #: templates/account/password_reset.html:16 187 | msgid "" 188 | "Forgotten your password? Enter your e-mail address below, and we'll send you " 189 | "an e-mail allowing you to reset it." 190 | msgstr "" 191 | 192 | #: templates/account/password_reset.html:22 193 | msgid "Reset My Password" 194 | msgstr "" 195 | 196 | #: templates/account/password_reset.html:26 197 | msgid "Please contact us if you have any trouble resetting your password." 198 | msgstr "" 199 | 200 | #: templates/account/password_reset_from_key.html:9 201 | msgid "Bad Token" 202 | msgstr "" 203 | 204 | #: templates/account/password_reset_from_key.html:13 205 | #, python-format 206 | msgid "" 207 | "The password reset link was invalid, possibly because it has already been " 208 | "used. Please request a new password reset." 210 | msgstr "" 211 | 212 | #: templates/account/password_reset_from_key.html:25 213 | msgid "Your password is now changed." 214 | msgstr "" 215 | 216 | #: templates/account/password_set.html:6 templates/account/password_set.html:14 217 | msgid "Set Password" 218 | msgstr "" 219 | 220 | #: templates/account/signup.html:9 templates/account/signup.html:32 221 | msgid "Sign Up" 222 | msgstr "" 223 | 224 | #: templates/account/signup.html:11 225 | #, python-format 226 | msgid "" 227 | "Already have an account? Then please sign in." 228 | msgstr "" 229 | 230 | #: templates/avatar/change.html:8 231 | msgid "Your current avatar: " 232 | msgstr "" 233 | 234 | #: templates/avatar/change.html:11 235 | msgid "You haven't uploaded an avatar yet. Please upload one now." 236 | msgstr "" 237 | 238 | #: templates/avatar/change.html:17 239 | msgid "Choose new Default" 240 | msgstr "" 241 | 242 | #: templates/avatar/change.html:22 243 | msgid "Upload New Image" 244 | msgstr "" 245 | 246 | #: templates/avatar/change.html:25 templates/userprofiles/identity_form.html:19 247 | msgid "Back" 248 | msgstr "" 249 | 250 | #: templates/userprofiles/home.html:23 251 | msgid "Profile completed at" 252 | msgstr "Profil complété à" 253 | 254 | #: templates/userprofiles/home.html:35 255 | msgid "" 256 | "Your profile must be completed in order to access all the features of the " 257 | "site" 258 | msgstr "Votre profil doit être complété afin d'accéder à toutes les fonctionnalités du site" 259 | 260 | #: templates/userprofiles/home.html:37 261 | msgid "Thank you to complete these informations:" 262 | msgstr "Merci de compléter ces informations:" 263 | 264 | #: templates/userprofiles/home.html:52 265 | msgid "Email adress verification" 266 | msgstr "Vérification de l'adresse email" 267 | 268 | #: templates/userprofiles/home.html:56 269 | msgid "Verify email" 270 | msgstr "Vérifier l'email" 271 | 272 | #: templates/userprofiles/home.html:58 273 | msgid "Edit email" 274 | msgstr "Editer l'email" 275 | 276 | #: templates/userprofiles/home.html:75 277 | msgid "Personal infos" 278 | msgstr "Infos personelles" 279 | 280 | #: templates/userprofiles/home.html:79 281 | msgid "Edit" 282 | msgstr "Editer" 283 | 284 | #: templates/userprofiles/home.html:81 285 | msgid "Complete now" 286 | msgstr "Remplir maintenant" 287 | 288 | #: templates/userprofiles/home.html:90 289 | msgid "Change your avatar" 290 | msgstr "Changer votre avatar" 291 | 292 | #: templates/userprofiles/home.html:91 293 | msgid "Change your password" 294 | msgstr "Changer votre mot de passe" 295 | 296 | #: templates/userprofiles/identity_form.html:4 297 | msgid "My profile: Identity" 298 | msgstr "Mon profil: identité" 299 | 300 | #: templates/userprofiles/identity_form.html:14 301 | msgid "Identity" 302 | msgstr "Identité" 303 | 304 | #: templates/userprofiles/identity_form.html:18 305 | msgid "Save" 306 | msgstr "Enregister" 307 | -------------------------------------------------------------------------------- /userprofiles2/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-11-21 16:39 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='UserProfile', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('phone', models.PositiveIntegerField(blank=True, null=True, verbose_name='Phone')), 22 | ('gender', models.CharField(blank=True, choices=[('man', 'Man'), ('woman', 'Woman')], max_length=40, verbose_name='Gender')), 23 | ('avatar', models.ImageField(blank=True, upload_to='userprofiles2/avatars', verbose_name='Avatar')), 24 | ('completion_level', models.PositiveSmallIntegerField(default=0, verbose_name='Profile completion percentage')), 25 | ('email_is_verified', models.BooleanField(default=False, verbose_name='Email is verified')), 26 | ('personal_info_is_completed', models.BooleanField(default=False, verbose_name='Personal info completed')), 27 | ('user', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='User')), 28 | ], 29 | options={ 30 | 'verbose_name': 'User profile', 31 | 'verbose_name_plural': 'User profiles', 32 | }, 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /userprofiles2/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/synw/django-userprofiles2/255454e600866170e7c80db898872e388e22d72e/userprofiles2/migrations/__init__.py -------------------------------------------------------------------------------- /userprofiles2/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | from django.utils.translation import ugettext_lazy as _ 4 | 5 | 6 | GENDER = (('man', 'Man'), ('woman', 'Woman')) 7 | 8 | 9 | class UserProfile(models.Model): 10 | user = models.OneToOneField(User, null=True, related_name="profile", 11 | verbose_name=_('User'), on_delete=models.CASCADE) 12 | phone = models.PositiveIntegerField( 13 | null=True, blank=True, verbose_name=_('Phone')) 14 | gender = models.CharField( 15 | max_length=40, blank=True, verbose_name=_('Gender'), choices=GENDER) 16 | avatar = models.ImageField( 17 | upload_to='userprofiles2/avatars', blank=True, verbose_name=_('Avatar')) 18 | completion_level = models.PositiveSmallIntegerField( 19 | default=0, verbose_name=_('Profile completion percentage')) 20 | email_is_verified = models.BooleanField( 21 | default=False, verbose_name=_('Email is verified')) 22 | personal_info_is_completed = models.BooleanField( 23 | default=False, verbose_name=_('Personal info completed')) 24 | 25 | class Meta: 26 | verbose_name = _('User profile') 27 | verbose_name_plural = _('User profiles') 28 | 29 | def __str__(self): 30 | return "User profile: %s" % self.user.username 31 | 32 | def get_completion_level(self): 33 | completion_level = 0 34 | if self.email_is_verified: 35 | completion_level += 50 36 | if self.personal_info_is_completed: 37 | completion_level += 50 38 | return completion_level 39 | 40 | def update_completion_level(self): 41 | self.completion_level = self.get_completion_level() 42 | self.save() 43 | -------------------------------------------------------------------------------- /userprofiles2/signals.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from django.conf import settings 3 | from django.dispatch import receiver 4 | from django.contrib.auth.models import User 5 | from allauth.account.signals import user_signed_up, email_confirmed 6 | from .models import UserProfile 7 | 8 | 9 | @receiver(user_signed_up, dispatch_uid="user_signed_up") 10 | def create_new_profile(request, **kwargs): 11 | if settings.DEBUG: 12 | print('# ============ Signal fired: "user_signed_up" ============= #') 13 | if not request.user.is_authenticated: 14 | return 15 | user = kwargs['user'] 16 | profile = UserProfile(user=user) 17 | profile.save() 18 | if settings.DEBUG: 19 | print('New profile created for user ' + user.username) 20 | return 21 | 22 | 23 | @receiver(email_confirmed, dispatch_uid="email_confirmed") 24 | def set_email_confirmed(request, **kwargs): 25 | if settings.DEBUG: 26 | print('# ============ Signal fired: "email_confirmed" ============= #') 27 | if not request.user.is_authenticated: 28 | return 29 | else: 30 | if settings.DEBUG: 31 | print('User is identified : ' + request.user.username) 32 | user = request.user 33 | profile = UserProfile.objects.get(user=user) 34 | profile.email_is_verified = True 35 | profile.completion_level = profile.get_completion_level() 36 | profile.save() 37 | if settings.DEBUG: 38 | print('Email set as verified') 39 | return 40 | -------------------------------------------------------------------------------- /userprofiles2/templates/userprofiles2/email_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load staticfiles i18n %} 3 | 4 | {% block title %}{% trans 'My account > Email' %}{% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

{% trans 'Email' %}

10 |
{% csrf_token %} 11 | {{ form }} 12 | {% if user.profile.email_is_verified %} 13 | 14 | {% else %} 15 | 16 | {% endif %} 17 |
18 |
19 |
20 | 21 | {% endblock %} -------------------------------------------------------------------------------- /userprofiles2/templates/userprofiles2/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load i18n avatar_tags %} 3 | 4 | {% block title %}{% trans "My profile" %}{% endblock %} 5 | 6 | {% block content %} 7 | 15 |
16 |
17 | 22 |

{{ user.username }}

23 |

{% if profile.completion_level == 100 %} {% endif %}{% trans "Profile completed at" %} 24 | 25 | {{ profile.completion_level }}% 26 | 27 |

28 |
29 |
30 | {{ profile.completion_level }}% 31 |
32 |
33 | {% if not profile.completion_level == 100 %} 34 |

35 |  {% trans "Your profile must be completed in order to access all the features of the site" %} 36 |

37 |

{% trans "Thank you to complete these informations:" %}

38 | {% endif %} 39 |
40 |
41 |
42 |
43 |
44 | {% if not profile.email_is_verified %} 45 | 46 | 47 | 48 | {% else %} 49 | 50 | {% endif %} 51 |
52 |

 {% trans "Email adress verification" %}

53 |
54 |
55 | {% if not profile.email_is_verified %} 56 | {% trans "Verify email" %} 57 | {% else %} 58 | {% trans "Edit email" %} 59 | {% endif %} 60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {% if not profile.personal_info_is_completed %} 68 | 69 | 70 | 71 | {% else %} 72 | 73 | {% endif %} 74 |
75 |

 {% trans "Personal infos" %}

76 |
77 |
78 | {% if profile.personal_info_is_completed %} 79 | {% trans "Edit" %} 80 | {% else %} 81 | {% trans "Complete now" %} 82 | {% endif %} 83 |
84 |
85 |
86 |
87 | 95 |
96 |
97 | {% endblock content %} -------------------------------------------------------------------------------- /userprofiles2/templates/userprofiles2/identity_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load i18n staticfiles avatar_tags %} 3 | 4 | {% block title %}{% trans "My profile: Identity" %}{% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 | 14 |

{{ user.username }} : {% trans "Identity" %}

15 |
{% csrf_token %} 16 | {{ form }} 17 |
18 | 19 | {% trans "Back" %} 20 |
21 |
22 |
23 |
24 | {% endblock %} -------------------------------------------------------------------------------- /userprofiles2/templates/userprofiles2/personal_infos_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load staticfiles bootstrap %} 3 | 4 | {% block title %}Mon compte > Informations personelles{% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

Informations personelles

10 |
{% csrf_token %} 11 | {{ form|bootstrap }} 12 |
13 | 14 | Retour 15 |
16 |
17 |
18 |
19 | 20 | {% endblock %} -------------------------------------------------------------------------------- /userprofiles2/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from .views import ProfileHomeView, ProfileIdentite 3 | 4 | urlpatterns = [ 5 | url(r'^$', ProfileHomeView.as_view(), name='profile-home'), 6 | url(r'^identity/(?P[0-9]+)/$', 7 | ProfileIdentite.as_view(), name='profile-identity-form'), 8 | ] 9 | -------------------------------------------------------------------------------- /userprofiles2/views.py: -------------------------------------------------------------------------------- 1 | from django.urls import reverse_lazy 2 | from django.http import HttpResponseRedirect 3 | from django.views.generic.edit import UpdateView 4 | from django.views.generic import TemplateView 5 | from django.contrib.auth.mixins import LoginRequiredMixin 6 | from .models import UserProfile 7 | from .forms import IdentiteForm 8 | 9 | 10 | class ProfileHomeView(LoginRequiredMixin, TemplateView): 11 | template_name = 'userprofiles2/home.html' 12 | user_check_failure_path = reverse_lazy("account_signup") 13 | 14 | def check_user(self, user): 15 | if user.is_active: 16 | return True 17 | return False 18 | 19 | def get_context_data(self, **kwargs): 20 | context = super(ProfileHomeView, self).get_context_data(**kwargs) 21 | profile = UserProfile.objects.get_or_create(user=self.request.user)[0] 22 | context['profile'] = profile 23 | return context 24 | 25 | 26 | class ProfileIdentite(LoginRequiredMixin, UpdateView): 27 | template_name = "userprofiles2/identity_form.html" 28 | form_class = IdentiteForm 29 | user_check_failure_path = reverse_lazy("account_signup") 30 | success_url = reverse_lazy("profile-home") 31 | 32 | def get_queryset(self): 33 | queryset = UserProfile.objects.filter(user=self.request.user) 34 | return queryset 35 | 36 | def form_valid(self, form, **kwargs): 37 | super(ProfileIdentite, self).form_valid(form) 38 | profile = form.save(commit=False) 39 | user = self.request.user 40 | user.first_name = form.cleaned_data['first_name'] 41 | user.last_name = form.cleaned_data['last_name'] 42 | user.save() 43 | profile.gender = form.cleaned_data['gender'] 44 | profile.phone = form.cleaned_data['phone'] 45 | profile.personal_info_is_completed = True 46 | profile.completion_level = profile.get_completion_level() 47 | profile.save() 48 | return HttpResponseRedirect(self.get_success_url()) 49 | --------------------------------------------------------------------------------