Using a registration form to add to custom user fields (django) - django

I'm creating custom user models for a registration form in django, but I'm having some problems getting the data into the database. Currently the users can register and their username, password, email, first name and last name are saved, but all the other form data isn't saving into the object. Below are my forms and the output:
Models.py
class Profile(models.Model):
user = models.OneToOneField(User)
gender = models.CharField(max_length=20)
medication = models.CharField(max_length=50, blank=True)
medical_history = models.CharField(max_length=50,blank=True)
DOB = models.CharField(max_length=20)
telephone = models.CharField(max_length=20)
address = models.CharField(max_length=30)
city = models.CharField(max_length=20)
state = models.CharField(max_length=20)
postcode = models.CharField(max_length=30)
forms.py:
class CreateAccountForm(ModelForm):
class Meta:
model = Profile
fields = ("username","password","password2","first_name","last_name",
"gender","medication","medical_history","DOB","email","telephone",
"address","city","state","postcode")
views.py:
def create_account(request):
form = CreateAccountForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
password2 = form.cleaned_data['password2']
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
gender = form.cleaned_data['gender']
medication = form.cleaned_data['medication']
medical_history = form.cleaned_data['medical_history']
DOB = form.cleaned_data['DOB']
email = form.cleaned_data['email']
telephone = form.cleaned_data['telephone']
address = form.cleaned_data['address']
city = form.cleaned_data['city']
state = form.cleaned_data['state']
postcode = form.cleaned_data['postcode']
if password == password2:
if (password_verification(password)) == 3:
if (username_verification(username)) == False:
form.save()
return HttpResponseRedirect('/login')
else:
return HttpResponseRedirect('/create_account')
else:
return HttpResponseRedirect('/create_account')
else:
return HttpResponseRedirect('/create_account')
return render(request, "create_account.html", {'form': form})
In the django admin window, the user is registering to the database with the create_user fields, but none of the added custom fields are saving in the available columns. Any help would be great this is really bugging me. Below is a pic of the empty fields, cheers!

You are saving User only user.save() so other Profile ( please change your user table to something meaningful Profile.
And also you don't need password first_name last_name email in your profile as well.
And I'll suggest to use the ModelForm to save the Profile table.
user_form = CreateAccountForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
# save the form after your password check
user_form.save()
profile_form.save()

Related

Django how to save value to model without being present on form post

I have the following Model/form/view:
Model
class Account(models.Model):
username = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=150)
identifier_type = models.ForeignKey(IdentifierType, on_delete=models.SET_NULL, null=True)
actflag = models.CharField(max_length=1, blank=True)
created_date = models.DateTimeField(blank=True, null=True)
comments = models.TextField(_(
'comments'), max_length=500, blank=True)
priority_type = models.ForeignKey(PriorityType, on_delete=models.SET_NULL, null=True)
deadline_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.name
Form
class PortfolioForm(forms.ModelForm):
portfolio = forms.CharField(widget=forms.Textarea)
class Meta:
model = Account
fields = ['name', 'comments', 'priority_type', 'deadline_date', 'identifier_type', 'portfolio']
View
def portfolios(request):
if request.user.is_authenticated:
if request.POST:
fm = PortfolioForm(request.POST)
user = User.objects.get(username=request.user)
if fm.is_valid():
messages.success(request, 'Portfolio has been created.')
fm.save()
return redirect('portfolios')
else:
fm = PortfolioForm()
context = {"name": request.user, "form": fm}
return render(request, 'portfolios.html', context)
else:
return redirect('login')
The form works fine with posting via my template, however you will notice there are some fields within my model that are not in my form I would like to fill in automatically without the user having to fill in - for example username field I would like this to be current user that submits the form and also created_date would like the current date time the user has submitted the form.
I tried to add the following to my view under if fm.is_valid(): attempting to save username as current user to the model but did not work:
Account.objects.username = request.user
How can I go about doing this? Thanks in advance
You can save these values after creating the Account object when you save the form. If you use the commit=False parameter in the save method, this does not hit the database and you can easy modify the Account object.
from django.utils import timezone
def portfolios(request):
if request.user.is_authenticated:
if request.POST:
fm = PortfolioForm(request.POST)
# user = User.objects.get(username=request.user)
if fm.is_valid():
account = fm.save(commit=False)
account.username = request.user
account.created_date = timezone.now()
account.save()
messages.success(request, 'Portfolio has been created.')
return redirect('portfolios')
else:
fm = PortfolioForm()
context = {"name": request.user, "form": fm}
return render(request, 'portfolios.html', context)
else:
return redirect('login')
You can use django forms instance for saving any predefined value without showing or render those fields to your users or html template. Here is an example how to automatically save your username and created_date fields .
if fm.is_valid():
fm = fm.save(commit=False)
fm.instance.username = request.user
fm.instance.created_date = timezone.now()
fm.save()

How to post data of logged in user with a form in Django?

