I have models which is Player and Position. Player is associated with position player is currently at. You can assign a player new position, which is why I need it to use it in some form. But in that form I see that Position is position Object (see image bellow), but I would like to put "Position.name" in there to see the name of choices instead that object, but I have no Idea how to do it.
Thank you for your help.
models.py
class Position(models.Model):
name = models.CharField(max_length=20)
short = models.CharField(max_length=2)
class Players(models.Model):
name = models.CharField(max_length=200)
positionId = models.ForeignKey(Position, on_delete=models.CASCADE, null=True, blank=True)
forms.py
class CompositionForm(ModelForm):
class Meta:
model = Players
fields = ("positionId", ... many more ... )
table.html
<table id="nominated-player-table" class="table table-bordered" style="">
{% for form in formset.forms %}
{% if forloop.first %}
<thead>
<td colspan="15"
style="background-color: dimgray; color: white; border-top-right-radius: 15px; border-top-left-radius: 15px; border: none">
Nominovaní hráči
</td>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr>
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
CodePudding user response:
I ran into this the other day, but with a ModelChoiceField in an ordinary form, not a ModelForm. You subclass ModelChoiceField to override the choices labels generation. From the Django docs:
from django.forms import ModelChoiceField
class MyModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return "My Object #%i" % obj.id
In your case include obj.PositionId.name
in the label
Something similar should be possible for ModelForms. Check docs. Yes, modelform_factory has a field_classes
argument so you can override the default ModelChoiceField
CodePudding user response:
You need add to your models the magic methods __str__
or __unicode__
, because Django itself don't know how to convert model instances to string, and represents it as ModelName object
# In python 2.x you can uncoment next line.
# from __future__ import unicode_literals
class Position(models.Model):
name = models.CharField(max_length=20)
short = models.CharField(max_length=2)
def __unicode__(self):
return self.name
class Players(models.Model):
name = models.CharField(max_length=200)
positionId = models.ForeignKey(
Position, on_delete=models.CASCADE, null=True, blank=True)
def __unicode__(self):
return self.name
If you need more pesonalization, you can use label_from_instance
in the form:
class CustomModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return 'The position with name %s' % obj.name
class CompositionForm(forms.ModelForm):
positionId = CustomModelChoiceField(queryset=Position.objects)
class Meta:
model = Players
fields = ("positionId", ... many more ... )