title: How to set the initial value for relationship fields in Django's admin?
body: <h2>Summary</h2>
  
  <p>We would like to set the initial selection of the select-boxes representing different kinds of model relationships on a basic "add" or "change" page in the Django admin.
  The initial selection should be saved to the database, if the user clicks one of the "Save" buttons.</p>
  
  <p>We specifically want to do this by setting the <code>initial</code> value on the form fields (for <code>ModelAdmin</code> or <code>TabularInline</code>).</p>
  
  <p>The question is: </p>
  
  <p><em>What is the proper "value" to assign to</em> <code>Field.initial</code>, <em>for different kinds of relationship form-fields?</em></p>
  
  <h2>Background</h2>
  
  <p>Suppose we have a simple <code>Model</code> with <em>one or more</em> <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#module-django.db.models.fields.related" rel="nofollow noreferrer">relationship fields</a>, i.e. <code>OneToOneField</code>, <code>ForeignKey</code>, or <code>ManyToManyField</code>. By default, the latter has an <em>implicit</em> <code>through</code> model, but it may also use an <em>explicit</em> <code>through</code> model, as explained in the <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#django.db.models.ManyToManyField.through" rel="nofollow noreferrer">docs</a>. An explicit <code>through</code> model is a model with <a href="https://docs.djangoproject.com/en/2.1/topics/db/models/#extra-fields-on-many-to-many-relationships" rel="nofollow noreferrer">at least</a> two <code>ForeignKey</code> fields.</p>
  
  <p>The relationship fields, represented by select-boxes, appear automatically on the standard <code>ModelAdmin</code> "add" or "change" forms, except for the <code>ManyToManyField</code> with <em>explicit</em> <code>through</code> model. That one requires an inline, such as the <code>TabularInline</code>, as explained <a href="https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#working-with-many-to-many-intermediary-models" rel="nofollow noreferrer">here</a> in the docs.</p>
  
  <p>Note that the <em>implicit</em> <code>ManyToManyField</code> is associated with a <code>ModelMultipleChoiceField</code> on the (admin) form, and the other relationship fields are associated with a <code>ModelChoiceField</code>. The latter includes the <code>ManyToManyField</code> with <em>explicit</em> <code>through</code> model, because that is actually represented by a <code>ForeignKey</code> field in the <code>TabularInline</code>. </p>
  
  <h2>Goal</h2>
  
  <p>Now consider a basic Django <code>ModelAdmin</code> "add" (or "change") page for this model, including inlines for any <em>explicit</em> <code>through</code> models. An example based on Django's Pizza-Topping is depicted below.</p>
  
  <p>We want to achieve two goals:</p>
  
  <ol>
  <li>set the <em>initial selection</em> for one or more of the relationship fields</li>
  <li>the initial selection must be <em>saved</em> to the database if we click one of the "Save" buttons (assuming we did not change the selection manually)</li>
  </ol>
  
  <p>Note that the second one seems trivial, but apparently isn't (see below).</p>
  
  <p><a href="https://i.stack.imgur.com/gEsBs.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gEsBs.png" alt="django pizza admin example"></a></p>
  
  <h2>Approach</h2>
  
  <p>As far as I know, there are several ways to achieve this: </p>
  
  <ul>
  <li>set the model field <code>default</code> value, e.g. <code>ForeignKey.default</code>, optionally passing a callable (<a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#default" rel="nofollow noreferrer">docs</a>)</li>
  <li>set the <code>Form.initial</code> value for the admin form (<a href="https://docs.djangoproject.com/en/2.1/ref/forms/api/#django.forms.Form.initial" rel="nofollow noreferrer">docs</a>)</li>
  <li>set the <code>Field.initial</code> value for the admin form-field (<a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#initial" rel="nofollow noreferrer">docs</a>)</li>
  </ul>
  
  <p><em>Regardless</em> of which approach is "best" for a certain use case, <em>this question</em> is about the last approach: setting the value of <code>Field.initial</code>.</p>
  
  <p>We do this by extending <code>ModelAdmin.formfield_for_dbfield</code> (or <code>TabularInline.formfield_for_dbfield</code>), as follows:</p>
  
  <pre><code>def formfield_for_dbfield(self, db_field, request, **kwargs):
      if db_field.name == 'some_relationship_field_name':
          kwargs['initial'] = value
      return super().formfield_for_dbfield(db_field, request, **kwargs)
  </code></pre>
  
  <p>The <code>value</code> in this example could be an <code>obj.id</code>, <code>obj</code>, <code>[obj.id, ...]</code>, or <code>[obj, ...]</code>, where <code>obj</code> is a <code>Model</code> instance.</p>
  
  <h2>Problem</h2>
  
  <p>Depending on the type of relationship field, different types of <code>value</code> may or may not work.</p>
  
  <p>For the <code>ManyToManyField</code> with implicit <code>through</code> model, we can only assign a list of objects, so that one is easy.</p>
  
  <p>For the other relationships, in some cases the initial select-box selection matches the assigned value, but is not saved (e.g. because <a href="https://docs.djangoproject.com/en/2.1/_modules/django/forms/fields/#Field.has_changed" rel="nofollow noreferrer">Field.has_changed</a> returns <code>False</code>). 
  In other cases the initial select-box value is saved, but does not match the assigned value.       </p>
  
  <h2>Question</h2>
  
  <p>So, the obvious question is:</p>
  
  <p><strong>What is the proper <code>value</code> to assign to <code>Field.initial</code>, for different kinds of relationship fields on an admin form?</strong></p>
  
  <h2>Related</h2>
  
  <p>Despite having spent quite a lot of time searching, I could not find a clear answer in the documentation, nor on SO, nor anywhere else. Also tried to figure this out through the source code, but that turns out to be quite tricky.</p>
  
  <p>Some similar questions: </p>
  
  <ul>
  <li><a href="https://stackoverflow.com/q/5223048">Django, set initial data to formset with ManyToMany</a></li>
  <li><a href="https://stackoverflow.com/q/10000950">How to set initial data for Django admin model add instance form?</a></li>
  <li><a href="https://stackoverflow.com/q/6164773">Django AdminForm field default value</a></li>
  <li><a href="https://stackoverflow.com/q/2960232">django-admin formfield_for_* change default value per/depending on instance</a></li>
  <li><a href="https://stackoverflow.com/q/12656529">Django - ForeignKey field initial value definition in Admin</a></li>
  </ul>