I am pretty new to django and I am very lost with django-registration. At the moment I have the django-registration set up an going but I need to add another field to it for a phone number. I need the phone number field in the registration field instead so I can use the api from twilio to send a verification link through text instead of email. How would I go about adding this one field to django-registration?
I work with django at work and for that kind of issue we used to attach a model to the user, example:
You create a new model, for example profile with a OneToOneField to user
Add your desired fields to that profile model, such as (tlf, country, language,log...)
Create admin.py to manage this model (profile) at the same time you manage users in django admin
Profile Model Example
class Profile(models.Model):
user = models.OneToOneField(User)
phone = models.CharField(max_length=255, blank=True, null=True, verbose_name='phone')
description = models.TextField(blank=True, verbose_name='descripction')
...
...
class Meta:
ordering = ['user']
verbose_name = 'user'
verbose_name_plural = 'users'
admin.py example
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
filter_horizontal = ['filter fields'] # example: ['tlf', 'country',...]
verbose_name_plural = 'profiles'
fk_name = 'user'
class UserAdmin(UserAdmin):
inlines = (ProfileInline, )
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active')
admin.site.unregister(User) # Unregister user to add new inline ProfileInline
admin.site.register(User, UserAdmin) # Register User with this inline profile
Create an user and attach a profile to him
# Create user
username = 'TestUser'
email = 'test#example.com'
passw = '1234'
new_user = User.objects.create_user(username, email, passw)
# Create profile
phone = '654654654'
desc = 'Test user profile'
new_profile = Profile(user=new_user, phone = phone, description=desc)
new_profile.profile_role = new_u_prole
new_profile.user = new_user
# Save profile and user
new_profile.save()
new_user.save()
Now you'll have this Profile model attached to each user, and you could add the fields you wish to Profile Model, and for example if you make:
user = User.objects.get(id=1)
you can access to his profile doing:
user.profile
and to access phone
user.profile.phone
Not django-registration, but I customized django-userena once to add a custom field to the signup form.
You can view the code here.
I am sure the process works more or less the same in django-registration too: overriding the signup form and adding custom fields.
However, django-registration is no longer maintained, I believe. It is a classic and works so well, but there are other options too.
Related
I'm using django.contrib.auth and I have a working login/registration system, however I want to extend my User model to have street address and phone number for registration purposes only, and I'm not sure how can I do that properly. What I have done works but feels wrong and I would like to know a proper way to do this.
I created accounts app and in models.py I have this:
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
address = models.CharField(max_length=200)
address_number = models.CharField(max_length=20)
phone = models.CharField(max_length=20)
...then I registered that in admin.py:
from django.contrib import admin
from .models import User
admin.site.register(User)
...then in settings.py I added this line:
AUTH_USER_MODEL = 'accounts.User'
...and wherever I used django.contrib.auth.User, now I use accounts.models.User.
As I said, this works however it somehow feels wrong and it easily could be as this is my first time extending the User model. Why I think this is wrong? For one, Users has disappeared in admin from "Authentication and Authorization" and is instead under "Accounts" (as expected).
How can I accomplish this in a proper way?
#EDIT:
Here is my register form:
from django import forms
from accounts.models import User
class RegistrationForm(forms.ModelForm):
email = forms.EmailField(max_length=200, help_text='Required')
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
class Meta:
model = User
fields = (
'username',
'email',
'first_name',
'last_name',
'address',
'address_number',
'phone'
)
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords do not match.')
return cd['password2']
def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise forms.ValidationError(
'Please use another e-mail, that is already taken.')
return email
I have a User model and i want to add a new field to the user, in the database and in the user form. i have looked online many differente ways to do this but i want to know what is the "correct" way to do it. Specially the correct way to create migrations.
Django Version: (1,10,0,u'final',1)
Not sure if I got what you're looking for but let's say you want to add a "Status" field to your User model, and then have it in the Admin panel so you can interact with it (update, change, etc...).
in models.py - we are creating a Profile class which will be linked to a User and then a status to be added to a user:
class Profile(models.Model):
" A profile added User """
user = models.OneToOneField(User, on_delete=models.CASCADE)
# so to link the profile to a user
status = models.CharField(max_length=100, blank=True)
# a field status
def __str__(self):
return self.status
in admin.py - we are integrating the newly created Profile to the user
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile'
fk_name = 'user'
class CustomUserAdmin(UserAdmin):
inlines = (ProfileInline, )
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(CustomUserAdmin, self).get_inline_instances(request, obj)
# And then we unregister the User class and register the two updated ones
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
Don't forget to run /manage.py makemigrations and then /manage.py migrate to update the database.
Let me know if that answer your question.
The error I get is: extend user to a custom form, the "user_id" field is my custom form is the "property", which is linked to the table "auth_user" is not saved, and I need both tables relate to make use my custom form attributes and shape of the User of django.
my models.py
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
Matricula = models.CharField(max_length=25)
forms.py
class SignupForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('first_name', 'last_name', 'Matricula')
#Saving user data
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.Matricula = self.cleaned_data['Matricula']
user.save()
##Save profile
profile = Profile()
Profile.user = user
profile.Matricula = self.cleaned_data['Matricula']
profile.save()
i tried:
user = models.OneToOneField(User, on_delete=models.CASCADE)
but I get an error:
Error
You believe that ForeignKey can be used or correct use OneToOneField?
You should be careful with your capitalisation. You've assigned the user value to the class, not the instance. It should be:
profile = Profile()
profile.user = user
Or better:
profile = Profile(user=user)
You are not setting user to that instance of Profile:
profile = Profile()
profile.user = user # Notice the case of Profile
I am having difficulty creating custom User fields using the Cookiecutter Django framework. I have changed the cookiecutter template significantly - removing django-allauth but a lot of the structure remains the same.
If I wanted to add another field to the User model (for example, "department" - the users are employees), where would I add it?
I figured I could add a department variable to users/models.py but it doesn't seem to work. When I login to the admin site, I don't see a department field when I add a user. Similarly, I don't see a name field in the admin site - I only see First Name, Last Name, and Email Address.
# users/models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import
from django.contrib.auth.models import AbstractUser
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
#python_2_unicode_compatible
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(blank=True, max_length=255)
department = models.CharField(blank=True, max_length=5)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username})
The admin file:
# users/admin.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from .models import User
class MyUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = User
class MyUserCreationForm(UserCreationForm):
error_message = UserCreationForm.error_messages.update({
'duplicate_username': 'This username has already been taken.'
})
class Meta(UserCreationForm.Meta):
model = User
def clean_username(self):
username = self.cleaned_data["username"]
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
#admin.register(User)
class UserAdmin(AuthUserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
You are missing the fieldsets attribute:
#admin.register(User)
class UserAdmin(AuthUserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
fieldsets = (
('', {'fields': ('department',)}),
) + AuthUserAdmin.fieldsets
list_display = ('username', 'department', 'is_superuser')
search_fields = ['username', 'department']
You don't need to set the attributes list_display and search_fields to display your department field. But I left them in the sample since they are very handy when it comes to Django admin customization.
ModelAdmin.list_display:
Set list_display to control which fields are displayed on the change
list page of the admin.
ModelAdmin.search_fields:
Set search_fields to enable a search box on the admin change list
page. This should be set to a list of field names that will be
searched whenever somebody submits a search query in that text box.
I'm trying to create and manage a custom user in django.
I saw there are two possibilities, and i've chosen to extend (not create a new auth).
Models
models.py
class Artists(models.Model):
user = models.OneToOneField(User)
artist_image = models.ImageField(null=True, blank=True, upload_to="/artist_image/")
def __str__(self):
return 'Profil de {0}'.format(self.username)
def get_absolute_url(self):
return reverse('artist-details', kwargs={'pk': self.pk})
As i read in doc, I just make a OneToOne field with the User class of django auth models, so I can access method and properties, such as username, email, on my own user (here Artists).
form.py
class CreateArtistForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email')
def save(self, commit=True):
user = super(CreateArtistForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
Here I extend UserCreationForm to prepare a form a little different (I want to have email field on my register form).
But here is my question : I first tried with
class Meta:
model = Artists
fields = ('user.username', 'user.email')
But I the error fields unknown in model Artist.
So I tried just with username and email and same error.
So I changed the model = Artists to User, and it works fine.
But now how i register my Artist Object when the user is saved?
Do I have to make something like (in save()):
artist = Artists()
artist.user = user
artist.save()
Or override create_user()?
I'm quite lost here and i'm looking docs and questions not able to find something because most of example people define their own auth.
Thanks in advance
Besta
edit : i'm using django 1.8.2 and python 3.4