3

I am trying to display the version field from the below model other than the default str which is field2_name:

Note: This SO link Displaying a specific field in a django form might be more than I need but I am not 100% sure. I tried to implement this but was not successful.

Also note that I tried the example at https://docs.djangoproject.com/en/1.10/ref/forms/fields/ but was not able to get it to work

Model (Generic names):

class CodeVersion(models.Model):
field1= models.ForeignKey(SomeOtherModel, on_delete=models.CASCADE)
field2_name = models.CharField(max_length=256)
field3_description = models.CharField(max_length=1000, blank=True)
version = models.PositiveIntegerField()

def __str__(self):
  return self.field2_name

Form:

class VersionsForm(forms.Form):

code_versions = forms.ModelChoiceField(queryset=CodeVersion.objects.none())

def __init__(self, SomeOtherModel_id):
   super(VersionsForm, self).__init__()
   self.fields['infocode_versions'].queryset = CodeVersion.objects.filter(SomeOtherModel_id=SomeOtherModel_id)

This works - it returns field2_name as it is supposed to.

How do I return version instead - what is the simplest way?

Any help or guidance is appreciated.

Community
  • 1
  • 1
beginAgain
  • 211
  • 4
  • 17

4 Answers4

7

From the ModelChoiceField docs:

The __str__ (__unicode__ on Python 2) method of the model will be called to generate string representations of the objects for use in the field’s choices; to provide customized representations, subclass ModelChoiceField and override label_from_instance. This method will receive a model object, and should return a string suitable for representing it. For example:

from django.forms import ModelChoiceField

class MyModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "My Object #%i" % obj.id
Community
  • 1
  • 1
knbk
  • 52,111
  • 9
  • 124
  • 122
  • Thank you for your response. I tried a version of this (see 1st SO link) and I was unable to get it to work. It is possible that I did it incorrectly though. I will look at this specific example today. The truth is I am not really clear on exactly what is happening in this example but I will "dig in". :) – beginAgain Feb 01 '17 at 13:05
  • Gave you +1 - please see comment I made to iklinac. – beginAgain Feb 03 '17 at 14:27
3

If I got your question correctly you could change object string representation

def __str__(self):
  return str(self.version)

You could then inherit ModelChoiceField and override label_from_instance method

or even monkey patch it like this

self.fields['field_name'].label_from_instance = self.label_from_instance

@staticmethod
def label_from_instance(self):
    return str(self.value)
iklinac
  • 14,944
  • 4
  • 28
  • 30
  • Thank you for responding :) Unfortunately I can't change the str for this particular model. – beginAgain Feb 01 '17 at 01:22
  • You could then inherit ModelChoiceField and override label_from_instance method – iklinac Feb 01 '17 at 01:34
  • Thank you - I will look further in to label_from_instance and your ideas today. – beginAgain Feb 01 '17 at 13:08
  • Turns out I was able to change the str to what I needed - it wasn't being used yet. I will have to put this on the back burner as I am sure this will be needed in the future. Gave you +1. – beginAgain Feb 03 '17 at 14:26
  • @iklinac is there a way to write the monkey patch method all in one line? For example incorporate the `label_from_instance` routine in the right hand side of `self.fields['field_name'].label_from_instance = self.label_from_instance` – Ibo Aug 23 '18 at 22:52
  • @Ibo use lambda: `self.fields['field_name'].label_from_instance = lambda obj: str(obj.value)` – lampslave Oct 28 '19 at 22:19
1

The simplest way in this case that I struggled myself:

under your line of code

self.fields['infocode_versions'].queryset = CodeVersion.objects.filter(SomeOtherModel_id=SomeOtherModel_id)

insert this:

self.fields["infocode_versions"].label_from_instance = lambda obj: "%s" % obj.version
Tash000
  • 31
  • 2
0

In one line :

self.fields['code_versions'].label_from_instance = lambda obj: f"{obj.version}"

Complete example

class VersionsForm(forms.Form):

    code_versions = forms.ModelChoiceField(queryset=CodeVersion.objects.none())
    
    def __init__(self, SomeOtherModel_id):
       super().__init__()
       self.fields['code_versions'].queryset = CodeVersion.objects.filter(SomeOtherModel_id=SomeOtherModel_id)
       self.fields['code_versions'].label_from_instance = lambda obj: f"{obj.version}"
Lucas B
  • 2,183
  • 1
  • 22
  • 22