Error when invoking creation of another form - django

models.py:
from django.db import models
from django.contrib.auth.models import User as BaseUser
CHOICE_GENDER = ((1, 'Male'), (2, 'Female'))
class Location(models.Model):
city = models.CharField(max_length=75)
country = models.CharField(max_length=25)
def __unicode__(self):
return ', '.join([self.city, self.state])
class Users(BaseUser):
user = models.OneToOneField(BaseUser, on_delete=models.CASCADE)
gender = models.IntegerField(choices=CHOICE_GENDER)
birth = models.DateField()
location = models.ForeignKey(Location)
class Meta:
ordering = ('user',)
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from .models import Users, Location, CHOICE_GENDER
class LocationForm(forms.ModelForm):
city = forms.CharField(max_length=75)
country = forms.CharField(max_length=25)
class Meta:
model = Location
fields = ('city', 'country',)
class RegistrationForm(UserCreationForm):
email = forms.CharField(max_length=75)
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
gender = forms.ChoiceField(choices=CHOICE_GENDER)
birth = forms.DateField()
location = LocationForm()
class Meta:
model = Users
fields = ('username', 'email', 'first_name', 'last_name', 'gender', 'birth')
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.gender = self.cleaned_data['gender']
user.birth = self.cleaned_data['birth']
if commit:
user.save()
return user
This code in forms.py doesn't work. It doesn't save LocationForm due to these errors:
country - This field is required.
city - This field is required.
I've certainly did something wrong here, but I don't know exactly what. I admit that I've jumbled the code in forms.py, especially in the save method for RegistrationForm because I don't know how to properly invoke the creation of another form and how to make a connection between two of them. I searched the Internet but I couldn't find precise info about that, so I tried to improvise but I've failed, unfortunately.
Could someone help me with this? Thanks in advance!
UPDATE: views.py (currently):
def signup(request):
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
location = loc_form.save()
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
pass
else:
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
I've also modified forms.py but I still got the error from above.

Instead of using LocationForm inside RegistrationForm you can handle them seprately in your views.py it will result in a cleaner code and easy to handle.
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
# since in your case they are dependent on each other
# save location form and get location object
location = loc_form.save()
# now you can use it in your reg_form
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
# no need to handle this case only for explanation
# use the forms, with valid post data initialized
# at the start of current if block
pass
else:
# create new forms for location and registration
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
You can read here more on how to handle more than one nested forms in django docs.

Related

Extended user model not save password correctly

im trying to create a child and parent objects at the same time with same form.
After migrations, i have two tables, user as always and doctor, whith the relationship with user in a extra column called user_ptr_id.
models.py:
class Doctor(User):
collegiated = models.CharField(verbose_name="Nº Colegiado", max_length=20, null=True, blank=True)
phone = models.CharField(verbose_name="Teléfono", max_length=12, null=True, blank=True)
class Patient(User):
age = models.PositiveIntegerField(verbose_name="Edad", blank=True)
forms.py:
class DoctorForm(forms.ModelForm):
class Meta:
model = app_models.Doctor
fields = ['username', 'email', 'password']
view.py:
if request.method == 'POST:
form = DoctorForm(request.POST.copy())
if form.is_valid():
forms.save()
else:
form = DoctorForm()
return ...
The two objects are created, doctor and user, well related with user_ptr_id but the user password appears unencrypted.
¿ How can i integrate UserCreationForm on child models ?
¿ How can i solve this issue ?
Anybody could help me please?
Thanks in advance.
use this in your views.py like this
also import make password
from django.contrib.auth.hashers import make_password
def user_signup(request):
if request.method == "POST":
user_form = userSignup(request.POST)
phone = request.POST['phone']
address = request.POST['address']
pincode = request.POST['pincode']
if user_form.is_valid() :
# Hash password using make_password() function
user = user_form.save(commit=False)
user.password = make_password(user.password)
user.save()
...

NOT NULL constraint failed: users_details.user_id

