#python #django #django-formwizard #django-formtools
Вопрос:
У меня есть образцовый клиент:
class Customer(models.Model):
name = models.CharField(
verbose_name='Company name',
max_length=100,
unique=True
)
street = models.CharField(
verbose_name='Street',
null=True,
max_length=150
)
house_number = models.IntegerField(
verbose_name='Number',
null=True
)
zipcode = models.CharField(
verbose_name='Zipcode',
max_length=6
)
city = models.CharField(
verbose_name='City',
max_length=100
)
phone = models.CharField(
verbose_name='Phone',
max_length=100
)
mobile_phone = models.CharField(
verbose_name='Mobile',
max_length=100
)
fax = models.CharField(
verbose_name='Fax',
max_length=100,
null=True,
blank=True
)
email = models.EmailField(
verbose_name='E-mail'
)
website = models.CharField(
verbose_name='Website',
max_length=100,
null=True,
blank=True
)
kvk = models.CharField(
verbose_name='KvK-number',
max_length=20,
help_text='s.v.p. uittreksel toevoegen, niet ouder dan 6 maanden'
)
kvk_file = models.FileField(
verbose_name='Excerpt',
max_length=2000,
upload_to=kvk_directory_path,
null=True,
)
activities = models.TextField(
verbose_name='Main acitivities',
null=True,
blank=True
)
total_employees = models.IntegerField(
verbose_name='Total employees',
null=True,
blank=True
)
yearly_transactions = models.IntegerField(
verbose_name='Estimated yearly transactions',
null=True,
blank=True
)
order_confirmation = models.BooleanField(
verbose_name='Order confirmation by e-mail?',
default=False
)
confirmation_email = models.EmailField(
verbose_name='E-mail for order confirmation',
null=True
)
delivery_address = models.CharField(
verbose_name='Delivery address',
max_length=100
)
delivery_zip = models.CharField(
verbose_name='Zipcode',
max_length=6
)
delivery_city = models.CharField(
verbose_name='City',
max_length=100
)
delivery_instructions = models.TextField(
verbose_name='Instructions',
null=True
)
mail_address = models.CharField(
verbose_name='PO Address',
max_length=100,
null=True,
blank=True
)
mail_zip = models.CharField(
verbose_name='PO Zipcode',
max_length=6,
null=True,
blank=True
)
mail_city = models.CharField(
verbose_name='PO City',
max_length=100,
null=True,
blank=True
)
iban = models.CharField(
verbose_name='IBAN-number',
max_length=36
)
btw = models.CharField(
verbose_name='BTW-number',
max_length=50
)
cash_pin = models.BooleanField(
verbose_name='Cash/Pin',
help_text='(pickup-only)',
default=False
)
invoice_mail = models.BooleanField(
verbose_name='Invoice per mail?',
default=False
)
invoice_street = models.CharField(
verbose_name='Street',
max_length=100,
null=True
)
invoice_house_number = models.IntegerField(
verbose_name='Number',
null=True
)
invoice_zip = models.CharField(
verbose_name='Zipcode',
max_length=100,
null=True
)
invoice_city = models.CharField(
verbose_name='City',
max_length=100,
null=True
)
invoice_email = models.BooleanField(
verbose_name='Invoice per e-mail?',
default=False
)
invoice_emailaddress = models.EmailField(
verbose_name='E-mail',
null=True
)
debit = models.BooleanField(
verbose_name='Debit',
default=False
)
comment = models.TextField(
verbose_name='Comments'
)
toa = models.BooleanField(
verbose_name='I agree with the terms',
default=True
)
def __str__(self):
return self.name
этого довольно много, чтобы втиснуть в одну форму, поэтому я разделил ее на разные формы:
class CompanyForm(ModelForm):
name = forms.CharField(
label=_("Company name"),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
street = forms.CharField(
label=_('Street'),
max_length=150,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
house_number = forms.CharField(
label=_('House number'),
max_length=10,
widget=forms.TextInput(attrs={'class': 'form-control right', 'placeholder': 'placeholder'})
)
zipcode = forms.CharField(
label=_('Zipcode'),
max_length=6,
widget=forms.TextInput(attrs={'class': 'form-control left', 'placeholder': 'placeholder'})
)
city = forms.CharField(
label=_('City'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
phone = forms.CharField(
label=_('Phone'),
max_length=15,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Vast nmmr', 'type': 'tel'})
)
mobile_phone = forms.CharField(
label=_('Mobiel'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Mobiel nmmr', 'data-placeholder': 'mobiel nmmr', 'type': 'tel'})
)
fax = forms.CharField(
label=_('Fax'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'}),
required=False
)
email = forms.EmailField(
label=_('E-mail'),
widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'onfocusout': 'validatemail(this.attributes["name"].value,this.id, "email")'})
)
website = forms.CharField(
label=_('Website'),
max_length=100,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
kvk = forms.CharField(
label=_('KvK number'),
max_length=12,
help_text=_('please add excerpt, not older than 6 months'),
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
activities = forms.CharField(
label=_('Main activities'),
widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'rows': 2}),
required=False
)
total_employees = forms.IntegerField(
label=_('Total employees'),
required=False,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'min': '0'})
)
yearly_transactions = forms.IntegerField(
label=_('Estimated yearly transactions'),
required=False,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'min': '0'})
)
class Meta:
model = Customer
fields = [
'name',
'street',
'house_number',
'zipcode',
'city',
'phone',
'mobile_phone',
'fax',
'email',
'website',
'kvk',
'activities',
'total_employees',
'yearly_transactions',
]
class AddressesForm(ModelForm):
# Delivery Fields ----
delivery_street = forms.CharField(
label=_('Street'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
delivery_number = forms.CharField(
label=_('House number'),
max_length=10,
widget=forms.TextInput(attrs={'class': 'form-control right', 'placeholder': 'placeholder'})
)
delivery_zip = forms.CharField(
label=_('Zipcode'),
max_length=6,
widget=forms.TextInput(attrs={'class': 'form-control left', 'placeholder': 'placeholder'})
)
delivery_city = forms.CharField(
label=_('City'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
delivery_instructions = forms.CharField(
label=_('Delivery instructions'),
required=False,
widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder':
'placeholder', 'rows': 2})
)
# ---- Delivery Fields
# Invoice Fields ----
different_invoice_address = forms.BooleanField(
label=_('Different invoice address'),
required=False,
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
invoice_mail = forms.ChoiceField(
label=_('Invoice per mail?'),
choices=INVOICE_PER_MAIL,
required=False,
widget=forms.RadioSelect(attrs={'class': 'form-check-input'}),
)
invoice_street = forms.CharField(
label=_('Street'),
max_length=100,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
invoice_house_number = forms.CharField(
label=_('House number'),
max_length=100,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control right', 'placeholder': 'placeholder'})
)
invoice_zip = forms.CharField(
label=_('Zipcode'),
max_length=100,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control left', 'placeholder': 'placeholder'})
)
invoice_city = forms.CharField(
label=_('City'),
max_length=100,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
invoice_email = forms.BooleanField(
label=_('Invoice per e-mail?'),
required=False,
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
invoice_emailaddress = forms.EmailField(
label=_('E-mailaddress for invoices'),
required=False,
widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
# ---- Invoice Fields
# Mail Fields ----
mail_address = forms.CharField(
label=_('PO number'),
max_length=5,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'}),
required=False
)
using_mail_address = forms.BooleanField(
label=_('Use PO?'),
required=False,
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
mail_zip = forms.CharField(
label=_('Zipcode'),
max_length=6,
widget=forms.TextInput(attrs={'class': 'form-control left', 'placeholder': 'placeholder'}),
required=False
)
mail_city = forms.CharField(
label=_('City'),
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control right', 'placeholder': 'placeholder'}),
required=False
)
# ---- Mail Fields
class Meta:
db_table = 'customers_customer'
model = Customer
fields = [
'delivery_street',
'delivery_number',
'delivery_zip',
'delivery_city',
'delivery_instructions',
'different_invoice_address',
'invoice_mail',
'invoice_street',
'invoice_house_number',
'invoice_zip',
'invoice_city',
'invoice_email',
'invoice_emailaddress',
'using_mail_address',
'mail_address',
'mail_zip',
'mail_city',
]
class PaymentForm(ModelForm):
# PAYMENT SPECIFICS
iban = forms.CharField(
label=_('IBAN number'),
max_length=36,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'onfocusout': 'alertValidIBAN(this.value)'})
)
btw = forms.CharField(
label=_('Tax number'),
max_length=50,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
cash_pin = forms.BooleanField(
label=_('Cash/Card'),
help_text=_('(pick-up only)'),
required=False,
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
debit = forms.BooleanField(
label=_('Automatic collection, permission to cancel'),
help_text=_('(invoice sum will be debited within 14 days)'),
required=False,
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
# --- PAYMENT SPECIFICS
# MISC ---
order_confirmation = forms.ChoiceField(
label=_('Order confirmation per mail?'),
choices=ORDER_CONFIRMATION,
required=False,
widget=forms.RadioSelect(attrs={'class': 'form-check-input'}),
)
confirmation_email = forms.EmailField(
label=_('E-mail'),
required=False,
widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'placeholder', 'onfocusout': 'validatemail(this.attributes["name"].value,this.id, "confemail")'})
)
comment = forms.CharField(
label=_('Comments and complements'),
required=False,
widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'placeholder'})
)
toa = forms.BooleanField(
label=_('I am authorized to sign and agree to the delivery-, payment-, and rental terms of Wijngo Holland b.v.v and hereby declare that the forms is filled correctly'),
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'placeholder': 'placeholder'})
)
# --- MISC
class Meta:
db_table = 'customers_customer'
model = Customer
fields = [
'debit',
'iban',
'btw',
'cash_pin',
'order_confirmation',
'confirmation_email',
'comment',
'toa',
]
теперь я застрял на построении метода «готово». В документации не совсем ясно, как это сделать, когда вы используете несколько форм для одной модели.
I could do customer = form_list[0].save(commit=False)
and then go by all the rest of the fields one by one:
customer.delivery_street = form_list[1].cleaned_data['delivery_street']
customer.delivery_number = form_list[1].cleaned_data['delivery_number']
but thats alooooot and feels too tedious than necessary.
How do I got about doing this?
views.py:
FORMS = [
("company", CompanyForm),
("addresses", AddressesForm),
("references", ReferenceFormSet),
("contacts", ContactFormSet),
("payment", PaymentForm),
# ("upload", DocumentForm),
]
TEMPLATES = {
"company": "form/step-1.html",
"addresses": "form/step-2.html",
"references": "form/step-3.html",
"contacts": "form/step-4.html",
"payment": "form/step-5.html",
# "upload": "form/step-6.html",
}
class RegisterWizard(SessionWizardView):
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def render_goto_step(self, *args, **kwargs):
form = self.get_form(data=self.request.POST)
# form = self.get_form(data=self.request.POST, request.FILES)
self.storage.set_step_data(self.steps.current, self.process_step(form))
# self.storage.set_step_files(self.steps.current, self.process_step_files(form))
return super().render_goto_step(*args, **kwargs)
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'bestanden'))
def get_context_data(self, form, **kwargs):
context = super().get_context_data(form=form, **kwargs)
context.update({'callme_forms': CallMeForms(prefix='callme')})
# context.update({'document_forms': DocumentForm(prefix='document')})
return context
def done(self, form_list, **kwargs):
customer = form_list[0].save(commit=False)
if form_list[1].cleaned_data['different_invoice_address'] is False:
# fill invoice_data with delivery_data
return render(
self.request, 'thank-you.html', {
'form_data': [form.cleaned_data for form in form_list],
}
)
urls.py:
from django.contrib import admin
from django.urls import path
from . import views
from .views import FORMS
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.RegisterWizard.as_view(FORMS), name='index'),
path('thank-you/', views.thank_you, name='thank_you'),
path('privacy-verklaring/', views.privacy_policy, name='privacy_policy'),
path('algemene-voorwaarden/', views.toa, name='toa'),
path('save_callme/', views.save_callme, name='save_callme')
]