django-shop
django-shop copied to clipboard
Customizing CustomerForm
Hi,
My Customer model has additional fields. And because of that the CustomerForm on checkout stage shows those fields. How can i hide them?
You are using the CustomerForm
via Cascade, right?
Then you have to create you own version of a CustomerForm
and register your own implementation of CustomerFormPlugin
. There you can refer to your form implementation.
It probably would be easier to allow a specific setting for this. If you want, I can make this overridable via a settings variable, which defaults to the current form.
You are using the CustomerForm via Cascade, right?
Correct.
Then you have to create you own version of a CustomerForm and register your own implementation of CustomerFormPlugin. There you can refer to your form implementation.
I also thought about this approach. But problem is that CheckoutSerializer also uses CustomerForm.
It probably would be easier to allow a specific setting for this. If you want, I can make this overridable via a settings variable, which defaults to the current form.
Yes, please, that will make thing much easier.
Please retry with HEAD from branch releases/0.12.x
.
There I added a new configuration directive named SHOP_CASCADE_FORMS
. You may override with your own form classes.
I'm curios if it works for you. Then I'll add some documentation on it.
Hi, unfortunately it doesn't work for some reason. I don't get any error, but also do not see any field.
I basically copied CustomerForm from checkout.py, renamed it and replaced path in settings.
@dismine, If it can help you, I just try with this, I see the fields it takes.
in myshop/settings.py:
...
SHOP_CASCADE_FORMS= {
'CustomerForm': 'myshop.forms.checkout.CustomerForm',
'GuestForm': 'shop.forms.checkout.GuestForm',
'ShippingAddressForm': 'shop.forms.checkout.ShippingAddressForm',
'BillingAddressForm': 'shop.forms.checkout.BillingAddressForm',
'PaymentMethodForm': 'shop.forms.checkout.PaymentMethodForm',
'ShippingMethodForm': 'shop.forms.checkout.ShippingMethodForm',
'ExtraAnnotationForm': 'shop.forms.checkout.ExtraAnnotationForm',
'AcceptConditionForm': 'shop.forms.checkout.AcceptConditionForm',
}
...
myshop/forms/checkout.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from djng.forms import fields
from shop.models.customer import CustomerModel
from shop.forms.base import DialogModelForm
class CustomerForm(DialogModelForm):
scope_prefix = 'customer'
legend = _("Customer's Details")
email = fields.EmailField(label=_("Email address"))
first_name = fields.CharField(label=_("First Name"))
last_name = fields.CharField(label=_("Last Name"))
class Meta:
model = CustomerModel
exclude = ['user', 'recognized', 'number', 'last_access']
custom_fields = ['email', 'first_name', 'last_name']
def __init__(self, initial=None, instance=None, *args, **kwargs):
initial = dict(initial) if initial else {}
assert instance is not None
initial.update(dict((f, getattr(instance, f)) for f in self.Meta.custom_fields))
super(CustomerForm, self).__init__(initial=initial, instance=instance, *args, **kwargs)
def save(self, commit=True):
for f in self.Meta.custom_fields:
setattr(self.instance, f, self.cleaned_data[f])
return super(CustomerForm, self).save(commit)
@classmethod
def form_factory(cls, request, data, cart):
customer_form = cls(data=data, instance=request.customer)
if customer_form.is_valid():
customer_form.instance.recognize_as_registered(request, commit=False)
customer_form.save()
return customer_form
if it can help you, I just try with this, I see the fields it takes.
Thank you. Yes, i also see fields when my custom form class has name CustomerForm. But why arbitrary name doesn't work? With current approach i cannot use class CustomerForm as a parent.
Like this it seems to work:
myshop/forms/checkout.py
# -*- coding: utf-8 -*-
from shop.models.customer import CustomerModel
from shop.forms.checkout import CustomerForm
class CustomerForm( CustomerForm):
class Meta:
model = CustomerModel
exclude = ['user', 'recognized', 'number', 'last_access']
custom_fields = ['email', 'first_name', 'last_name']
Arbitrary name doesn't work because she's coded in hard here, maybe: https://github.com/awesto/django-shop/commit/741146d3d9870dfc7a6bb4642561cbd3531d8634#diff-92de288a3bb676dd22abc143bc151271R31
It seems i have found the place that causes the issue:
First of all
class DialogFormPluginBase(ShopPluginBase):
...
def render(self, context, instance, placeholder):
"""
Return the context to render a DialogFormPlugin
"""
request = context['request']
form_data = self.get_form_data(context, instance, placeholder)
request._plugin_order = getattr(request, '_plugin_order', 0) + 1
if not isinstance(form_data.get('initial'), dict):
form_data['initial'] = {}
form_data['initial'].update(plugin_id=instance.pk, plugin_order=request._plugin_order)
bound_form = self.get_form_class(instance)(**form_data)
context[bound_form.form_name] = bound_form
context['headline_legend'] = bool(instance.glossary.get('headline_legend', True))
return self.super(DialogFormPluginBase, self).render(context, instance, placeholder)
String context[bound_form.form_name] = bound_form
relies on class name. When i change it, i also change variable name in context. Which way to resolve this situation i don't know. For now i just override form_name
in my custom form.
Hi
I think this is the right thread:
I would like to extend the RegisterUserForm
adding some fields to it, as we would like the customer to put in all her/his information beforehand and then continue in the shop.
I already extended the form RegisterUserForm
, adding my fields to it, making it my CustomRegisterUserForm
. Then I override the urls of django-SHOP in my urls.py
.
But as soon as I call the register-user
url, I do not see my additional fields.
When debugging using <pre> {% filter force_escape %} {% debug %} {% endfilter %} </pre>
in my template, I can see that the form is not my custom form but RegisterUserForm:
'register_user_form': <RegisterUserForm bound=False, valid=False, fields=(email;password1;password2;preset_password)>
I found in shop.cascade.auth
the plugin uses AUTH_FORM_TYPES
which sets the form back to RegisterUserForm
.
It would be a nice feature, if this also will be made customizable, so I do not have to extend all the code :-)
I just successfully overwritten and registered my CustomerForm. Is there any way to also rewrite the static summary? I would like to influence the rendering of this element too, because of the ordering of my fields do not make sense in visual representation (first I have salutation, then email, then name and lastname). Thanks in advance
There are many static summaries, which one are you referring?
Hi I am trying to overwrite the summary of "CustomerForm".
Markus Mohanty MSc. Tel.: 06763239108
Jacob Rief [email protected] schrieb am Mo., 15. Okt. 2018, 13:54:
There are many static summaries, which one are you referring?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/awesto/django-shop/issues/735#issuecomment-429822629, or mute the thread https://github.com/notifications/unsubscribe-auth/ABHi7LhklHdNzD_Cd2SaOpjNJqkyQz6Sks5ulHdlgaJpZM4UgwQL .
How about reordering the fields in the CustomerForm
? Create your own customer form class inheriting from CustomerForm
, use field_order to order them and configure this class using the settings directive SHOP_CASCADE_FORMS['CustomerForm']
.
The reason I didn't implement a template renderer is, that it would be against the DRY principle, ie. the merchant would have to adopt the customer model, as well as this template. If the above doesn't work, I might rethink about a template approach.
I now used field_order
and it works fine for the form dialog of CustomerForm
, but for static summary it still does not change order of fields.
I just retested with this setup:
Upgrade to HEAD on branch master
Add to the merchant project:
myshop/forms.py:
from shop.forms.checkout import CustomerForm as CustomerFormBase
class CustomerForm(CustomerFormBase):
field_order = ['email', 'last_name', 'first_name', 'salutation']
Add to the merchant settings.py
SHOP_CASCADE_FORMS = {
'CustomerForm': 'myshop.forms.CustomerForm',
}
Does this implementation then also change the field_order
of the static summary
?
I just made a test with the above, not very realistic example. This is what is rendered inside the customer's summary:
[email protected]
De Master
Adam
Mr.
Note, when rendering the address on the client's envelope, you can use an existing, but overridable template, named shop/templates/shop/address.txt
. For static summaries this has not been implemented. If there is a valid use-case for this, I might rethink about that.
In my case, my client has requested that Customer
is extended so that it represents a company (including VAT-Number, phonenumber and company name).
So in the summary it looks quite strange to have it look like this:
Company AG
ATU36196308
+4311234345
Mr.
[email protected]
Firstname
Lastname
It looks like the ordering of the fields of my CustomerModel
and then the additional fields of CustomerBase
. A more logical ordering would be:
Company AG
ATU36196308
+4311234345
[email protected]
Mr.
Firstname
Lastname
And that's what I would like to achieve.
I see. That means, that you would like to have the possibility to use a text template in order to render the CustomerForm as summary. Yes, I can implement that, although it means that you implementation gets a little bit less DRY.
I would appreciate it. I could not think of any solution, without rewriting the whole form.
Can i use this feature if i will install package from PyPi?
Did you find time, to think of a solution for formatting static summary of forms?
Yes, this has been implemented now.
However it's in a draft-branch which is still under development. Unfortunately not everything in that branch drafts/bootstrap-4-sendcloud
is stable and documented yet, hence I didn't release it officially yet.
You can either switch to that branch – I can help you on that – or try to back-port that feature into the current stable one.
thanks for the info. I will look into it, as soon as I can.