Failed to extends User form in django - python

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

Related

Why my django signals not working for User model?

I want to implement django signals on User model for create user profile. I want to create user profile when any user will be registered. here is my code for create user profile though signals:
from django.contrib.auth.models import User
#receiver(post_save, sender=User)
def user_is_created_or_save(sender,instance,created,**kwargs):
user = instance.user
first_name = instance.first_name
last_name = instance.last_name
if created:
UserProfile.objects.create(user=user)
I am not understanding why user profile not creating when any user registered?
#updated question
I am using Abstract user model. here is my user mdoel:
class UserManagement(AbstractUser):
is_blog_author = models.BooleanField(default=False)
is_editor = models.BooleanField(default=False)
is_subscriber = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
class Subscriber(models.Model):
user = models.OneToOneField(UserManagement, on_delete=models.CASCADE, primary_key=True)
email = models.EmailField(max_length=1000)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
is_subscriber = models.BooleanField(default=False)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name="userprofile")
Since a custom user model has been defined, you can't use from django.contrib.auth.models import User. It is also not a recommended way to reference the user model.
As described in the docs if you have properly setup your custom user model, you can use settings.AUTH_USER_MODEL to reference your custom user model as the sender:
from django.conf import settings
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def user_is_created_or_save(sender, instance, created, **kwargs):
...

How Could I Add Image Upload Option To The Registration Form?

My forms.py is this.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm,UserChangeForm
class RegistrationForm(UserCreationForm):
email= forms.EmailField(required = True)
class Meta:
model = User
fields = {
'username',
'first_name',
'last_name',
'email',
'password1',
'password2'
}
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
And, i have to add "upload image" option for the user so that user could upload their image from any file and load it on the profile.
You have to extend your user model with field profile_image = models.FileField() there is tutorial how to do it.
Than you have to add
class RegistrationForm(UserCreationForm):
email= forms.EmailField(required = True)
profile_image = forms.FileField() # add this field
...
def save(self, commit=True):
...
user.profile_image = self.cleaned_data.get('profile_image')
...
and add enctype="multipart/form-data" attribute to the <form ...> tag in the html template. Here is tutorial from Django docs on File Uploads.
EDIT
Extending the User model in the most basic way without changing the actual User model is that you'll create new model with one-to-one relation to the user model.
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
profile_image = models.FileField() # where is stored the user profile image
this is the Profile of each user. You will have to create profile when user is created, so:
place this code to the any models.py or file that is loaded on the startup with django
from django.contrib import auth
auth.models.User.add_to_class('create_profile', create_profile)
then create the method below
from (appname).models import Profile
def create_profile(self, **kwargs):
Profile.objects.create(
user=self,
**kwargs # you can pass other fields values upon creating
)
then modify to the RegistrationForm as I wrote before and modify the save function
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
# user has to be saved to add profile
user.save()
user.create_profile()
user.profile_img = self.cleaned_data.get('profile_image')
user.profile.save()
if commit:
user.save()
also when you are instantiating the RegistrationForm with request.POST do it like
form = RegistrationForm(request.POST, request.FILES)
# to the files have to be passed also, they are not in request.POST
if form.is_valid():
form.save()
and thats it.

Using foreign key of the UserCreationForm model User

I have made a signup page using built in UserCreationForm of django.
signup.html
class UserCreationForm(UserCreationForm):
email = EmailField(label=_("Email address"), required=True, help_text=_("Required."))
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
But I also need to make other tables in models.py. So if in another table category I need to make a foreign key of the primary key of this built in User of UserCreationForm. What is the primary key in this?
models.py
class category(models.Model):
uid = models.ForeignKey(#)
cname = models.CharField(max_length=20)
def __unicode__(self):
return u"{} {}".format(self.uid, self.cname)
class Meta:
db_table = "category"
What do I write in place of # ??
Just point to the User model:
from django.contrib.auth import User
uid = models.ForeignKey(User)
or better, in case you might want to customise the User model:
from django.conf import settings
uid = models.ForeignKey(settings.AUTH_USER_MODEL)

Save data in associative model using one query in django

I am working on registration module in django project. for registering user i am using auth_user table for extending this table i have created one more model Profile
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
start_date = models.DateField()
phone_number = models.CharField(max_length=12)
address = models.CharField(max_length=225)
subscription = models.BooleanField(default=False)
Profile table has been created successfully. Now what i want to do is when i submit the registration form, the fields related to Profile model within registration form should be inserted automatically after inserting fields related to auth_user model.
Means i don't want to first insert data in auth_user model and then after getting it's id again insert data in Profile table.
I want to insert complete record in one query. Is it possible ?
I think you can define a registration form and override the form save method to save the Profile when creating the User model. Sample code for your reference:
class RegistrationForm(forms.ModelForm):
start_date = forms.DateField()
phone_number = forms.CharField()
address = forms.CharField()
subscription = forms.BooleanField()
class Meta:
model = User
def save(self, commit=True):
instance = super(RegistrationForm, self).save(commit=commit)
profile = Profile(user=instance, start_date=self.cleaned_data['start_date'], phone_number=self.cleaned_data['phone_number'], address=self.cleaned_data['address'], subscription=self.cleaned_data['subscription'])
profile.save()
return instance
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save()
# do anything after user created
else:
raise Error('form validate failed')
else:
# handling the GET method

Django: Add another field to django-registration

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.

Categories