title: (How) does Django prevent data injection by manipulating forms?
body: <p>I'm using Django's built-in User model in one of my projects. Users should be editable, of course. Since it's the most convenient solution I started providing the form for User edits by using Django's own UserChangeForm. UserChangeForm is basically a ModelForm of the UserModel, so it makes it possible to change all the fields of the User model.</p>
  
  <p>I don't want users to be able to change every field. So, my first idea was to pass the whole UserChangeForm into the template but render only the fields that I need (say 'username' and 'email'). I also want only superusers to be able to change a username, so this field is only rendered if you are a superuser.</p>
  
  <p>The essential code looks like that:</p>
  
  <p><strong>view function</strong></p>
  
  <pre><code>def edit_user(request, pk):
      ...    #code to ensure not everyone can edit every user
      user = User.objects.get(pk=pk)
      if request.method == 'POST':
          form = UserChangeForm(request.POST, instance=user)
          if form.is_valid:
              form.save()
             ...    #redirect
      else:
          form = UserChangeForm(instance=user)
      ...    # render template
  </code></pre>
  
  <p><strong>form in the template</strong></p>
  
  <pre><code>&lt;form action="{{ request.path }}" method="post"&gt;
      {% csrf_token %}
      {% if user.is_superuser %}
          {{ form.username }}
      {% endif %}
      {{ form.email }}
      &lt;button type="submit"&gt;Save&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>Now, my question is: How about the security aspects of this solution? I do nothing to prevent an attacker to add the e.g. the username field even if he is no superuser. By that, he would populate the POST data with additional data, which is then send to the view function and used to update the User object. That could get really dangerous, since the original UserChangeForm also contains a field 'is_superuser'.</p>
  
  <p>I tried the hack the form myself to test my suspicion. I logged in as a normal user, added the username input via the Developer Tools and submitted the form. The result was an exception:</p>
  
  <pre><code>Traceback:
  File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
    111.                         response = callback(request, *callback_args, **callback_kwargs)
  File "/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
    20.                 return view_func(request, *args, **kwargs)
  File "/Users/joker/Development/wiki2099/wiki2099/apps/accounts/views.py" in edit_user
    69.             form.save()
  File "/Library/Python/2.7/site-packages/django/forms/models.py" in save
    364.                              fail_message, commit, construct=False)
  File "/Library/Python/2.7/site-packages/django/forms/models.py" in save_instance
    74.                          " validate." % (opts.object_name, fail_message))
  
  Exception Type: ValueError at /accounts/edit/12/
  Exception Value: The User could not be changed because the data didn't validate.
  </code></pre>
  
  <p>I'm not sure if that means that this kind of attack is not possible or that I just didn't do it right. I think, the CSRF token could prevent such kind of hacks, but I found nothing about that matter in the docs. Could anyone enlighten me? Is there any mechanism to prevent attackers from using not-rendered form fields and how does it work?</p>
  
  <p>Thanks in advance!</p>