I've tried to add another details form that have address and birth date on my registration form page. Every time i tried to sign up i get the NOT NULL constraint failed error.
models.py
class Details(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=60, blank=True)
birth_date = models.DateField(null=True, blank=True)
views.py
def register(request):
if request.method == 'POST':
r_form = UserRegisterForm(request.POST)
o_form = DetailsForm(request.POST)
if r_form.is_valid and o_form.is_valid():
r_form.save()
o_form.save()
username = r_form.cleaned_data.get('username')
messages.success(request, f'Your account has been created!')
return redirect('login')
else:
r_form = UserRegisterForm()
o_form = DetailsForm()
context = {
'r_form' : r_form,
'o_form' : o_form
}
return render(request, 'users/register.html', context)
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1', 'password2']
class DetailsForm(forms.ModelForm):
address = forms.CharField()
birth_date = forms.DateField()
class Meta:
model = Details
fields = ['address', 'birth_date']
ERROR
While extraneous details/profile "sidecar" models are not the best practice since pluggable user models came along, this particular problem is caused by the two models not being associated.
Try
if r_form.is_valid and o_form.is_valid():
user = r_form.save()
o_form.instance.user = user
o_form.save()

Nested models form saving: This field is required error

models.py:
from django.db import models
from django.contrib.auth.models import User as BaseUser
CHOICE_GENDER = ((1, 'Male'), (2, 'Female'))
class Location(models.Model):
city = models.CharField(max_length=75)
country = models.CharField(max_length=25)
def __str__(self):
return ', '.join([self.city, self.state])
class Users(BaseUser):
user = models.OneToOneField(BaseUser, on_delete=models.CASCADE)
gender = models.IntegerField(choices=CHOICE_GENDER)
birth = models.DateField()
location = models.ForeignKey(Location)
class Meta:
ordering = ('user',)
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from .models import Users, Location
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = '__all__'
class RegistrationForm(UserCreationForm):
class Meta:
model = Users
fields = ('username', 'email', 'first_name', 'last_name', 'gender', 'birth', 'location')
views.py:
def signup(request):
if request.method == "POST":
reg_form = forms.RegistrationForm(request.POST)
loc_form = forms.LocationForm(request.POST)
if loc_form.is_valid():
reg_form.location = loc_form.save()
if reg_form.is_valid():
reg_form.save()
return redirect('./')
reg_form = forms.RegistrationForm()
loc_form = forms.LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form': reg_form})
I can't manage to make this work, it gives location - This field is required error. I've tried every combination in views.py, and it never passed the reg_form.is_valid() command due to that reason. Can anybody help me in this? Thanks in advance!
SOLVED: views.py new, working code:
def signup(request):
if request.method == "POST":
reg_form = forms.RegistrationForm(request.POST)
loc_form = forms.LocationForm(request.POST)
if reg_form.is_valid():
reg = reg_form.save(commit=False)
if loc_form.is_valid():
reg.location = loc_form.save()
reg.save()
return redirect('./')
reg_form = forms.RegistrationForm()
loc_form = forms.LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form': reg_form})
Removing location from RegistrationForm fields tuple should stop the behavior.
Since you are using a separate form for Location, you shouldn't populate location field using RegistrationForm.

How to hash text to md5/sha1 in django?

