Home > database >  Making a CreateForm with choices based on database values
Making a CreateForm with choices based on database values

Time:05-31

I am making a django project and I have a form for the User to add a Vehicle Manually that will be assigned to him. I also would like to had an option for the user to choose a vehicle based on the entries already present in the database.

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"

I created a form so the user can add his Vehicles as such:

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']

The corresponding view:

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)

The html file:

vehicles/templates/vehicles/vehicle_form.html

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

 <div >
    <form method="POST">
        {% csrf_token %}
        <fieldset >
            <legend >New Vehicle</legend>
            {{ form|crispy }}
        </fieldset>
        <div >
            <button  type="submit">Submit</button>
        </div>
    </form>
    
</div>
{% endblock content %}
 

I would like to add another form in which the user has a dropdown with option with the brands, models and batteries that already exist in the database. If there's a car in the database with brand: Tesla, model: Model 3, battery: 50 kWh, then it would appear in the dropbox as a choice for each field.

I'm not sure how to do this and sorry for the newbie question... Thanks in advance!

CodePudding user response:

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 %}

Output-

enter image description here

enter image description here

enter image description here

enter image description here

Note- if u can't see updated values in dropdown do server restart because localhost not suport auto update value fill in dropdown it's supoorted on live server

Thank you

CodePudding user response:

I once had to do something similar, but I needed a form which had one checkbox for each item in a list of externally-supplied strings. I don't know if this is the cleanest way, but I used python metaclasses:

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()

In my get() method, I instantiate it as:

    form = SockSelectForm.build(names)

and the corresponding form handling in the post() method is:

    form = SockSelectForm(request.POST)

I suspect if you look under the covers of Django's ModelForm, you'd see something similar, but I couldn't use ModelForm because it's too closely tied to the model system for what I needed to do.

  • Related