pythonhtmldjangoweb

How to show more object information on forms in django


This is a follow up question to this question: How to pass user object to forms in Django

Here is my form:

class SellForm(forms.Form):
    symbol = forms.ModelChoiceField(queryset=None, widget=forms.Select(attrs={
        'class': 'form-control',
        'placeholder': 'Symbol',
        'autofocus': 'autofocus',
        }))
    
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        super(SellForm, self).__init__(*args, **kwargs)
        self.fields['symbol'].queryset = Holdings.objects.filter(student=self.request.user.student)

This form is providing me with this dropdown: the example of the dropdown that this form creates

I have extra information in the model which is the purchase price of each share, is there a way to get this onto the form also? It would have to be non editable though as its the price that the share was purchased at.

Here is the model that the form is getting the data from:

class Holdings(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    symbol = models.CharField(max_length=10)
    purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
    
    class Meta:
        verbose_name_plural = "Holdings"
        ordering = ['symbol']
    
    def __str__(self):
        return self.symbol

I would very much appreciate any help if possible! Thank you!


Solution

  • The simplest way is just overriding the __str__ method and include the purchase price:

    class Holdings(models.Model):
        student = models.ForeignKey(Student, on_delete=models.CASCADE)
        symbol = models.CharField(max_length=10)
        purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
    
        class Meta:
            verbose_name_plural = "Holdings"
            ordering = ['symbol']
    
        def __str__(self):
            return f'{self.symbol} ({self.purchase_price})'

    Filtering can be done more efficiently though with:

    class SellForm(forms.Form):
        symbol = forms.ModelChoiceField(
            queryset=None,
            widget=forms.Select(
                attrs={
                    'class': 'form-control',
                    'placeholder': 'Symbol',
                    'autofocus': 'autofocus',
                }
            ),
        )
    
        def __init__(self, *args, request, **kwargs):
            super(SellForm, self).__init__(*args, **kwargs)
            self.fields['symbol'].queryset = Holdings.objects.filter(
                student__user=self.request.user
            )

    since this will prevent a query to get the Student object for the user, or we can work with:

    class SellForm(forms.Form):
        symbol = forms.ModelChoiceField(
            queryset=None,
            widget=forms.Select(
                attrs={
                    'class': 'form-control',
                    'placeholder': 'Symbol',
                    'autofocus': 'autofocus',
                }
            ),
        )
    
        def __init__(self, *args, request, **kwargs):
            super(SellForm, self).__init__(*args, **kwargs)
            self.fields['symbol'].queryset = Holdings.objects.filter(
                student_id=self.request.user.student_id
            )