I want to convert text to sha1 in django. But, i'm not find the way how to do it if field attribut wrapped by the form.
This is my views:
def ubah_password_email(request, pk):
#cek session
if 'username' in request.session and request.session['hak_akses'] == 'user':
user = get_object_or_404(User, pk=pk) #ambil id dengan get
profile = UserProfile.objects.filter(user=user).first()
email_form = EmailForm(data=request.POST, instance=profile) #gunakan instance untuk mengambil data yang sudah ada
users = User.objects.all()
if request.POST:
if email_form.is_valid():
email = email_form.save(commit=False)
email.save()
return redirect('home')
else:
email_form = EmailForm(instance=profile)
data = {
'email_form': email_form,
'object_list': users,
}
return render(request, 'ubah_password_email.html', data)
else:
return HttpResponseRedirect('/simofa/logout')
This is my model
class UserProfile(models.Model):
user = models.OneToOneField(User) #digunakan untuk relasi ke model User (default) alias UserProfile adalah sebagai extending model
CATEGORY_CHOICES = (
('admin','Admin'),
('user','User'),
)
hak_akses = models.CharField(max_length=100, choices = CATEGORY_CHOICES)
password_email = models.CharField(max_length=100, blank=True)
password_pckelas = models.CharField(max_length=100, blank=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
This is my forms
class EmailForm(forms.ModelForm):
password_email = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = UserProfile
fields = ('password_email',)
i'm trying using this and this reference. But, i still can't convert text to sha1?
I'm very grateful for your input. So, please help me :)
I'm not sure why you want or need a second password field. But make_password allows you to generate a hashed password:
from django.contrib.auth.hashers import make_password
Docs: https://docs.djangoproject.com/en/1.7/topics/auth/passwords/#django.contrib.auth.hashers.make_password
Source: https://github.com/django/django/blob/master/django/contrib/auth/hashers.py#L58

Django: Changing User Profile by forms

I am using UserProfile to save some fields that I created. Its working fine. But I would like to create a new view to let user change (update) theses fields values. But, theses values arent being showing in form. Anyone have any idea how to fix it?
view.py
#login_required
def atualizar_cadastro_usuario(request):
if request.method == 'POST':
form = cadastrousuarioForm(request.POST,instance=request.user.get_profile())
if form.is_valid():
new_user = form.save()
return render_to_response("registration/cadastro_concluido.html",{})
else:
form = cadastrousuarioForm(request.POST,instance=request.user.get_profile())
return render_to_response("registration/registration.html", {'form': form})
form.py
class cadastrousuarioForm(UserCreationForm):
username = forms.EmailField(label = "Email",widget=forms.TextInput(attrs={'size':'60','maxlength':'75'}))
email = forms.EmailField(label = "Digite o Email novamente",widget=forms.TextInput(attrs={'size':'60','maxlength':'75'}))
nome = forms.CharField(label = 'Nome',widget=forms.TextInput(attrs={'size':'30','maxlength':'100'}))
cpf = BRCPFField(label='CPF')
data_nascimento=forms.DateField(widget=forms.DateInput(format = '%d/%m/%Y'), input_formats=('%d/%m/%Y',))
endereco = forms.CharField(label = 'Endereço',widget=forms.TextInput(attrs={'size':'30','maxlength':'100'}))
cidade = forms.CharField(label = 'Cidade')
estado = forms.CharField(widget=BRStateSelect(), label='Estado', initial = 'SP')
telefone = forms.CharField(label = "Telefone",widget=forms.TextInput(attrs={'size':'12','maxlength':'12'}))
escolaridade = forms.ChoiceField(choices=UserProfile.ESCOLARIDADE_ESCOLHAS)
profissao = forms.CharField(label = 'Profissão')
empresa = forms.CharField(label = 'Empresa',required=False)
receber_emails = forms.ChoiceField(choices=UserProfile.QUESTIONARIO_ESCOLHAS)
#captcha = CaptchaField(label = 'Digite as letras a seguir')
class Meta:
model = User
fields = ("username","email")
def save(self, commit=True):
user = super(cadastrousuarioForm, self).save(commit=False)
...
In bash, it works fine:
>>> from django.contrib.auth.models import User
>>> from cadastro.models import UserProfile
>>> u = User.objects.get(username='user#gmail.com')
>>> u.get_profile().telefone
u'123123455'
You need to change your model in the form from User to UserProfile. The form also needs to subclass ModelForm rather than UserCreationForm. Also, it looks like you're only using a subset of fields in your ModelForm (username and email). Finally, since you're using a ModelForm you don't need to define all of the model's fields in your form. Try changing your cadastrousuarioForm to the following:
class cadastrousuarioForm(ModelForm):
class Meta:
model = UserProfile
fields = ('username','email')
def save(self, commit=True):
user = super(cadastrousuarioForm, self).save(commit=False)