Replacing the value of one form field with another - django

I have written a piece of code where the user can select an occupation from a select box (teacher, doctor, pilot, etc) and if their occupation isn't in the list they can select 'other' then write their occupation in a textbox underneath.
I can successfully detect if they selected 'other' from the dropdown box, but cannot figure out how to populate the 'occupation' field with the data from the 'other' field.
if request.method == 'POST':
form = OccupationForm(request.POST, request.FILES, instance=request.user.occupation)
if form.is_valid():
# if user selected 'other' - get input from text field
if form['occupation'].value() == 'other':
# this doesnt work
#form_data = self.get_form_step_data(form)
#form.other = form_data.get('other', '')
#form.save()
return redirect('#')
#form.save()
#return redirect('#')
else:
form = OccupationForm(instance=request.user.occupation)
Thank you.
EDIT:
shortened models.py
class Occupation(models.Model):
# I just realized, maybe this should be OneToManyField ??
user = models.OneToOneField(User, on_delete=models.CASCADE)
OCCUPATIONS = (
('teacher', 'Teacher'),
('doctor', 'Doctor'),
('other', 'Other'),
)
occupation = models.CharField('What is your job?', max_length=200, null=True, choices=OCCUPATIONS)
shortened forms.py
class OccupationsForm(forms.ModelForm):
other = forms.CharField(required=False, label='')
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('occupations') == 'other':
cleaned_data['occupations'] = cleaned_data.get('other')
return cleaned_data
class Meta:
model = Occupations
fields = ['occupations']
Thank you

The clean methods of your form is the place where you validate and clean data sent to the form, this includes potentially changing the data.
class OccupationForm(forms.ModelForm):
....
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('occupation') == 'other':
cleaned_data['occupation'] = cleaned_data.get('other')
return cleaned_data
Now you can just call form.save straight after form.is_valid as the clean method will have cleaned/returned the correct data

Related

Django ModelForm Custom Date Field

I am trying to create a reservation form that creates an object for model Reservation when the form is posted. I am using a custom datepicker widget to pick the ate, but I am also using ModelForms.
The issue is that, if I do not have 'date' listed in the meta fields list in the forms.py, then the form doesn't look for the date field form input on post. But if I include 'date' inside the meta fields of the forms.py Modelform, then it errors and says "date field can not be left blank" even though it is not blank...
forms.py
class ReservationForm(forms.ModelForm):
date = forms.DateField(
widget=DatePickerInput(format='%m/%d/%Y')
)
def clean_date(self):
data = self.cleaned_data['date']
# Check if a date is not in the past.
if data < datetime.date.today():
raise ValidationError(_('Invalid date - reservation in past'), code='invalid')
messages.danger(request, "Reservation Created")
print('ERROR')
# Remember to always return the cleaned date.
return data
class Meta:
model = Reservation
fields = ('reservation_time', 'people', 'name', 'email', 'phone') # REMOVED 'date'
views.py
def reservationFormView(request):
#reservation = create(Reservation)
# If this is a POST request then process the Form data
if request.method == 'POST':
# Create a form instance and populate it with data from the request (binding):
form = ReservationForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required
reservation = form.save(commit=False)
reservation.ReservationEmail = form.cleaned_data['email']
reservation.ReservationName = form.cleaned_data['name']
reservation.ReservationPeople = form.cleaned_data['people']
reservation.ReservationTime = form.cleaned_data['reservation_time']
reservation.date = form.cleaned_data['date']
print( reservation.date)
#reservation.created_time = timezone.now()
reservation.save()
# redirect to a new URL:
return HttpResponseRedirect('/reservation-confirmation/')
# If this is a GET (or any other method) create the default form.
else:
form = ReservationForm()
return render(request, 'home/reservation_form.html', {'form': form, })
models.py
class Reservation(BaseModel):
class Meta:
verbose_name_plural = "Reservations"
TIME_CHOICES = (
...
)
SEATING_CHOICES = (
...
)
date = models.DateField(null=True)
name = models.CharField(max_length=35, null=True)
phone = PhoneNumberField(null=True) #USE THIS https://github.com/stefanfoulis/django-phonenumber-field
email = models.EmailField(null=True)
people = models.PositiveSmallIntegerField(choices=SEATING_CHOICES, default=None, db_index=True)
reservation_time = models.PositiveSmallIntegerField(choices=TIME_CHOICES, default=None, db_index=True)
def __str__(self):
return '(%s) %s %s' % (self.date, self.name, self.phone )
Your clean_date method does not return a value in case the if condition is False. You should return the cleaned data in case it is correct, like:
def clean_date(self):
data = self.cleaned_data['date']
# Check if a date is not in the past.
if data < datetime.date.today():
raise ValidationError(_('Invalid date - reservation in past'), code='invalid')
messages.danger(request, "Reservation Created")
# not indented under the if
return data
Otherwise, this function will return None in case the data is valid, and raise a ValidationError in case the data is invalid.

Django UserChangeForm custom validation

