1

I want to pass a query string e.g., ?refcode='A1234' to a hidden field called inbound_referral_code in a ModelForm.

My model is as follows:

class User(models.Model):
   email = models.EmailField(max_length=255, blank=False, unique=True)
   inbound_referral_code = models.CharField(max_length=255)

My ModelForm is currently as follows:

class UserForm(forms.ModelForm):
   model = User
   fields = ['email', 'inbound_referral_code']
   widgets = {'inbound_referral_code': forms.HiddenInput()}

My View is:

def register(request):
   if request.method == 'POST':
      form = UserForm(request.POST)
      [...]
   else:
      form = UserForm()
      return render(request, 'register.html', {'form': form})

And my template is currently:

<form action="{% url 'register' %}" method="post">
   {% csrf_token %}
   {{ form.as_p }}
   <input type="submit" value="Submit"/>
</form>

Two questions:

  • How do I assign ?refcode parameter to inbound_referral_code field?
  • What happens if ?refcode isn't provided?
2
  • Is your problem that you don't know how to set the inbound_referral_code when rendering, or that you don't know how to read it after the post? Commented Oct 6, 2017 at 16:28
  • Actually I don't understand either of those! I will update question... Commented Oct 6, 2017 at 16:35

2 Answers 2

2

Combining the different answers, the following solution worked:

Set the "initial" value of the form parameter, and ensure the template renders with the bound form if validation fails. The correct view function is:

def register(request):
   if request.method == 'POST':
      form = UserForm(request.POST)
      if form.is_valid():
         return redirect([...])
   else:
      refcode = request.GET.get('refcode')
      form = UserForm(intial={'inbound_referral_code': refcode)

   return render(request, 'register.html', {'form': form})

Note that the bottom return render(...) needed to be moved so that it is also called with the form from the POST request if it contains validation errors...

Sign up to request clarification or add additional context in comments.

Comments

1

To assign the refcode, you need to pass it into the form, so you pass in something other than request.POST that contains it, change it before

dict = request.POST.copy()
dict["inbound_referral_code"] = request.POST.get("refcode")
form = UserForm(dict)
# ...

or after validating:

if form.is_valid():
    form.cleaned_data["inbound_referral_code"] = request.POST.get("refcode")

If it isn't provided, you can check for that and pass a custom value, or set a default when defining the form/model.


To set it in the template, you can pass an initial value

else:
  form = UserForm(initial={"inbound_referral_code": "ref-value-here"})
  return render(request, 'register.html', {'form': form})

3 Comments

Ok - I am currently doing that, however I have modified the first block of code to work on GET (not POST). However, by doing this, the template is already throwing up a "this field is required" error on the email field immediately...
If you want the email to be optional, you can define it in your form and pass required=False
No the issue isn't the email being optional - it is definitely required. The issue is I need to pass refcode to the form on a GET request... Given the current implementation it results in validation errors being thrown before the user has even tried to enter any data...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.