Django Form Wizard: Why is this happening? - django

I have a dinamic form wizard step as following:
class AltaForm6(forms.Form):
CHOICES = ((1, 1,), (2, 2,))
username = ChoiceFieldInvalid(required=True, label="Usuario", widget=forms.RadioSelect, choices=CHOICES)
username2 = forms.CharField(required=False, label="Otro")
#username = ChoiceWithOtherField(required=True, label="Usuario", choices=CHOICES)
def clean_username2(self):
username = self.cleaned_data.get('username')
username2 = self.cleaned_data.get('username2')
if username == "Otro" and len(username2) == 0:
raise forms.ValidationError("Debe especificar un nombre de usuario")
return username2
def clean_username(self):
username = self.cleaned_data.get('username')
return username
Then i dynamically change the choices values:
class AltaWizard(SessionWizardView):
template_name = 'agroshare/wizard.html'
def get_form(self, step=None, data=None, files=None):
form = super(AltaWizard, self).get_form(step, data, files)
if step == '5':
import logging
logger = logging.getLogger(__name__)
cleaned_data = self.get_cleaned_data_for_step('2') or {}
logger.error(cleaned_data)
nombre = cleaned_data.get('nombre')
apellido = cleaned_data.get('apellido')
first = possibleUid(nombre, apellido, '1')
second = possibleUid(nombre, apellido, '2')
if ' ' in nombre:
third = possibleUid(nombre, apellido, '3')
form.fields['username'].choices = ((first, first,), (second, second,), (third, third,), ("Otro", "Otro",))
if ' ' in apellido:
fourth = possibleUid(nombre, apellido, '4')
form.fields['username'].choices = ((first, first,), (second, second,), (fourth, fourth,), ("Otro", "Otro",))
else:
form.fields['username'].choices = ((first, first,), (second, second,), ("Otro", "Otro",))
if step == '5':
form.user = self.request.user
return form
def render(self, form=None, **kwargs):
form = form or self.get_form()
context = self.get_context_data(form=form, **kwargs)
if self.steps.current == '5':
form2 = self.get_form('5')
cleaned_data = self.get_cleaned_data_for_step('5') or {}
username = cleaned_data.get('username')
form2.fields['username'].choices = [username]
return self.render_to_response(context)
The problem is, when i go back to this step trough the wizard, it does not modify the "choices" values, it shows "CHOICES = ((1, 1,), (2, 2,))"
How can i achieve that when i go back to this step, the form can actually show the values i want?

Related

Use saved form instead of cleaned form django

I am not able to display the invoice number in the receipt.html.
invoice number is auto generated in models.py
models.py
from random import randint
class Buyer(models.Model):
name_of_buyer = models.CharField(max_length=200,null=True)
address_of_buyer = models.CharField(max_length=200,null=True)
interested_in = models.ForeignKey(Box,on_delete=models.CASCADE,null=True)
Pickup_dt = models.DateField(null=True)
Pickup_time = models.CharField(max_length=80,null=True)
Invoice_number = models.CharField(max_length=12,blank=True,unique=True)
def save(self, *args, **kwargs):
if self.interested_in == 'Mangos':
x=randint(99,99999)
self.Invoice_number = str('MAN') + str(x)
elif self.service == 'Banana':
x=randint(99,99999)
self.Invoice_number = str('BAN') + str(x)
elif self.service == 'Apple':
x=randint(99,99999)
self.Invoice_number = str('APP') + str(x)
super(imfc_one,self).save()
def __str__(self):
return str(self.Invoice_number)
forms.py
class Sale(forms.ModelForm):
def clean_interested_in(self):
buyer_interested_in_box = self.cleaned_data['interested_in']
if buyer_interested_in_box.mango < 10:
raise forms.ValidationError('Not enough fruits.Please select another box')
class Meta:
model = Buyer
fields = '__all__'
view.py
def ind(request):
form = Sale()
if request.method == 'POST':
form = Sale(request.POST)
if form.is_valid():
form.save(commit=True)
return render(request,'app_one/receipt.html',{'upform':form.cleaned_data})
else:
print("form is not vaalid")
return render(request,'app_one/index1.html',{'form':form})
receipt.html
receipt : {{ upform.Invoice_number }}
How can I have the invoice number in the receipt.html
Thank you.
You don't have to pass form.cleaned_data in view. Just pass your saved object
def ind(request):
form = Sale()
if request.method == 'POST':
form = Sale(request.POST)
if form.is_valid():
buyer = form.save(commit=True)
return render(request,'app_one/receipt.html',{'buyer': buyer})
else:
print("form is not vaalid")
return render(request,'app_one/index1.html',{'form':form})
In receipt.html, just call
receipt : {{ buyer.Invoice_number }}