ValueError: The Custom_User could not be changed because the data didn't validate.
I am trying to make a UserChangeForm to allow customers to edit their address, contact or password. However, for the field "postal code" I have set a restriction where there are only certain postal addresses I want to service.
#forms.py
#Extract list of postal codes which are valid and put into a list
valid_postal_code = []
postal_code_model = PostalCode.objects.all()
for code in postal_code_model:
valid_postal_code.append(code.postal_code)
#form
class EditAccountForm(UserChangeForm):
class Meta:
model = Custom_User
fields = (
'address',
'postal_code',
'unit_number',
'email',
'contact_number',
'password'
)
def clean_postal_code(self):
post_code = self.cleaned_data.get('postal_code')
if post_code not in valid_postal_code:
print('hello')
raise forms.ValidationError('Sorry we do not serve this postal code right now D:')
return post_code
If the user inputs a postal code that is not in the valid_postal_code list, I would like that the form be able to raise an Error message on the form.
However, I get the above error(which is to be expected), straight away without the raising for error.
#views.py
def edit_info_page(request):
if request.method == 'POST':
form = EditAccountForm(request.POST, instance=request.user)
if form.is_valid:
form.save()
print('form changed')
return redirect('home:edit_info_page')
else:
form = EditAccountForm(instance=request.user)
return render(request, 'sign/edit_info.html', {'form':form})
#models
class Custom_User(AbstractUser):
postal_code = models.IntegerField(null=True)
unit_number = models.CharField(max_length=10)
address = models.CharField(max_length=250)
contact_number = models.IntegerField(null=True)
order_count = models.PositiveIntegerField(default=0)
total_spending = models.DecimalField(max_digits=10, decimal_places=2, default=0)
def __str__(self):
return self.username
Above are my models and views for reference. IMO, I think I am definitely missing something here but Im just not too sure how to break into the UserChangeForm. I'm still a relative newbie (haven't sent anything into production yet). Any advice would be great!
In the view change:
if form.is_valid:
to
if form.is_valid():
The validation is not getting executed, which consequently does not validate your post data, which in turn does not allow you to save the user.
Suggestion:
Change
if post_code not in valid_postal_code:
to
if post_code and post_code not in valid_postal_code:
to ensure to raise the error only if user has entered something.
Try this
class EditAccountForm(UserChangeForm):
class Meta:
model = Custom_User
fields = (
'address',
'postal_code',
'unit_number',
'email',
'contact_number',
'password'
)
def clean_postal_code(self):
valid_postal_code = PostalCode.objects.all().values_list('postal_code', flat=True)
post_code = self.cleaned_data.get('postal_code')
if post_code not in valid_postal_code:
raise forms.ValidationError('Sorry we do not serve this postal code right now D:')
return post_code
Better way to write AJAX call for postal_code field and call ajax function from postal_code focus out/blur event,
Or Make the postal code field auto complete or selection field

storing data to database with html form in django

form.valid is not working,when i fill the form the data should store in database using html form and also how to upload image,how to define the form in html page,is there anything wrong in my code,below is my models.py,views.py,forms.py is given,i have search many forums but not able to get answer
models.py
class Deal(models.Model):
Deal_Category = models.CharField(max_length=30, choices=(('F','Fashion'),
('T', 'Travel') ))
Deal_Title = models.CharField(max_length=30,blank=True)
Deal_Redemption = models.CharField(max_length=50,blank=True)
Deal_Start = models.DateField()
Deal_End =models.DateField()
Deal_Details = models.CharField(max_length=50,blank =True)
Deal_Location= models.CharField(max_length=50,blank =True)
Deal_Terms = models.CharField(max_length=50,blank =True)
#Images = models.ImageField(upload_to='static/image',blank=True)
forms.py
class DealForm(forms.ModelForm):
class Meta():
model= Deal
fields=('Deal_Category','Deal_Title','Deal_Redemption','Deal_Start','Deal_End','Deal_Details',
'Deal_Location','Deal_Terms')
views.py
def deal_form(request):
print("Deal")
if request.method == 'POST':
print("user")
form = DealForm(data=request.POST )
print("Deal1")
if form.is_valid():
print("Deal2")
form.save(commit=True)
print("Deal4")
return render(request, 'advertizer/adver_create_coupon.html')

django issues between forms and models

