Создание формы CreateForm с вариантами выбора на основе значений базы данных

Я делаю проект на django и у меня есть форма для пользователя, чтобы добавить автомобиль вручную, который будет закреплен за ним. Я также хотел бы иметь возможность для пользователя выбрать автомобиль на основе записей, уже имеющихся в базе данных.

vehicles/models.py

class Vehicle(models.Model):

user =  models.ForeignKey(User, on_delete=models.CASCADE) 
nickname = models.CharField(unique = True, max_length=150)
date_joined = models.DateTimeField(default=timezone.now)
brand = models.CharField(max_length=150)
battery = models.CharField(max_length=150)
model = models.CharField(max_length=150)

def __str__(self):
        return self.nickname

def get_absolute_url(self):

    return reverse('vehicle-list')
class Meta:
    db_table = "vehicles"

Я создал форму, чтобы пользователь мог добавить свои транспортные средства следующим образом:

vehicles/forms.py

class VehicleAddFormManual(forms.ModelForm):

class Meta:
    model = Vehicle
    fields = ('brand','model', 'battery', 'nickname')

def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    super().__init__(*args, **kwargs)
    self.fields['brand']
    self.fields['model']
    self.fields['battery']
    self.fields['nickname']

Соответствующий вид:

vehicles/views.py

class AddVehicleViewManual(LoginRequiredMixin, CreateView):

model = Vehicle
form_class = VehicleAddFormManual

def get_form_kwargs(self):
       
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

def form_valid(self, form):
        
        form.instance.user = self.request.user
        return super().form_valid(form)

Файл html:

<
{% extends "blog/base.html" %}
{% block content %}
{% load crispy_forms_tags %}

 <div class="content-section">
    <form method="POST">
        {% csrf_token %}
        <fieldset class="form-group">
            <legend class="border-bottom mb-4">New Vehicle</legend>
            {{ form|crispy }}
        </fieldset>
        <div class="form-group">
            <button class="btn btn-outline-info" type="submit">Submit</button>
        </div>
    </form>
    
</div>
{% endblock content %}
 
vehicles/templates/vehicles/vehicle_form.html

Я хочу добавить еще одну форму, в которой у пользователя будет выпадающий список с опциями с марками, моделями и аккумуляторами, которые уже существуют в базе данных. Если в базе данных есть автомобиль с маркой: Tesla, модель: Model 3, батарея: 50 кВтч, то он появится в выпадающем списке в качестве варианта для каждого поля.

Я не уверен как это сделать и извините за вопрос новичка.... Заранее спасибо!

model.py

    class DropdownModel(models.Model):
        brand = models.CharField(max_length=150)
        battery = models.CharField(max_length=150)
        model = models.CharField(max_length=150)
    
        def __str__(self):
            return self.brand.

    

form.py

    from .models import DropdownModel
    
    all_brand = DropdownModel.objects.values_list('brand','brand')
    all_battery = DropdownModel.objects.values_list('battery','battery')
    all_model= DropdownModel.objects.values_list('model','model')
    
    class DropdownForm(forms.ModelForm):
        class Meta:
            model = DropdownModel
            fields = "__all__"
    
            widgets = {
                'brand':forms.Select(choices=all_brand),
                'battery':forms.Select(choices=all_battery),
                'model':forms.Select(choices=all_model),
            }

index.html

{% extends "base.html" %}
{% load static %}
{% block title %}
     Index | Page 
{% endblock title %}
   
{% block body %}
  {{form.as_p}}
{% endblock body %}

Выход-

enter image description here

enter image description here

enter image description here

enter image description here

Примечание- если вы не видите обновленные значения в выпадающем списке, перезагрузите сервер, потому что localhost не поддерживает автоматическое обновление значений в выпадающем списке, оно поддерживается на живом сервере

Спасибо

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

class SockSelectForm(forms.Form):
    @staticmethod
    def build(sock_names):
        fields = {'sock_%s' % urllib.parse.quote(name):
                  forms.BooleanField(label=name, required=False)
                  for name in sock_names}
        sub_class = type('DynamicSockSelectForm', (SockSelectForm,), fields)

        return sub_class()

В моем методе get() я инстанцирую его как:

    form = SockSelectForm.build(names)

а соответствующая обработка формы в методе post() такова:

    form = SockSelectForm(request.POST)

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

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