Home > OS >  Django choice field as model ForeignKey in FormSet
Django choice field as model ForeignKey in FormSet

Time:11-05

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.

Position Object

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 ... )

  • Related