i am a beginner with Django. I want to ask how can i access a variable in forms.py to print out for the user. I know that models.py create the database for the user. The variable that i want to print it is a checkbox multiple choice field. I need to print the value of the multiplechoice in a table.The image is here
This is the Form.py:
class BacktestForm(forms.ModelForm):
period_start = forms.DateField(initial=datetime.datetime.today().date() - datetime.timedelta(days=365+16), widget=forms.widgets.DateInput(format="%Y/%m/%d"), input_formats=["%Y/%m/%d"])
period_end = forms.DateField(initial=datetime.datetime.today().date() - datetime.timedelta(days=16), widget=forms.widgets.DateInput(format="%Y/%m/%d"), input_formats=["%Y/%m/%d"])
market = forms.MultipleChoiceField(required=False,widget=CheckboxSelectMultiple, choices=MARKET_CHOICES)
sector = forms.MultipleChoiceField(required=False,widget=CheckboxSelectMultiple, choices= MEDIA_CHOICES)
class Meta:
model = Parameters
Models.py:
class Parameters(models.Model):
user = models.ForeignKey(User)
title = models.CharField('title', max_length=100, default='', blank=True, help_text='Use an indicative name, related to the chosen parameters')
type = models.CharField('forecast type', choices=FORECAST_TYPES, max_length=20, default="backtest")
#input characteristics
price_1_min = models.FloatField('1. Price, min', default=0.1, validators=[MinValueValidator(0.1), MaxValueValidator(20000)])
price_1_max = models.FloatField('1. Price, max', default=20000, validators=[MinValueValidator(0.1), MaxValueValidator(20000)])
This is my view.py for the button save:
def backtest(request, pk=None):
if pk is not None:
param = get_object_or_404(Parameters, pk=pk, user=request.user)
form = BacktestForm(request.POST or None, instance=param)
else:
form = BacktestForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
if 'save' in request.POST:
obj = form.save(commit=False)
obj.user = request.user
obj.type = "backtest"
obj.save()
messages.info(request, 'Saved!')
return redirect(obj.get_backtest_url())
Please post the full forms class. I don't see how your model and form is connected. I think you might need a modelform instead of a form if you want to access the model.
So the way to connect them would be like this
forms.py
from .models import Parameter
class ParameterForm(forms.ModelForm):
market = forms.MultipleChoiceField(required=False,widget=CheckboxSelectMultiple, choices=MARKET_CHOICES)
sector = forms.MultipleChoiceField(required=False,widget=CheckboxSelectMultiple, choices= MEDIA_CHOICES)
class Meta:
model = Parameters

Django IntegrityError signup_simplesubscriber.date_created may not be NULL

I've read every "InterityError" + "may no be NULL" post and still can't track down what's causing this error.
I've got a two-part signup form. First part is just selecting a product. That passes a product ID to the next page as part of the URL, where they input personal info. I can get the form to work fine until I start removing fields -- i'm using model forms -- because some fields don't need to be displayed.
Here's my model, and the modelForm:
class SimpleSubscriber(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=200)
city = models.CharField(max_length=100)
state = models.CharField(max_length=2)
zipcode = models.CharField(max_length=9)
phone = models.CharField(max_length=10)
email = models.EmailField()
date_created = models.DateTimeField(null=True)
sub_type = models.ForeignKey(Product)
def __unicode__(self):
return self.name
class SubscriberForm(ModelForm):
class Meta:
model = SimpleSubscriber
fields = ('name', 'address', 'city', 'state', 'zipcode', 'phone', 'email', 'sub_type',)#'date_created',
And here's my views:
def select_product(request):
title = "get yourself an e-edition. wurd."
pform = Product.objects.order_by('product_active')
if request.method == 'POST': # If the form has been submitted...
pform = ProductForm(request.POST) # A form bound to the POST data
if pform.is_valid(): # All validation rules pass
# ...
return HttpResponseRedirect('signup/%i' % pform.id) # Redirect after POST
else:
form = ProductForm() # An unbound form
return render_to_response('signup/index.html', {'title': title, 'pform': pform}, context_instance=RequestContext(request))
def subscriber_signup(request, product_id):
productchoice = Product.objects.get(id=product_id)
now = datetime.datetime.now()
title = "We need some information."
if request.method == 'POST': # If the form has been submitted...
sform = SubscriberForm(request.POST) # A form bound to the POST data
if sform.is_valid(): # All validation rules pass
sform.date_created = now
sform.sub_type = productchoice
sform.save()
return HttpResponseRedirect('thankyou/') # Redirect after POST
else:
sform = SubscriberForm() # An unbound form
return render_to_response('signup/detail.html', {'title': title, 'sform': sform, 'productchoice': productchoice, 'now': now.date(),}, context_instance=RequestContext(request))
I think it has something to do with the modelForm, but I'm pretty new, so I really have no idea. If I add all the fields to SubscriberForm, then they get filled out and everything works fine. But I don't want users to have to say when they filled out the form, so i put sform.date_created = now and I want the product_id to be filled in automatically by what choice they picked on the previous page. but if I exclude these fields from the form it throws the IntegrityError, which isn't very helpful in explaining what to change.
Any hints on where I'm messing up?
Thanks,
Two things:
1) You may benefit from using exlude in your form definition:
class SubscriberForm(ModelForm):
class Meta:
model = SimpleSubscriber
exclude = ('date_created', )
2) To your question, heres how to fix it:
if sform.is_valid(): # All validation rules pass
suscriber = sform.save(commit=False)
suscriber.date_created = now
suscriber.sub_type = productchoice
suscriber.save()
Alternatively to #fceruti's suggestion, you can also add more kwarg tags null=True on the model's field where appropriate - only forcing a minimal set of fields to be completed in the form.