I tried adding another field (pin) in forms.py and models.py
The error i got was
"FieldError at /student/signup/
Cannot resolve keyword 'pin' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, password, user_infos, user_permissions, username"
forms.py
class RegisterForm(forms.Form):
GRADE_CHOICES = (
(9,'9'), (10,'10'), (11,'11'), (12,'12') ,
)
curr_year = date.today().year
GRAD_YEAR_CHOICES = (
(curr_year,curr_year), (curr_year+1,curr_year+1), (curr_year+2,curr_year+2), (curr_year+3,curr_year+3) ,
)
first_name = forms.CharField(max_length = 25)
last_name = forms.CharField( max_length = 25)
emailid = forms.EmailField()
passwd1 = forms.CharField(max_length=100,widget=forms.PasswordInput)
passwd2 = forms.CharField(max_length=100,widget=forms.PasswordInput)
gradyear = forms.ChoiceField( choices=GRAD_YEAR_CHOICES)
grade = forms.ChoiceField( choices=GRADE_CHOICES)
pin = forms.IntegerField()
def clean(self):
cleaned_data = super(RegisterForm, self).clean()
print cleaned_data
if cleaned_data['passwd1'] != cleaned_data['passwd2']:
raise forms.ValidationError({'passwd1':['Password do not match']})
if User.objects.filter(email=cleaned_data['emailid']).count():
raise forms.ValidationError({'emailid':['Email already taken ']})
if User.objects.filter(pin=cleaned_data['pin']).count():
raise forms.ValidationError({'pin':['Pin already taken ']})
return cleaned_data
views.py
def signup(request):
print "signup"
if request.method == 'POST':
print "post signup"
form = RegisterForm(request.POST)
try:
if form.is_valid():
print form.cleaned_data
u = User.objects.create_user(form.cleaned_data['emailid'], form.cleaned_data['emailid'], form.cleaned_data['passwd1'] )
ui = UserInfo()
ui.user = u
ui.class_of = form.cleaned_data['gradyear']
ui.grade = form.cleaned_data['grade']
ui.balance = 0
print "Hi"
ui.pin = form.cleaned_data['pin']
print ui.pin
u.first_name = form.cleaned_data['first_name']
u.last_name = form.cleaned_data['last_name']
u.save()
ui.save()
user = authenticate(username=form.cleaned_data['emailid'], password=form.cleaned_data['passwd1'])
login(request,user)
print "after login in signup"
return redirect("/")
else:
print "error"
print form.errors
except:
raise
print "error here"
print form.errors
pass
#return render(request, 'student/register.html', {'form': form})
else:
form = RegisterForm()
return render(request, 'student/register.html', {'form': form})
models.py:
class UserInfo(models.Model):
user = models.OneToOneField(User, related_name='user_infos')
class_of = models.IntegerField()
#username = user.username
#fname = user.fname
#lname = user.last_name
#email = user.email
#Staff = user.is_staff
pub_date = models.DateTimeField( auto_now=True)
grade = models.IntegerField()
balance = models.DecimalField(max_digits=6, decimal_places=2)
pin = models.IntegerField()
#first_name = models.CharField(max_length = 25)
I don't think not be doing this right. Is there any way to add another column in a database another way?
You have "pin" field in your UserInfo model, but in forms.py you are trying to filter User model:
if User.objects.filter(pin=cleaned_data['pin']).count():
User model does not have "pin" field, so you are getting that error message.
Also I suggest you to learn and start using ModelForms: https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/
Related
I am using a Userprofile form with an UpdateView and encountering an issue where validation errors are not being raised, even when the conditions for the errors to be raised are met. What could be causing this unexpected behavior?
forms.py.
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ("avatar","username","first_name","last_name","age","gender")
# fields = ("avatar",)
Gender = (
('one','Male'),
('two','Female'),
)
widgets ={
'age' : forms.TextInput(attrs={'class':'form-control'}),
'gender' : forms.Select(choices=Gender,attrs={'class': 'form-control'}),
}
# TRIED THIS AS WELL
# def clean_age(self):
# age = self.cleaned_data["age"]
# print(age,'hm here')
# if age < 18:
# print(age,'hm here')
# raise forms.ValidationError("You're age should be 18 plus")
# return age
def clean(self):
cleaned_data = super().clean()
age = cleaned_data.get('age')
print('haye',age)
if age < 18:
print(age,'hm here')
# raise forms.ValidationError("You're age should be 18 plus")
age = "You're age should be 18 plus"
self.add_error('age',age)
raise forms.ValidationError("You're age should be 18 plus")
views.py
here i'm updated user model fields and then userprofile field and then saving them respectively.
class UserProfileUpdateView(UpdateView):
refirect_field_name ='accounts:profile'
template_name = 'accounts/profiles/profile_update.html'
form_class = UserProfileForm
model = UserProfile
def get_object(self, *args, **kwargs):
return self.request.user.userprofile
def get_context_data(self, *args, **kwargs):
context = super(UserProfileUpdateView, self).get_context_data(*args, **kwargs)
update_form = UserProfileForm(instance = self.request.user.userprofile)
context['form']=update_form
return context
def form_valid(self, form):
username = form.cleaned_data['username']
print('username :',username)
first_name = form.cleaned_data['first_name']
print('first name :',first_name)
last_name = form.cleaned_data['last_name']
print('last name :',last_name)
age = form.cleaned_data['age']
print('age :',age)
gender = form.cleaned_data['gender']
print('gender :',gender)
# usermodel save
user = User.objects.get(username=self.request.user)
print('GOT reqested User',user)
user.username = username
print('changed username :',user.username)
user.age = age
print('changed age :',user.age)
user.gender = gender
print('changed gender:',user.gender)
user.first_name = first_name
print('changed first name :',user.first_name)
user.last_name = last_name
print('changed last name :',user.last_name)
user.save()
# userprofile save
profile = UserProfile.objects.get(user=self.request.user)
print('GOT reqested User',profile)
profile.username = username
print('changed username :',profile.username)
profile.age = age
print('changed age :',profile.age)
profile.gender = gender
print('changed gender:',profile.gender)
profile.first_name = first_name
print('changed first name :',profile.first_name)
profile.last_name = last_name
print('changed last name :',profile.last_name)
profile.save()
form.save()
return super().form_valid(form)
models.py
class UserProfile(models.Model):
user = models.OneToOneField(auth.models.User,related_name='userprofile', on_delete=models.CASCADE)
avatar = models.ImageField(("displays"), upload_to='displays', height_field=None, width_field=None, max_length=None,default ='user.jpg')
create_date = models.DateTimeField(default = timezone.now)
Gender = (
('one','Male'),
('two','Female'),
)
first_name = models.CharField(("first_name"), max_length=50,null=True)
last_name = models.CharField(("last_name"), max_length=50,null=True)
username = models.CharField(("username"), max_length=50,null=True)
age = models.IntegerField(("age"),null=True)
gender = models.CharField(("gender"), max_length=50,choices=Gender,null=True)
def __str__(self):
return f'{self.user.username} UserProfile'
def clean_fields(self, exclude=None):
if self.age < 18:
raise ValidationError(
{"age": "You're age should be 18+"}
)
return super().clean_fields(exclude=exclude)
def save(self,*args, **kwargs):
if not self.username:
self.username = self.user.username
if not self.age:
self.age = self.user.age
if not self.gender:
self.gender = self.user.gender
if not self.first_name:
self.first_name = self.user.first_name
if not self.last_name:
self.last_name = self.user.last_name
super(UserProfile,self).save(*args, **kwargs)
Please tell me how can i fix this issue and raise errors on unvalid details.
If more information is require then tell me in a comment section, I'll update my question with that information.
By using both methods there is no need to override form's clean method and the object is validated whenever you create an instance.
Method 1:
Override clean_fields method of class UserProfile in models.py
def clean_fields(self, exclude=None):
if self.age < 18:
raise ValidationError(
{"age": "You're age should be 18+"}
)
return super().clean_fields(exclude=exclude)
Method 2:
Add min value validation for age field while defining it
age = models.PositiveIntegerField(
help_text="Age of the user.",
validators=[
MinValueValidator(
18, "You're age should be 18+"
)
]
)
Your views:
def form_valid(self, form):
# userprofile save
profile = form.save(commit=False)
# usermodel save
user = self.request.user
user.username = profile.username
user.age = profile.age
user.gender = profile.gender
user.first_name = profile.first_name
user.last_name = profile.last_name
user.save()
return super().form_valid(form)
In Django, I want to build a form that collects shipping addresses from users! Then save them to database
There is views.py starts with defining a function "is_valid_form(values)"
def is_valid_form(values):
valid = True
for field in values:
if field == '':
valid = False
return valid
class EnCheckoutView(View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
form = CheckoutForm()
context = {
'form': form,
'couponform': CouponForm(),
'order': order,
'DISPLAY_COUPON_FORM': True
}
shipping_address_qs = Address.objects.filter(user=self.request.user, address_type='S', default=True)
if shipping_address_qs.exists():
context.update({
'default_shipping_address': shipping_address_qs[0]
})
return render(self.request, 'en-checkout-page.html', context)
except ObjectDoesNotExist:
messages.info(self.request, 'You do not have an active order.')
return redirect('core:en-checkout')
def post(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
except ObjectDoesNotExist:
messages.warning(self.request, 'You do not have an active order')
return redirect('core:en-order-summary')
form = CheckoutForm(self.request.POST or None)
if form.is_valid():
use_default_shipping = form.cleaned_data.get("use_default_shipping")
if use_default_shipping:
print('Using the default shipping address')
address_qs = Address.objects.filter(user=self.request.user, default=True)
if address_qs.exists():
shipping_address = address_qs[0]
order.shipping_address = shipping_address
order.save()
else:
messages.info(self.request, 'No default shipping address available')
return redirect('core:en-checkout')
else:
print('User is entering a new shipping address')
customer_name = form.cleaned_data.get('customer_name')
phone = form.cleaned_data.get('phone')
email = form.cleaned_data.get('email')
shipping_address1 = form.cleaned_data.get('shipping_address1')
shipping_address2 = form.cleaned_data.get('shipping_address2')
en_shipping_country = form.cleaned_data.get('en_shipping_country')
shipping_zip = form.cleaned_data.get("shipping_zip")
if is_valid_form([customer_name, phone, shipping_address1]):
shipping_address = Address(
user=self.request.user,
customer_name=customer_name,
phone=phone,
email=email,
street_address=shipping_address1,
apartment_address=shipping_address2,
country=en_shipping_country,
zip=shipping_zip,
address_type='S'
)
shipping_address.save()
order.shipping_address = shipping_address
order.save()
set_default_shipping = form.cleaned_data.get('set_default_shipping')
if set_default_shipping:
shipping_address.default = True
shipping_address.save()
else:
messages.info(self.request, 'Please ***fill in the required shipping address fields')
en_payment_option = form.cleaned_data.get('en_payment_option')
if en_payment_option == 'S':
return redirect('core:en-payment', en_payment_option='Pay with credit card')
elif en_payment_option == 'P':
return redirect('core:ar-delivery', en_payment_option='Cash on delivery')
else:
messages.warning(self.request, 'Invalid payment option selected')
return redirect('core:en/checkout')
Why this form does not save the address to the database?
I could have posted forms.py, html template, and models.py, but I guess that will explain the problem.
forms.py
EN_PAYMENT_CHOICES = (
('S', 'Pay with credit card'),
('P', 'Cash on delivery')
)
class CheckoutForm(forms.Form):
customer_name = forms.CharField(max_length=100, required=True)
phone = forms.IntegerField(required=True)
email = forms.EmailField()
shipping_address1 = forms.CharField(required=True)
shipping_address2 = forms.CharField(required=False)
ar_shipping_country = CountryField(blank_label='(اختار البلد)').formfield(
required=False,
widget=CountrySelectWidget(attrs={
'class': 'custom-select d-block w-100',
}))
en_shipping_country = CountryField(blank_label='(Choose a country)').formfield(
required=False,
widget=CountrySelectWidget(attrs={
'class': 'custom-select d-block w-100',
}))
shipping_zip = forms.CharField(required=False)
set_default_shipping = forms.BooleanField(required=False)
use_default_shipping = forms.BooleanField(required=False)
payment_option = forms.ChoiceField(
widget=forms.RadioSelect, choices=PAYMENT_CHOICES)
en_payment_option = forms.ChoiceField(
widget=forms.RadioSelect, choices=EN_PAYMENT_CHOICES)
models.py
class Address(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
customer_name = models.CharField(max_length=100, null=True)
phone = models.IntegerField(null=True)
email = models.EmailField(null=True)
street_address = models.CharField(max_length=250)
apartment_address = models.CharField(max_length=250)
country = CountryField(multiple=False, null=True)
zip = models.CharField(max_length=100)
address_type = models.CharField(max_length=1, choices=ADDRESS_CHOICES)
default = models.BooleanField(default=False)
def __str__(self):
return self.user.username
class Meta:
verbose_name_plural = 'Addresses'
The code works well but when trying to add a new user to the site it logs in as the superuser only.
Model
class RegistrationForm(forms.Form):
username = forms.CharField(label = 'Username', max_length = 30)
first_name = forms.CharField(label = 'First name', max_length = 30,widget=forms.TextInput(attrs={'class' : 'Name'}))
last_name = forms.CharField(label = 'Last name', max_length = 30,widget=forms.TextInput(attrs={'class' : 'Name'}))
email1 = forms.EmailField(label = 'email', required = True,widget=forms.TextInput(attrs={'class' : 'email'}))
email2 = forms.EmailField(label = 'Re-enter email',widget=forms.TextInput(attrs={'class' : 'email'}))
password1 = forms.CharField(label= "Password", widget = forms.PasswordInput(attrs={'class' : 'password1'}))
birthday = forms.DateField(label = 'Birthday',widget=forms.TextInput(attrs={'class' : 'birthday'}))
class Meta:
model = User
fields = ('username', 'email', 'password1','password2')
def save(self, commit = True):
user = super(RegistrationForm, self).save(commit = False)
user.email1 = self.cleaned_data['email1']
user.email2 = self.cleaned_data['email2']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.birthday = self.cleaned_data['birthday']
if commit:
user.save()
return user
def clean_username(self):
email1 = self.cleaned_data['email1']
if not re.search(r"(^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email1):
raise forms.ValidationError('Use a real email address eg. something#example.com.')
try:
user.objects.get(email1 = email1)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('email is already in use.')
def clean_username(self):
username = self.clean_data['username']
if not re.search(r'^\w+$', username):
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
user.objects.get(username = username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
Views
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
user = User.objects.create_user(
username = form.clean_data['username'],
password = form.clean_data['password1'],
email = form.clean_data['email']
)
return HttpResponseRedirect('/register/success/')
else:
args = {}
args.update(csrf(request))
args['form'] = RegistrationForm()
print(args)
return render(request, 'registration/register.html', args)
I know there are a lot of similar questions here, but none of them seem to be working with my view in Django 1.8 with a ModelForm.
I have a user profile form that works as long as I have each required field in the template context, but I only want each logged in user to fill out their own form.
I'm doing something wrong here, and I'm not sure what the problem is. Can someone correct me? I've spent hours looking at other posts and trying various suggestions from SO. I'm getting "NOT NULL constraint failed: camp_userprofile.user_id"
Here's my models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
picture = models.ImageField(upload_to='profile_images', blank=True)
city = models.CharField(max_length = 20)
needs_camp_bike = models.BooleanField(default=False)
diet_lifestyle = models.CharField(max_length = 200, choices=What_are_you, null=True, blank=True)
meal_restrictions = models.CharField(max_length = 200, blank= True)
other_restrictions = models.CharField(max_length=100, blank=True)
arrival_day = models.IntegerField(choices=Days)
departure_day = models.IntegerField(choices=Days)
date = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return '%s %s %s %s %s %s %s %s %s' %(
self.user, self.picture, self.city,
self.needs_camp_bike,
self.diet_lifestyle, self.meal_restrictions, self.other_restrictions,
self.arrival_day, self.departure_day
)
My forms.py
class UserProfileForm(ModelForm):
class Meta:
Fish = "Fish"
Mammal = "Mammal"
Vegetarian = "Vegetarian"
Omnivore = "Omnivore"
Onions = "Onions"
Cucumber = "Cucumber"
Peppers = "Peppers"
Gluten_free = "Gluten_free"
Vegan = "Vegan"
Shellfish = "Shellfish"
Olives = "Olives"
Pork = "Pork"
Soy = "Soy"
Dairy = "Dairy"
Cilantro = "Cilantro"
Quinoa = "Quinoa"
Nightshades = "Nightshades"
Nuts = "Nuts"
Pescaterian = "Pescaterian"
Restrictions = (
(Mammal, "Mammal"),
(Onions, "Onions"),
(Cilantro, "Cilantro"),
(Soy, "Soy"),
(Dairy, "Dairy"),
(Quinoa, "Quinoa"),
(Pork, "Pork"),
(Olives, "Olives"),
(Dairy, "Dairy"),
(Peppers, "Peppers"),
(Cucumber, "Cucumber"),
(Nightshades, "Nightshades"),
(Nuts, "Nuts")
)
model = UserProfile
fields = ('picture', 'city',
'needs_camp_bike', 'diet_lifestyle',
'other_restrictions', 'arrival_day',
'departure_day', 'meal_restrictions')
widgets = {
'meal_restrictions': forms.widgets.CheckboxSelectMultiple(choices=Restrictions),
}
and my views.py
#login_required
def profile(request):
form = UserProfileForm(request.POST)
print(request.user)
if request.method == 'POST':
if form.is_valid():
form.save(commit=False)
form.user =request.user.username
form.save(commit=True)
else:
print(messages.error(request, "Error"))
return render(request, "profile.html", RequestContext(request, {'form': form, 'profile': profile,}))
You shouldn't do form.user = request.user.username, because form.user won't add the user to the form. You should capture the object that form.save(commit=false) returns, then assign the user to that object and save it.
Also you cannot assign a user field with username, username is only a string not User object. You should do this instead:
if form.is_valid():
userprofile = form.save(commit=False)
userprofile.user = request.user
userprofile.save()
this is my views.py
def signup(request):
print "signup"
if request.method == 'POST':
print "post signup"
form = RegisterForm(request.POST)
try:
if form.is_valid():
print form.cleaned_data
u = User.objects.create_user(form.cleaned_data['emailid'], form.cleaned_data['emailid'], form.cleaned_data['passwd1'] )
ui = UserInfo()
ui.user = u
ui.class_of = form.cleaned_data['gradyear']
ui.grade = form.cleaned_data['grade']
ui.balance = 0
ui.save()
and in my forms.py i have:
class RegisterForm(forms.Form):
GRADE_CHOICES = (
(9,'9'), (10,'10'), (11,'11'), (12,'12') ,
)
curr_year = date.today().year
GRAD_YEAR_CHOICES = (
(curr_year,curr_year), (curr_year+1,curr_year+1), (curr_year+2,curr_year+2), (curr_year+3,curr_year+3) ,
)
first_name = forms.CharField(max_length = 25)
last_name = forms.CharField( max_length = 25)
emailid = forms.EmailField()
passwd1 = forms.CharField(max_length=100,widget=forms.PasswordInput)
passwd2 = forms.CharField(max_length=100,widget=forms.PasswordInput)
gradyear = forms.ChoiceField( choices=GRAD_YEAR_CHOICES)
grade = forms.ChoiceField( choices=GRADE_CHOICES)
def clean(self):
cleaned_data = super(RegisterForm, self).clean()
if cleaned_data['passwd1'] != cleaned_data['passwd2']:
raise forms.ValidationError({'passwd1':['Password do not match']})
if User.objects.filter(email=cleaned_data['emailid']).count():
raise forms.ValidationError({'emailid':['Email already taken ']})
return cleaned_data
why does everything print to the database except first_name and last_name??? (username, email, grade, gradyear, and password all save)
EDIT: This is my UserInfo
class UserInfo(models.Model):
user = models.OneToOneField(User, related_name='user_infos')
class_of = models.IntegerField()
#username = user.username
#fname = user.fname
#lname = user.last_name
#email = user.email
#Staff = user.is_staff
pub_date = models.DateTimeField( auto_now=True)
grade = models.IntegerField()
balance = models.DecimalField(max_digits=6, decimal_places=2)
#first_name = models.CharField(max_length = 25)
In the code provided, you never save first_name and last_name for User or UserInfo.
In def signup(request):, right after this line:
u = User.objects.create_user(form.cleaned_data['emailid'], form.cleaned_data['emailid'], form.cleaned_data['passwd1'] )
Try including this:
u.first_name = form.cleaned_data['first_name']
u.last_name = form.cleaned_data['last_name']
u.save()