How can I save an string pk into int pk?

I have a problem with a submit form when I want to save the profile ID the form have an error, i dont understand why because in the console all is ok but the form_valis is false, so think because the ModelChoiseField send a pk in sting format so how can i convert the string pk to int pk ?
My Form
class UsuarioForm(forms.ModelForm):
id_perfil = forms.ModelChoiceField(queryset=Perfil.objects.filter(status='1'), label="Perfil" ,empty_label="Seleciona perfil", widget=forms.Select(attrs={'class':'form-control'}))
My Models
class Usuario(models.Model):
id_usuario = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=255)
id_perfil = models.IntegerField()
status = models.CharField(max_length=50)
class Perfil(models.Model):
id_perfil = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=255)
status = models.CharField(max_length=50)
The save method
def save_usuario_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
usuario = form.save(commit=False)
if usuario.status == '':
usuario.status = '1'
usuario.id_usuario_alt = '1'
elif usuario.status == '1':
usuario.status = '2'
form.save()
data['form_is_valid']= True
usuarios = Usuario.objects.filter(status='1').order_by('id_usuario')[:5]
data['html_usuario_list'] = render_to_string('back/Modulo_usuarios/usuarios_list.html',{
'usuarios':usuarios
})
else:
data['form_is_valid']= False
context = {'form':form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
The error
All fields are fill and post method is OK

Changing Django form property 'required' by bool in template

I'm trying to have the option for an admin to make fields required or not for a user.
My form looks like this.
class StudentDetailForm(MyForm):
first_name = fields.CharField(required=True)
last_name = fields.CharField(required=True)
date_of_birth = MyDateField(required=True, widget=MyDateInput(attrs{'class': 'dobpicker'}))
id_number2 = fields.CharField(required=True, label='PPS Number')
note = fields.CharField(required=False,
widget=forms.Textarea(attrs={'cols': '25', 'rows': '2'}))
class Meta:
model = Person
fields = ['first_name', 'last_name', 'date_of_birth', 'id_number2', 'gender', 'note']
etc...
This is how I tried to changed the required field. It loops through all the fields and presents tick boxes for visible or required on the admin page.
Then each is presented on the form page with a required or not value.
student_form = StudentDetailForm(None, data=request.POST or None)
mother_form = ParentDetailForm(None, data=request.POST or None, prefix='g1', instance=mother)
father_form = ParentDetailForm(None, data=request.POST or None, prefix='g2', instance=father)
family_form = FamilyDetailForm(None, data=request.POST or None)
# student_form, mother_form, father_form, family_form = get_web_intake_forms(school, request.POST or None, requestpps)
for name, value in webfields.items():
if not value['visible']:
# name is actual name plus : plus a number
# split up to name and number
bits = name.split(':')
fname = bits[0]
formnum = bits[1]
if formnum == '1':
del student_form.fields[fname]
elif formnum == '2':
del mother_form.fields[fname]
elif formnum == '3':
del father_form.fields[fname]
elif formnum == '4':
del family_form.fields[fname]
elif value['required']:
# name is actual name plus : plus a number
# split up to name and number
bits = name.split(':')
fname = bits[0]
formnum = bits[1]
if formnum == '1':
student_form.base_fields[fname].required = True
elif formnum == '2':
mother_form.fields[fname].required = True
elif formnum == '3':
father_form.fields[fname].required = True
elif formnum == '4':
family_form.base_fields[fname].required = True
elif not value['required']:
# name is actual name plus : plus a number
# split up to name and number
bits = name.split(':')
fname = bits[0]
formnum = bits[1]
if formnum == '1':
student_form.base_fields[fname].required = False
elif formnum == '2':
mother_form.fields[fname].required = False
elif formnum == '3':
father_form.fields[fname].required = False
elif formnum == '4':
family_form.base_fields[fname].required = False
I tried base_fields which kind of worked but was a bit messy.
Any ideas?
You probably don't want to change base_fields - that updates the fields of the StudentDetailForm class, not just the particular form instance
Depending on the rest of your view, setting form.fields['first_name'].required should work.
However, it's normally better to set self.fields['first_name'].required inside the form's __init__ method. I'm not sure how you would do this because you seem to have multiple forms and many field names, so here's a simpler example.
class MyForm(forms.Form):
first_name = forms.CharField()
def __init__(self, *args, **kwargs):
first_name_required = kwargs.pop('first_name_required')
super(MyForm, self).__init__(*args, **kwargs)
self.fields['first_name'].required = first_name_required
You would then initialise your form like:
form = MyForm(data=request.POST, first_name_required=True)

saving in admin does not work (Mezzanine 3.1.10)

Any help appreciated.
I cannot save parent Program object in admin.py. It only does not work for 1 particular model with inlines, and only with one particular inline. If I take ProgramHotelInline out, I can save the model. If ProgramHotelInline is in inlines for ProgramAdmin, I can't save the model; the terminal output gives: "POST /admin_keywords_submit/ HTTP/1.1" 403 2294
Here is the PageAdmin class:
class ProgramHotelInline(admin.StackedInline):
model = ProgramHotel
extra = 5
def get_formset(self, request, obj=None, **kwargs):
initial = []
formset = super(ProgramHotelInline, self).get_formset(request, obj, **kwargs)
#initial c/i-c/o
if obj:
if request.method == "GET":
for bh in range(0,self.extra):
initial+=[{'check_in':datetime.combine(obj.base_arrival,time(14,00)),
'check_out':datetime.combine(obj.base_departure,time(12,00))}]
self.extra = len(initial)
formset.__init__ = curry(formset.__init__, initial=initial)
return formset
def queryset(self, request):
"""
Prefetch info.
"""
qs = super(ProgramHotelInline, self).queryset(request)
return qs.select_related('hotel__organization','roomtype')
program_extra_fieldsets = ((None, {"fields": ("base_arrival","base_departure","program_type","default_commission","content","no_bed_age","free_child_age","short_description","images")}),)
class ProgramAdmin(PageAdmin):
inlines = (CodeInline,ProgramExcursionInline,ProgramTransferInline, ProgramHotelInline,ProgramCommissionInline,ProgramDiscountInline)
fieldsets = deepcopy(PageAdmin.fieldsets) + program_extra_fieldsets
filter_horizontal = ('images', )
admin.site.register(Program,ProgramAdmin)
here are the models:
class ProgramHotel(models.Model):
program = models.ForeignKey(Program,null=True,blank=True)
hotel = models.ForeignKey('tour.Hotel')
roomtype = ChainedForeignKey(
'tour.RoomType',
chained_field="hotel",
chained_model_field="hotel",
show_all=False,
auto_choose=False,blank=True,null=True,help_text="<span style='color:blue'>null means no bed</span>")#null stands for (child) with no bed!
check_in = models.DateTimeField(default=default_ci_time)
check_out = models.DateTimeField(default=default_co_time)
#max_age = models.IntegerField(default=0)
pax_per_room = models.SmallIntegerField()
exb = models.BooleanField(default=False)
bb = models.BooleanField(default=False)
turn = models.SmallIntegerField(default = 1)#if we have more than one stopping, first stopping - turn=1,2nd - turn=2 etc
USD = '$'
KRW = unichr(8361)
CURRENCY_CHOICES = (
(USD, 'USD'),
(KRW, 'KRW'),
)
currency = models.CharField(default = "$",max_length=1,choices=CURRENCY_CHOICES)
price = models.DecimalField('price per pax, including comm.',decimal_places=0, max_digits=21, default = 0)#in USD
def __unicode__(self):
if self.roomtype:
if self.pax_per_room == 2:
rt= u"\u00BD%s" % (self.roomtype.roomtype)
elif self.pax_per_room == 3:
rt= u"\u2153%s" % (self.roomtype.roomtype)
elif self.pax_per_room == 4:
rt= u"\u00BC%s" % (self.roomtype.roomtype)
elif self.pax_per_room == 5:
rt= u"\u2155%s" % (self.roomtype.roomtype)
elif self.pax_per_room == 1:
rt= u"%s, single occupancy" % (self.roomtype.roomtype)
elif self.pax_per_room > 5:
rt= u"1/%s %s" % (self.pax_per_room,self.roomtype.roomtype)
else:
rt= u"%s" % (self.roomtype.roomtype)
else:
rt="no bed"
bb = u", breakfast" if self.bb else u", NO BREAKFAST"
exb = u", +extra bed" if self.exb else u""
return u"%s: %s, %s ~ %s%s%s; %s%s" % (self.hotel.organization,rt,self.check_in.strftime("%d %B %Y"), self.check_out.strftime("%d %B %Y"),bb,exb,self.price,self.currency)
class Meta:
unique_together = (("program", "turn","hotel","roomtype","check_in","pax_per_room","exb","bb"),)
class Program(Page,RichText):
def default_commission_default():
l = list(DynamicParameter.within_dates.within_dates(datetime.today()))[:1]
dynamic = l[0]
return dynamic.default_agent_commission
def no_bed_age_default():
l = list(DynamicParameter.within_dates.within_dates(datetime.today()))[:1]
dynamic = l[0]
return dynamic.default_no_bed_age
def free_child_age_default():
l = list(DynamicParameter.within_dates.within_dates(datetime.today()))[:1]
dynamic = l[0]
return dynamic.default_free_child_age
program_type = models.ManyToManyField(ProgramType)
images = models.ManyToManyField(PicasaGallery,null=True, blank=True)
short_description = RichTextField(max_length=250,default = "")
#excursions, transfers, hotels - just a template; actuals are in Code
hotels = models.ManyToManyField('tour.Hotel', through='ProgramHotel')
transfers = models.ManyToManyField('misc.Transfer', through='ProgramTransfer')
excursions = models.ManyToManyField("tour.Excursion", through='ProgramExcursion')
commission = models.ManyToManyField(Customer, through='ProgramCommission')
default_commission = models.DecimalField('agent commission',decimal_places=3, max_digits=4, default = default_commission_default)
base_arrival = models.DateField()
base_departure = models.DateField()
no_bed_age = models.SmallIntegerField(default=no_bed_age_default) #UP TO THIS AGE ALLOWED TO HAVE NO BED
free_child_age = models.SmallIntegerField(default=free_child_age_default) #NO BED+BREAKFAST FREE, IF ADULTS HAVE BREAKFAST; no tickets!
discount = models.ManyToManyField(Discount, through='ProgramDiscount')
def save(self, *args, **kwargs):
''' On save, make invisible in left and foot menu
SET COMMISSION, IF DEFINED
add bonus for a company, if any
'''
self.in_menus = '1'
super(Program, self).save(*args, **kwargs)
if self.default_commission:
for customer in Customer.objects.filter(customer_type="AGENT"):
try:
pc = ProgramCommission.objects.get(program=self,customer=customer)
except ObjectDoesNotExist:
pc = ProgramCommission(program=self,customer=customer, commission=self.default_commission)
#print pc
if not pc.id:
if pc.customer.organization=="Private Customer":
pc.commission = 0.00
try:
customer_comm = CustomerCommission.within_dates.within_dates(self.base_arrival).get(customer=customer).bonus_commission
if customer_comm >0:
pc.commission = pc.commission + customer_comm
except ObjectDoesNotExist:
pass
pc.save()
def __unicode__(self):
return u"%s" % (self.title)
def groupcode(self):
"""
return filtered set - only code.group=True
"""
return self.code_set.filter(group=True,arr_date__gte=datetime.today())
def distincthotel(self):
"""
return filtered set - only distinct hotels
"""
return self.programhotel_set.distinct('hotel')
def get_admin_url(self):
return urlresolvers.reverse("admin:%s_%s_change" %
(self._meta.app_label, self._meta.module_name), args=(self.id,))
class Meta:
ordering = ['title']
Found the source of mistake: that was outdated django-smart-selects. After update it works again.

Django form edit problem at intiliazation

I have a trouble with pre-population of the forms in Django. Because debuggin tool in Aptana doesn't work well, I couldn't detect the error.
I think when I try form = MemberSettings(default_data) form tries to validate the data and it gives errors for invalid fields even in first load.
Could you help me to find out the problem ?
Thanks
forms.py
class MemberSettings(forms.Form):
email = forms.EmailField(label=_("member_Email"),required = True)
currentPassword = forms.CharField(label=_("member_currentPassword"),widget=forms.PasswordInput,required=False)
newPassword = forms.CharField(label=_("member_newPassword"),widget=forms.PasswordInput,required=False)
newPasswordRe = forms.CharField(label=_("member_newPasswordRe"),widget=forms.PasswordInput,required=False)
emailPreference = forms.ChoiceField(label=_("member_email_preference"), widget=forms.RadioSelect(renderer=HorizRadioRenderer),choices = UserMailPreference.USER_MAIL_PREF,required = True)
gender = forms.ChoiceField(label=_("member_gender"), widget=forms.RadioSelect(renderer=HorizRadioRenderer),choices = UserGender.USER_GENDER ,required = False)
birthYear = forms.ChoiceField(label=_("member_birthyear"),required = False)
education = forms.ChoiceField(label=_("member_education"),choices = UserEducation.USER_EDU, required = False)
def __init__(self,*args, **kwargs):
super(MemberSettings,self).__init__(*args, **kwargs)
now = datetime.datetime.now()
birthYearList = []
for i in reversed(range (now.year-80,now.year-13)):
birthYearList.append((i,str(i)))
self.fields["birthYear"].choices = birthYearList
def clean_currentPassword(self):
field_data = self.cleaned_data['currentPassword']
if len(field_data) <= 0:
return field_data
if len(field_data.split(' ')) != 1:
raise forms.ValidationError(_('member_err_password_empty_char'))
if len(field_data) > 32:
raise forms.ValidationError(_('member_err_password_maxChar'))
if len(field_data) < 5:
raise forms.ValidationError(_('member_err_password_minChar'))
return field_data
def clean_newPassword(self):
field_data = self.cleaned_data['newPassword']
if len(field_data) <= 0:
return field_data
if len(field_data.split(' ')) != 1:
raise forms.ValidationError(_('member_err_password_empty_char'))
if len(field_data) > 32:
raise forms.ValidationError(_('member_err_password_maxChar'))
if len(field_data) < 5:
raise forms.ValidationError(_('member_err_password_minChar'))
return field_data
views.py
#login_required
def settings_edit(request):
u = request.user
if request.method == 'POST':
form = MemberSettings(request.POST)
if form.is_valid():
return redirect('/member/settings_edit/')
else:
return render_response(request, 'member/settings_edit.html', {'form': form})
else:
default_data = {
'email': u.email,
'gender': u.get_profile().gender,
'education': u.get_profile().education,
'birthYear': u.get_profile().birthyear,
'emailPreference': u.get_profile().mail_preference,
}
form = MemberSettings(default_data)
return render_response(request, 'user/settings_edit.html', {'form': form})
You need to use the initial argument when constructing your form instance in the view:
form = MemberSettings(initial=default_data)
See https://docs.djangoproject.com/en/1.3/ref/forms/api/ for more information. Hope that helps you out.