Как показать в выпадающем списке Django Forms текст, доступ к которому осуществляется по внешнему ключу?
У меня есть код для редактирования таблицы "instruments", которая имеет внешний ключ к другой таблице 'instrumenttype'. Я хочу отобразить выпадающий список, показывающий текстовые значения из таблицы instreumenttype. Моя проблема заключается в том, что выпадающий список показывает "InstrumentType object(n)" вместо описания типа инструмента из другой таблицы. Обновление работает нормально; когда я получаю выбранное значение и обновляю таблицу инструментов, вставляется правильный идентификатор ключа.
Вот форма:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from instruments.models import Instrument
from instrumenttypes.models import InstrumentType
# Form used to edit the data pertaining to a specific instrument
class EditInstrumentForm(forms.ModelForm):
instrumenttype = forms.ModelChoiceField(queryset=InstrumentType.objects.all())
class Meta:
model = Instrument
fields = ('instrument', 'dateAdded', 'dateRemoved', 'nickname', 'serialNo', 'status',
'instrumenttype')
Вот фрагмент представления:
def update_instrument_view(request, id=id):
instrument = get_object_or_404(Instrument, id=id)
if request.method == 'POST':
form = EditInstrumentForm(request.POST, request.FILES, instance=instrument)
if form.is_valid():
instrument.instrument = form.cleaned_data.get('instrument')
instrument.dateAdded = form.cleaned_data.get('dateAdded')
instrument.dateRemoved = form.cleaned_data.get('dateRemoved')
instrument.nickname = form.cleaned_data.get('nickname')
instrument.serialNo = form.cleaned_data.get('serialNo')
instrument.status = form.cleaned_data.get('status')
instrument.instrumenttype = form.cleaned_data.get('instrumenttype')
instrument.save()
messages.success(request, 'Your instrument has been updated.')
return redirect('instrument_details', instrument.id)
else:
form = EditInstrumentForm(instance=instrument)
messages.error(request, 'Issue updating data.')
return render(request, 'instrument_update.html', {'form': form, 'instrument':instrument})
else:
form = EditInstrumentForm(instance=instrument)
return render(request, 'instrument_update.html', {'form':form, 'instrument': instrument})
Выпадающий список показывает ссылку на объект, но я хочу, чтобы он показывал instrumenttype.instrumentType (который является текстовым описанием). Снимок вывода формы
Вот модель таблицы типов приборов:
from django.db import models
from instrumenttypes.models import InstrumentType
from stations.models import Station
# Create your models here.
class Instrument(models.Model):
instrument = models.CharField(max_length=40)
instrumenttype = models.ForeignKey(InstrumentType, on_delete=models.CASCADE, null=True)
station = models.ForeignKey(Station, on_delete=models.CASCADE, default=1)
serialNo = models.CharField(max_length=60, null=True, blank=True)
dateAdded = models.DateTimeField("Date Added", null=True, blank=True)
dateRemoved = models.DateTimeField("Date Removed", null=True, blank=True)
status = models.CharField(max_length=10, null=True, blank=True)
nickname = models.CharField(max_length=40, null=True, blank=True)
Вот модель таблицы инструментов:
from django.db import models
from instrumenttypes.models import InstrumentType
from stations.models import Station
# Create your models here.
class Instrument(models.Model):
instrument = models.CharField(max_length=40)
instrumenttype = models.ForeignKey(InstrumentType, on_delete=models.CASCADE, null=True)
station = models.ForeignKey(Station, on_delete=models.CASCADE, default=1)
serialNo = models.CharField(max_length=60, null=True, blank=True)
dateAdded = models.DateTimeField("Date Added", null=True, blank=True)
dateRemoved = models.DateTimeField("Date Removed", null=True, blank=True)
status = models.CharField(max_length=10, null=True, blank=True)
nickname = models.CharField(max_length=40, null=True, blank=True)
Я прочитал много документации и соответствующих ответов об этом, но пока не нашел решения... расстраивает, потому что это кажется такой простой вещью...
переопределите метод __str__
на вашей модели, чтобы вернуть соответствующее описание, например;
def __str__(self):
return self.instrumentType
(обратите внимание, что в вашем вопросе дважды указана модель инструмента, а не модель InstrumentType, которую вы упоминаете, так что не уверен на 100%, что это правильное поле для доступа, но должно быть достаточно легко для вас, чтобы заставить работать, если это не так)
Если вы хотите вызвать пользовательский метод вместо того, чтобы полагаться на поведение __str__
, смотрите https://docs.djangoproject.com/en/4.0/ref/forms/fields/#django.forms.ModelChoiceField.iterator:
from django.forms import ModelChoiceField
class InstrumentTypeModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return f"choice: {obj.instrumentType}"