I am creating a form for users to book times on my web app. Currently I have the following files.
see forms.py:
class BookingForm(forms.ModelForm):
usname = User.username
daterequired = forms.CharField(max_length=60, required=True)
students = forms.CharField(max_length=60, required=True)
length = forms.CharField(max_length=60, required=True)
class Meta:
model = Booking
fields = "__all__"
see models.py:
class Booking(models.Model):
usname = User.username
daterequired = models.DateField(_("Date"), default=datetime.date.today)
students = models.CharField(max_length=200)
length = models.CharField(max_length=40, blank=True)
see views.py:
#login_required
def choose(request):
if request.method == 'POST':
form = BookingForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.save()
return redirect('index')
else:
form = BookingForm()
return render(request, 'choose.html', {'form': form})
What I am trying to achieve is that when a user clicks submit on the form that their user data automatically gets logged in the bookings table on the database. At the minute the only data getting logged in the table is the date field, students and length. I need to know which user is posting this data.
Can anyone help?
First the model. The way you have defined usname is not valid. Change it to:
class Booking(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
daterequired = models.DateField(_("Date"), default=datetime.date.today)
students = models.CharField(max_length=200)
length = models.CharField(max_length=40, blank=True)
Then change the form to this:
class BookingForm(forms.ModelForm):
class Meta:
model = Booking
exclude = ['user', ]
You don't need to redefine fields if you use ModelForm.
Run makemigrations and migrate. Finally, change code inside choose() to:
if form.is_valid():
form = form.save(commit=False)
form.user = request.user
form.save()
return redirect('index')

Key Error with form - DJANGO

I have a project in django and I am creating a simple form that will allow a user to create a simple profile that asks for name and date of birth and location. I am getting a key error with the date of birth section and I dont know exactly why.
I am trying to collect data and store it to then later added it to a database record.
Here is the views file:
cd = form.cleaned_data
first_name = cd['first_name']
last_name = cd['last_name']
dob_month = cd['dob_month']
dob_day = ['dob_day']
dob_year = ['dob_year']
city = cd['city']
state = cd['state']
phone = cd['phone']
privacy = cd['privacy']
Here is the models file:
user = models.ForeignKey(User, on_delete=models.CASCADE) # server
first_name = models.CharField(max_length=25, default='first')
last_name = models.CharField(max_length=25, default='last')
dob_month = models.IntegerField(default=0)
dob_day = models.IntegerField(default=0)
dob_year = models.IntegerField(default=0)
city = models.CharField(max_length=45) # user
state = models.CharField(max_length=25, default='state')
phone = models.BigIntegerField(default=0) # user
privacy = models.SmallIntegerField(default=1) # user
created = models.DateTimeField(auto_now_add=True) # server
here is the forms file:
class ProfileForm(forms.ModelForm):
split_choices = (('1', 'public'),
('2', 'private'))
privacy = forms.TypedChoiceField(
choices=split_choices, widget=forms.RadioSelect, coerce=int
)
dob = forms.DateField(widget=extras.SelectDateWidget)
class Meta:
model = Profile
fields = ['first_name', 'last_name', 'dob', 'city', 'state', 'phone', 'privacy']
and finally, here is the error that I am getting:
KeyError at /setup_profile/
'dob_month'
Request Method: POST
Request URL: http://127.0.0.1:8000/setup_profile/
Django Version: 1.8.6
Exception Type: KeyError
Exception Value:
'dob_month'
Exception Location: C:\Users\OmarJandali\Desktop\opentab\opentab\tab\views.py in profile_setup, line 292
first_name 'omar'
last_name 'jandali'
dob_month '1'
dob_day '23'
dob_year '2024'
city 'riverside'
state 'ca'
phone '9515343666'
privacy '1'
submit 'submit'
UPDATED:
here is the views.py file but the issue is with the cd['dobv_month'], but i have no idea why the error is coming from there.
def profile_setup(request):
if 'username' not in request.session:
return redirect('login')
else:
# the following is just going to grab the currently logged in user and
# save the profile information to the appropriate user
username = request.session['username']
currentUser = User.objects.get(username = username)
# the following is the provessing for the form where the user entered
# the profile informaiton
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
first_name = cd['first_name']
last_name = cd['last_name']
dob_month = cd['dob_month']
dob_day = ['dob_day']
dob_year = ['dob_year']
city = cd['city']
state = cd['state']
phone = cd['phone']
privacy = cd['privacy']
# this is the new record that is going to be created and saved
new_profile = Profile.objects.create(
user = currentUser,
first_name = first_name,
last_name = last_name,
dob_month = dob_month,
dob_day = dob_day,
dob_year = dob_year,
city = city,
state = state,
phone = phone,
privacy = privacy,
)
return redirect('home_page')
else:
# this is what is going to be saved into the html file and used to
# render the file
form = ProfileForm()
message = 'fill out form below'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/profile_setup.html', parameters)
Let's say your model name is User.
forms.py:
from .models import User
class UserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
class Meta:
model = User
fields = '__all__'
and views.py:
def user_create(request):
form = UserForm(request.POST or None)
if request.method == 'POST':
form = UserForm(request.POST or None)
if not form.is_valid():
print form.errors
return render(request, 'user_create.html', {'form': form})
else:
first_name = form.cleaned_data.get("first_name")
last_name = form.cleaned_data.get("last_name")
# pass your extra fields here
new_user = User.objects.create_user(
user=user,
first_name=first_name,
last_name=last_name,
)
new_user.save()
return redirect('where you want to redirect',)
return TemplateResponse(request, 'user_create.html')
finally user will be save.
Read docs:https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/

Registration form save

I try to save two forms in registration. I can see the auth form save but the second form is not pass .is_valid(). Could you please let me know what is wrong?
Models.py
class School(models.Model):
id = models.IntegerField(primary_key=True)
Name = models.CharField(max_length=50, null=False)
Domain = models.CharField(max_length=50, null=False)
Mascot = models.ImageField(null=True, upload_to='mascot')
def delete(self, *args, **kwargs):
self.Mascot.delete()
super(School, self).delete(*args, **kwargs)
def __str__(self):
return self.Name
class HeepooUser(models.Model):
user = models.OneToOneField(User)
phone = models.CharField(max_length=15, null=True)
allow_phone = models.BooleanField(default=False)
school_id = models.IntegerField()
date_join = models.DateTimeField(auto_now_add=True)
forms.py
class UserForm(forms.ModelForm):
email = forms.EmailField(max_length=50, required=True)
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('email', 'password')
class RegisterForm(forms.ModelForm):
school_id = forms.ModelChoiceField(queryset=School.objects.all())
phone = forms.CharField(max_length=15, min_length=10, required=False)
class Meta:
model = HeepooUser
fields = ('phone', 'school_id')
views.py
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = RegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.set_password(user.password)
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile = profile_form.save()
registered = True
else:
return HttpResponse('Wrong access1')
else:
user_form = UserForm()
profile_form = RegisterForm()
return render(request, "register.html", {
'user_form': user_form,
'profile_form': profile_form,
'registered': registered,
})
I try to save email and password to auth_user and school_id and phone to separate table.
All the best!
tested your code and what I've encountered when submitting a form is
school_id value must be an integer
I'm suggesting to set school_id/school to be a foreignKey of the School model
class HeepooUser(models.Model):
user = models.OneToOneField(User)
phone = models.CharField(max_length=15, null=True)
allow_phone = models.BooleanField(default=False)
school_id = models.ForeignKey(School)
date_join = models.DateTimeField(auto_now_add=True)
so that we could just do the forms like this
class RegisterForm(forms.ModelForm):
class Meta:
model = HeepooUser
exclude = ('allow_phone', 'user')
also I think you don't need to specify the form fields for UserForm since by default django user only requires a password, username, and email
The problem is with how binary ANDs work. If user_form.is_valid() returns False, the "if" statement marks the whole statement as False without needing to evaluate profile_form.is_valid(). Therefore, profile_form.is_valid() never gets called and it's errors dict will not get populated. Unfortunately, django's form is_valid() does more than just return a boolean and has the side effect of populating that errors dict.
if user_form.is_valid() and profile_form.is_valid():
...
One thing you might be able to do is something like this:
user_valid = False
if user_form.is_valid():
user_valid = True
profile_valid = False
if profile_form.is_valid():
profile_valid = True
if user_valid and profile_valid:
... do something
The above ensures that both forms get processed. There might be a better way to express it, but that's the idea.

Custom Admin Creation Form

So in my models I have a specfic profile that has a one to one relationship with a more general profile that has a one to one relationship with the django user model. I want to be able to fill out one form in the django admin and create instances of all three models, with relationships already set up.
I haven't messed around with the django admin too much, so I'm not entirely sure how to make it work. Here is my failed attempt:
class CreateSpecializedProfileAdminForm(forms.ModelForm):
class Meta:
exclude = ['profile']
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=30)
password = forms.CharField(max_length=30)
confirm_password = forms.CharField(max_length=30)
def clean(self):
password = self.cleaned_data['password']
confirm_password = self.cleaned_data['confirm_password']
if len(self.cleaned_data['password']) < 6:
raise forms.ValidationError('Password must be at least 6 characters.')
if password != confirm_password:
raise forms.ValidationError('Passwords must match.')
return super(CreateSpecializedProfileAdminForm, self).clean()
def save(self, commit=True):
from django.contrib.auth.models import User
first = self.cleaned_data['first_name']
last = self.cleaned_data['last_name']
email = self.cleaned_data['email']
password = self.cleaned_data['password']
user = User.objects.create_user(email, email, password)
user.first_name = first
user.last_name = last
user.save()
profile = UserProfile()
profile.user_auth = user
profile.save()
specialized_profile = SpecializedProfile()
specialized_profile.profile = profile
specialized_profile.save()
return specialized_profile
class SpecializedProfileAdmin(admin.ModelAdmin):
form = CreateSpecializedProfileAdminForm
admin.site.register(SpecializedProfile, SpecializedProfileAdmin)
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
remove class Meta and move exclude = ['profile'] to ModelAdmin
class SpecializedProfileAdmin(admin.ModelAdmin):
exclude = ['profile']
form = CreateSpecializedProfileAdminForm