I found this post on how to extend the UserCreationForm with extra fields such as "email." However, the email field is already defined in the pre-built user model.
I created an extra model (called UserProfile) that futher extends Django's pre-built User class. How do I get these fields I defined in UserProfile to appear in my UserCreationForm?
Add fields as appropriate for your UserProfile model (it's not too easy to use a ModelForm to avoid Repeating Yourself, unfortunately), then create and save a new UserProfile instance in the over-ridden save() function. Adapted from the post you linked to:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
job_title = forms.CharField(max_length=100, required=True)
age = forms.IntegerField(required=True)
class Meta:
model = User
def save(self, commit=True):
if not commit:
raise NotImplementedError("Can't create User and UserProfile without database save")
user = super(UserCreateForm, self).save(commit=True)
user_profile = UserProfile(user=user, job_title=self.cleaned_data['job_title'],
age=self.cleaned_data['age'])
user_profile.save()
return user, user_profile
Related
I'm using django's built-in User model, but I also have my own Account model which extends it:
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
age = models.IntegerField(blank=True)
location = models.CharField(max_length=255, blank=True)
experience = models.TextField(blank=True)
in my admin.py file:
class AccountInline(admin.StackedInline):
model = Account
can_delete = False
verbose_name_plural = 'Accounts'
class CustomUserAdmin(UserAdmin):
inlines = (AccountInline,)
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
I want it to be that when a User registers they enter this information in, but my issue is getting both the UserForm and AccountForm in the same template/view.
As of now this is my registration view:
class UserRegistration(generic.CreateView):
form_class = RegisterForm
template_name = 'registration/registration.html'
def form_valid(self, form):
user = form.save()
form.registration_notification()
login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect(self.request.GET.get('next'))
How do I add my AccountForm to this view as well so that I can render both in the template and submit with one button. I've seen people do it with a function based view but is there a way to do it with a class-based view?
I also want the same idea for my UpdateView where a User can update User information, but also Account information. I assume it would follow the same logic.
You can use a Custom user model "Extend AbstractUser" since you want to add extra fields and add as many other fields as you want in a single model and avoid making extra queries to the database.
From Django documentation :
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
field 1
field 2
forms.py
from django.contrib.auth.forms import UserCreationForm
from myapp.models import User
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('custom_field',)
You can read more here
In my Django app, I have defined a Many-to-one relationship using ForeignKey. Now what I want is that when a logged-in user submits the ListForm then his username should automatically add to the owner field of the ListModel. Currently when a user submits the form, None is being shown in the owner field, how can I add the username to the database along with the form?
my models.py:
from django.db import models
from django.contrib.auth.models import User
class ListModel(models.Model):
owner = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
task = models.CharField(max_length=255)
completed = models.BooleanField(default=False)
my forms.py:
from django.forms import ModelForm
from .models import ListModel
from django import forms
class ListForm(ModelForm):
class Meta:
model = ListModel
fields = ['owner','task', 'completed']
You have to override the form_valid() method of the View and attach the current logged in user as an Owner.
def form_valid(self, form):
form.instance.owner = self.request.user <------ This line will do the trick.
return super().form_valid(form)
Finally got it working (my solution reference)
First, we need to exclude the owner field from the ModelForm in forms.py:
class ListForm(ModelForm):
class Meta:
model = ListModel
fields = ['task', 'completed']
# instead of above line we can simply write: exclude = ['owner']
and in the views.py:
form = ListForm(request.POST)
if form.is_valid():
task_list = form.save(commit=False)
task_list.owner = request.user
task_list.save()
return redirect('/')
where instead of task_list we can use any variable & also note that after task_list.save() no need to do form.save() because it's already included in task_list = form.save(commit=False)
I was dealing with user authentication in django and created a UserProfile model with foreign key to User in-built model. Then I created explicitly defined User model and then deleted it to restore the original code.
But now in my UserProfile database accessed from admin page is showing (None) for all the profiles created earlier.
And when I click on it it shows an error.
This is the code:
forms.py and models.py
from django import forms
from django.contrib.auth.models import User
from cms.models import UserProfile
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('designation',)
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
designation = models.CharField(max_length=128,blank=True)
def __unicode__(self):
return self.user.username
How do I delete that (None)?
As I said in comments, it's because your __unicode__() built-in method prints this user
Try change this part of the code to:
def __unicode__(self):
try:
return self.user.username
except:
return "UserProfile has No User instance"
I am new to Django and I have been trying this for weeks, but could not find a way to solve this problem.
I want to store additional information like user mobile number, bank name, bank account. And want to store the mobile number while user registers and wants user to login with either (mobile number and password) or (email and password).
This is my UserProfile model
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
user_mobile = models.IntegerField(max_length=10, null=True)
user_bank_name=models.CharField(max_length=100,null=True)
user_bank_account_number=models.CharField(max_length=50, null=True)
user_bank_ifsc_code = models.CharField(max_length=30,null=True)
user_byt_balance = models.IntegerField(max_length=20, null=True)
And this is my forms.py
from django import forms
from django.contrib.auth.models import User # fill in custom user info then save it
from django.contrib.auth.forms import UserCreationForm
from models import UserProfile
from django.contrib.auth import get_user_model
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
mobile = forms.IntegerField(required=True)
class Meta:
model = UserProfile
fields = ('username', 'email', 'password1', 'password2','mobile' )
def save(self,commit = False):
user = super(MyRegistrationForm, self).save(commit = False)
user.email = self.cleaned_data['email']
user.user_mobile = self.cleaned_data['mobile']
user.set_password(self.cleaned_data["password1"])
user_default = User.objects.create_user(self.cleaned_data['username'],
self.cleaned_data['email'],
self.cleaned_data['password1'])
user_default.save()
if commit:
user.save()
return user
In my settings.py I have included
AUTH_USER_MODEL = "registration.UserProfile"
admin.py of my app is
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'userprofile'
class UserProfileAdmin(UserAdmin):
inlines = (UserProfileInline, )
admin.site.register(UserProfile, UserProfileAdmin)
While adding the user from admin I get this error
Exception at /admin/registration/userprofile/1/
<class 'registration.models.UserProfile'> has no ForeignKey to <class 'registration.models.UserProfile'>
Can someone help me with this or point out to the full working exapmle, I have seen Django documentation but didn't find any luck. Or if there is another way to do this.
Thanks in advance
Edit 1:
While registering from the registration form I'm also getting this error
DatabaseError at /register
(1146, "Table 'django_auth_db.auth_user' doesn't exist")
You have confused yourself a bit here. The idea of subclassing AbstractUser - and defining AUTH_USER_MODEL as your subclass - is that the new model completely replaces auth.models.User. You shouldn't be importing the original User at all, and you certainly should be calling User.objects.create_user(): your new model's manager now has its own create_user method.
Because of this, there's no reason to muck about with inline admins. Your UserProfile should be registered in the admin using the existing django.contrib.auth.admin.UserAdmin class.
Inlines forms assume that you have a Generic ForeignKey on your model, in this case, the UserProfileAdmin expect a Generic ForeignKey of the UserProfile, that does not exists. Try to do a regular Model Admin, like:
class UserProfileAdmin(admin.ModelAdmin):
can_delete = False
verbose_name_plural = 'userprofile'
admin.site.register(UserProfile, UserProfileAdmin)
I extended the User model in django to include several other variables, such as location, and employer. Now I'm trying to create a form that has the following fields:
First name (from User)
Last name (from User)
Location (from UserProfile, which extends User via a foreign key)
Employer (also from UserProfile)
I have created a modelform:
from django.forms import ModelForm
from django.contrib import auth
from alert.userHandling.models import UserProfile
class ProfileForm(ModelForm):
class Meta:
# model = auth.models.User # this gives me the User fields
model = UserProfile # this gives me the UserProfile fields
So, my question is, how can I create a ModelForm that has access to all of the fields, whether they are from the User model or the UserProfile model?
Hope this makes sense. I'll be happy to clarify if there are any questions.
You can either create two model forms (one for User and one for UserProfile) or create a custom form with all your fields and dispatch them in your view.
from django import forms
class ContactForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
location = forms.CharField()
employer = forms.CharField()
You can't. ModelForm expects all its fields to come from a single model. Create a child of Form and pull the field definitions from the models.