Django foreign key как опции для автозаполнения, ошибка: Выберите правильный вариант

Заранее благодарю за помощь. Я создаю свой первый проект Django, приложение для продажи билетов, в котором будет более 100 пунктов на выбор.

Я пытаюсь отобразить список элементов (объекты с внешним ключом) для выбора пользователем при создании билета в поле автозаполнения MDBootstrap. Элементы имеют как имя, так и ID, и я хочу, чтобы оба отображались в опциях автозаполнения, когда пользователь осуществляет поиск.

Моя форма работает, когда я отображаю только 'item_id' из модели Item в данных автозаполнения (находится в тегах скрипта внизу шаблона). Но когда я отображаю строку с 'item_name' и 'item_id' (как показано ниже), моя форма не отправляется и я получаю ошибку "Select a valid choice. Этот выбор не является одним из доступных вариантов."

Как я могу отобразить и 'item_name' и 'item_id' из модели Item в опциях автозаполнения, но затем заставить мою форму правильно отправить, распознав 'item_id' для своего поля внешнего ключа 'item'?

модели (каждая из этих моделей находится в отдельном приложении в проекте django)

    class Item(models.Model):
        item_name = models.CharField(max_length=200)
        item_id = models.CharField(max_length=200, primary_key=True)
    
    class Ticket(models.Model):
        ticket_id = models.AutoField(primary_key=True, null=False, blank=False)
        item = models.ForeignKey(Item, on_delete=models.PROTECT, null=False, blank=False, related_name="tickets")

view

    def TicketSubmit(request):
        items = Item.objects.all()  
        if request.method == "POST":
            item = request.POST.get("item")
            form = TicketSubmitForm(request.POST)
            photoform = TicketImageForm(request.POST or None)
            files = request.FILES.getlist("ticket_photo")
            if form.is_valid():
                f = form.save(commit=False)
                f.item = item
                for i in files:
                     TicketPhoto.objects.create(ticket=f, ticket_photo=i)
                messages.success(request, "Success! New Ticket Created")
                return HttpResponseRedirect(reverse_lazy("home"))
            else:
                print(form.errors)
        else:
            form = TicketSubmitForm()
            photoform = TicketImageForm()
        context = {"form": form, "photoform": photoform, "items": list(items)}
        return render(request, "home.html", context)

form

  class TicketSubmitForm(forms.ModelForm):
     class Meta:
         model = Ticket
         fields = ["item", "op_name", "ticket_text"]
         widgets = {
             "created_at": forms.HiddenInput,
             "completed": forms.HiddenInput,
             "item": forms.TextInput(
                 attrs={
                     "class": "form-control",
                     "id": "form11",
                 }
             ),
             "op_name": forms.TextInput(
                 attrs={
                     "class": "form-control",
                     "id": "op_nameInput",
                     "placeholder": "Enter your name here",
                 }
             ),
             "ticket_text": forms.Textarea(
                 attrs={
                     "class": "form-control",
                     "placeholder": "Write a few words about the issue here",
                     "rows": "4",
                 }
             ),
         }    

main.js

    const basicAutocomplete = document.querySelector('#basic');
    const dataFilter = (value) => {
        return data.filter((item) => {
            return item.toLowerCase().startsWith(value.toLowerCase());
        });
    };

    new mdb.Autocomplete(basicAutocomplete, {
        filter: dataFilter
    });

шаблон

    <form id="ticket_form" role="form" action="" method="post" enctype="multipart/form-data" class="">{% csrf_token %}
            <div id="basic" class="form-outline mx-5 mb-2">
                {{form.item}}
                <label class="form-label" for="form1">Find Item</label>
            </div>
    #other form fields and submit button
    </form>

    <script>
        const data = [{% for i in items %}'{{ i.item_name }} | ID:  {{ i.item_id }}', {% endfor %}];
    </script>

Ошибка заключается в том, что вы создаете другую строку для анализа данных при получении данных из формы, а не ту, которую ожидает Django, которая является уникальным идентификатором или вашим первичным ключом.

Это скорее проблема дизайна, но у вас есть несколько доступных вариантов.

Можно было бы просто, перед разбором данных, когда выбирается элемент, например, 'LT7 - Large Tractor 7', иметь шаблон Regex, чтобы адаптировать входные данные к тому, что нужно Django для работы с вашей моделью, или еще проще, разделить str на -. и взять первый элемент, который будет первичным ключом, который вам нужен

pk: str = input_from_form_string.split(' - ')[0]  # Your LT7 will be in this variable

Является более простым способом достижения цели.

Я смог исправить это следующим образом.

 if request.method == "POST":
        updated_request = request.POST.copy()
        item = request.POST.get("item")
        item = item.split("ID:")[1].strip()
        updated_request.update({"item": item})
        form = TicketSubmitForm(updated_request)
        photoform = TicketImageForm(request.POST or None)
        files = request.FILES.getlist("ticket_photo")
        if form.is_valid():
            f = form.save()
            for i in files:
                TicketPhoto.objects.create(ticket=f, ticket_photo=i)
            messages.success(request, "Success! New Ticket Created")
            return HttpResponseRedirect(reverse_lazy("home"))
        else:
            print(form.errors)
    else:
        form = TicketSubmitForm()
        photoform = TicketImageForm()
    context = {"form": form, "photoform": photoform, "items": list(items)}
    return render(request, "home.html", context)

Спасибо @AlexVergara за то, что направил меня в нужное русло.

Вернуться на верх