Form template tags for models.ForeignKey field

I’m trying to render my form fields manually in a template and have found the following available tags which allows me to work with most field types:

{{ field.name }}
{{ field.label }}
{{ field.id_for_label }}
{{ field.value }}
{{ field.widet_type }}
{{ field.auto_id }}
{{ field.errors }}
{{ field.help_text }}

For a field that is defined as a models.ForeignKey, this needs to be placed into a form as a

I’m sorry, I don’t understand what you’re asking for here.

Can you be more specific about what information you need, or provide more detail about what you’re trying to do?

@KenWhitesell I’m needing to manually build every field on a form on my template such that I can control how the fields are displayed and interacted with.

For a basic charField when I place it on a form I know I can do the following:

<input type="text" id="{{ form.field.id_for_label}}" name="{{ form.field.name }}" value="{{ form.field.value}}">

If however I want to place a model.ForeignKey field onto a form which will need to be a input type of select, how do I get all the options? What I can’t find in the documentation is how to access the option choices in a field that I need to iterate to generate my form field.
The output would be something like:

<select name="host" required id="id_host">
  <option value="">---------</option>

  <option value="20">Bristol University</option>

  <option value="21" selected>Cambridge University</option>
</select>

What are the {{ form.field.??? }} tags to get the ‘option value’ and ‘option text’?

Thanks

They aren’t tags. That’s not how options are rendered. See the select.html template in django.forms.templates.django.forms.widgets to see how they’re handled. (Rendering the select widget also causes the option templates to be rendered.)

Thanks for the link to the technical implementation, it however is currently beyond by Django/Python understanding to see how they work.

If I understand you correctly in Django it is possible to manually render a basic <input type=“text” and set all the requirements using tags based on the field, it is not possible to do the same with a <select as it’s not possible to access all of the <option value detail.
Therefore the only way to render a select field is by {{ form.field }} and pass anything additional through widget.attrs

This does however seem to go against the documentation on this page:
https://docs.djangoproject.com/en/5.0/topics/forms/modelforms/

If the model field has choices set, then the form field’s widget will be set to Select, with choices coming from the model field’s choices. The choices will normally include the blank choice which is selected by default. If the field is required, this forces the user to make a selection. The blank choice will not be included if the model field has blank=False and an explicit default value (the default value will be initially selected instead).

This implies that I should be able to access {{ form.field.choices }} in a template but I assume that it is not exposed for me to access.

First, there’s a terminology issue here to clarify that caused me to misread your original post. That was my mistake, and I apologize.

The term “tag” has a very specific meaning within Django, and is something different than a “variable”. A tag is something enclosed between {% %} markers while a variable reference is enclosed between {{ }}.

Almost, the form.fields.<fieldname>.choices is an iterator that you can cycle through in your template. However, this does not prevent the select field itself from iterating over that same set - and if you try to render those options manually, you’re going to get two copies of each.

What I think you really want to do is re-think your approach here.

Why are you trying to do it this way?

Django provides the template structures, and the ability for you to override a template, for a reason. Learn how to work with Django to fulfill the requirements, don’t try to reinvent the wheel.

Or, as I like to say: “Don’t fight the framework”.

That’s great, I hadn’t found form.fields. just form.
It’s provided what I needed.

I completely understand about it not being ‘the Django way’ but does get me to where I need to be efficiently and provides the needed result.

Thanks for your help.