Opened 3 months ago

Closed 3 months ago

Last modified 3 months ago

#35272 closed Bug (invalid)

Django Admin - changing input to <select> tag using ModelChoiceField posts an Object(1) in the form

Reported by: DaveG Owned by: nobody
Component: Forms Version: 5.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I simplified the Location model for clarity but when I use the code below to modify the admin interface it works fine but on submitting the form the text of the value attribute in the <option> tag is not posted, an object is. The Endpoint.sgln field just contains "Object(1)" and not the actual string from the <option> value attribute. I added images of the admin form, the generated html and the resulting row in the database from a submission. Not sure if this is a bug or a feature.

models.py

class Location(models.Model):
    sgln = models.CharField(max_length=15, unique=True)
    name = models.CharField(max_length=64)
    streetAddress = models.CharField(max_length=64)
    suite = models.CharField(max_length=64)
    city = models.CharField(max_length=32)
    state = models.CharField(max_length=2)
    postalCode = models.CharField(max_length=10)

class Endpoints(models.Model):
    sgln = models.CharField(max_length=19, unique=True)
    login = models.CharField('Endpoint Login ', max_length=32, default=None, null=True)
    password = models.CharField('Endpoint Password', max_length=32, default=None, null=True)
    tstamp = models.DateTimeField(auto_now_add=True)

forms.py

class SglnModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return obj.sgln + ":" + obj.name

class EndpointForm(forms.ModelForm): 
    sgln = SglnModelChoiceField(
        queryset=Location.objects.all(),
        to_field_name="sgln",
        label="Endpoint SGLN",
        required=True,
    )
    login = forms.CharField(label='Endpoint Login', max_length=32, required=True)
    password = forms.CharField(label='Endpoint Password', max_length=32, required=True)

admin.py

from django.contrib import admin
from .forms import EndpointForm
from .models import Endpoints

class EndpointAdmin(admin.ModelAdmin):
    form = EndpointForm

admin.site.register(Endpoints, EndpointAdmin)

the actual form as it appears in the admin interface:
https://i.stack.imgur.com/vZfGW.png

The HTML for the same form:
https://i.stack.imgur.com/n4eqG.png

The row inserted into the database:
https://i.stack.imgur.com/ju8RY.png

Change History (3)

comment:1 by Natalia Bidart, 3 months ago

Component: UncategorizedForms
Keywords: admin forms removed
Resolution: invalid
Status: newclosed
Type: UncategorizedBug

Hello Dave, thank you for your report.

I don't see how Django is at fault here: your EndpointForm, which is a ModelForm, is defining a sgln field to be a custom ModelChoiceField. The way Django works ensures that the value for the sgln field is actually an instance of a Location, you can clearly see this in the form's clean method for example (cleaned_data is {'sgln': <Location: Location object (2)>, 'login': 'q', 'password': 'q'} after form submission and data validation). But then the value of a model instance (<Location: Location object (2)>) has to be used to populate a CharField, so the str representation of the Location instance is being used, and since your model does not define a custom str, the default is used.

I see a few issues with your proposed approach, but I'm not going to detail those here since this is not a support channel. Django has a friendly community and multiple user support channels that you can reach out to for help. You can found those here: https://www.djangoproject.com/community/

comment:2 by DaveG, 3 months ago

Resolution: invalidfixed

This was user error

I changed to a ChoiceField and was able to get it working

comment:3 by Natalia Bidart, 3 months ago

Resolution: fixedinvalid

Thank you Dave for letting us know (though resolution should be kept as "invalid" since this is not a valid bug report about Django itself).

Note: See TracTickets for help on using tickets.
Back to Top