Model Form Select Values

Hello!

I seem to be stuck on what seems like it should be a relatively easy task!

I have a Model form for creating an Asset, which displays the relevant FK in the select options (Take the ‘Facility’ field as an example from the Model below:

class AssetData(models.Model):
    Description = models.CharField(blank=True, null=True,max_length=100)
    UU_Project_Number = models.ForeignKey(Project, null=True, on_delete=models.CASCADE)
    Site_Code = models.CharField(blank=True, null=True,max_length=5)
    Facility = models.ForeignKey(Facility, null=True, on_delete=models.CASCADE)
    Facility_Number = models.IntegerField(blank= False, null= True,)
    Process = models.ForeignKey(Process, null=True, on_delete=models.CASCADE)
    Process_Number = models.IntegerField(blank= False, null= True)
    Arrangement = models.ForeignKey(Arrangement, null=True, on_delete=models.CASCADE )
    Arrangement_Number = models.IntegerField(blank= False, null= True)
    Asset_Group = models.ForeignKey(AssetGroup, null=True, on_delete=models.CASCADE )
    Asset_Group_Number = models.IntegerField(blank= False, null= True)
    Equipment_Group_Identifier = models.ForeignKey(EGI, null = True, on_delete=models.CASCADE)
    Engineering_Design_Identifier = models.ForeignKey(EDI, null = True, on_delete=models.CASCADE)
    PID_Tag = models.ForeignKey(PID_Tag, blank=False, null=False,max_length=50, on_delete=models.CASCADE)
    PID_Tag_NUmber = models.CharField (blank=True, null=True, max_length = 7)
    Asset_Number = models.CharField(blank=False, null=False,max_length=50)
    Drawing = models.ForeignKey(Drawing, null = True, blank = False, on_delete=models.CASCADE)

    @property
    def friendly_display(self):
        values = "{}- {}".format(self.Asset_Number, self.Description)                 
        return values
    
    def __str__(self):
        return self.Asset_Number
     
    def save(self, *args, **kwargs):
        super(AssetData, self).save(*args, **kwargs)
        #Create the Unique Asset Number based on other Fields
        self.Asset_Number = f'{self.UU_Project_Number}-{self.Site_Code}-{self.Facility}{self.Facility_Number}-\
        {self.Process}{self.Process_Number}-{self.Arrangement}{self.Arrangement_Number}-\
        {self.Asset_Group}{self.Asset_Group_Number}-{self.PID_Tag}{self.PID_Tag_NUmber}'
        
        super().save(*args, **kwargs)

For this Model i have created this form:

class AssetData_Form(forms.ModelForm):
    def __init__(self,projectid, *args, **kwargs):
        super(AssetData_Form, self).__init__(*args, **kwargs)
        self.fields['Drawing'].queryset = Drawing.objects.filter(UU_Project_Number = projectid)
        

                
    class Meta:
        model = AssetData        
        exclude = ['UU_Project_Number', 'Site_Code','Asset_Number']
        widgets = {
            'Facility': forms.Select(attrs={
             'hx-get':" /process_options",
             'hx-target': '#id_Process',
             'hx-trigger': 'change'
         }),
            'Process': forms.Select(attrs={
             'hx-get': "/arrangement_options" ,
             'hx-target': '#id_Arrangement',
             'hx-trigger': 'change'
         }),

            'Asset_Group': forms.Select(attrs={
             'hx-get': "/EGI_options" ,
             'hx-target': '#id_Equipment_Group_Identifier',
             'hx-trigger': 'change'
         }),    
        
        }

How can I change the values in the select box from the default of the str field of the facility Model to the ‘friendly_display’ property of the ‘Facility’ Model?

class Facility(models.Model):

    Facility_Code = models.CharField( blank=True, null=True,max_length=2 )	
    Facilty_Description = models.CharField( blank=True, null=True,max_length=1000 )
    Facilty_Extended_Description = models.CharField( blank=True, null=True,max_length=5000 )
    #Process = models.ManyToManyField(Process,through = 'Facility_Process_Link')

    @property
    def friendly_display(self):
        values = "{}- {}".format(self.Facility_Code,self.Facilty_Description)                 
        return values
    
    def __str__(self):
        return self.Facility_Code
    
    class Meta:
        ordering = ['Facility_Code'] 

See the paragraph under the iterator docs where it talks about using the __str__ method for replacing the function being used to render the “display” portion of the options. Basically, you will subclass the widget to call your custom function, and use that widget in your form.

1 Like

Thanks for the advice, sometimes as a newbie to Django the hard part is finding the correct part of the docs to reference!
Although i didn’t use that method, it set me on the path to finding a solution, which was overriding the init method of the form and initialising the form field as such:

self.fields['Facility'].label_from_instance = lambda obj: "%s" % obj.friendly_display