Reputation: 3499
I offer discount codes in my checkout. I created form where users can type in the discount code and click on apply. The form checks if the discount code is valid and then applies it.
Now I want to add the functionality to add to the url domain.com/event/?discount=ABC
I want to check if request.GET
is set an then somehow redirect it to the 'form' / transform it into a request.POST
, so I can validate it. I am currently struggling to find the right approach to do that. Do you have any suggestions on how I could use the GET-parameter
and validate it the same way as I would use the form?
views.py
def dispatch(self, request, *args, **kwargs):
# Provide discount_code to all functions
self.discount_code = None
# Check if discount code is saved as a session
self.discount_code_session = request.session.get(
request.event.discount_code_cookie(), None)
if self.discount_code_session:
self.discount_code = Discount.objects.filter(
code=self.discount_code_session,
event=self.request.event.pk
).first()
@transaction.atomic
def post(self, request, *args, **kwargs):
# Discount Code
if self.discount_form.is_valid():
discount_code = self.discount_form.cleaned_data['code']
request.session[request.event.discount_code_cookie()] = discount_code
return redirect('events:detail', request.organizer.slug, request.event.slug)
forms.py
class DiscountFormEventPage(forms.ModelForm):
# Remove required attribute from HTML elements
use_required_attribute = False
class Meta:
model = Discount
fields = (
'code',
)
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
for visible_field in self.visible_fields():
visible_field.field.widget.attrs['class'] = 'form-control'
def clean_code(self):
input_code = self.cleaned_data['code']
# Check if discount code exists
discount_code = self.event.discounts.filter(code=input_code).first()
if not discount_code:
raise forms.ValidationError(_("The discount code couldn't be found."),
code='code_exists')
elif not discount_code.is_active():
raise forms.ValidationError(_("This discount code is not available\
anymore."),
code='code_not_active')
return input_code
UPDATE:
I now added this here in my view.py (DetailView):
def get(self, request, *args, **kwargs):
discount_code_get = request.GET.get('code')
if discount_code_get:
return DiscountFormEventPage(
prefix='discount',
data=request.GET,
event=self.request.event,
)
Upvotes: 1
Views: 4588
Reputation: 3499
I could solve it now with this code. Thank you to Bruno for helping me to find the right track:
def get(self, request, *args, **kwargs):
# Apply discount via GET parameter ?code=DISCOUNT
discount_code_get = request.GET.get('code')
if discount_code_get:
self.discount_form = DiscountFormEventPage(
data=request.GET,
event=self.request.event,
)
if self.discount_form.is_valid():
discount_code = self.discount_form.cleaned_data['code']
request.session[request.event.discount_code_cookie()] = discount_code
return redirect('events:detail', request.organizer.slug, request.event.slug)
return super().get(request, *args, **kwargs)
Upvotes: 0
Reputation: 1875
I don't see where you're getting the parameter, is it what your question is about? You can get it as follow:
# request.GET is a dict-like object
code = request.GET['discount']
# safer alternative against KeyError
code = request.GET.get('discount')
# if discount may be specified multiple times
code = request.GET.getlist('discount')
If you want to use a form to validate the incoming data, you should be able to pass it as first argument:
form = DiscountFormEventPage(request.GET)
if form.is_valid():
data = form.cleaned_data
return redirect('events:detail', request.organizer.slug, request.event.slug)
Upvotes: 4