Chowdahhh
Chowdahhh

Reputation: 159

How to filter Django Form dropdown for currently logged-in user (Class Based Views)

I have the two models, Fillup and Car, and the Fillup model has a Foreign key (for recording times you fill up your car with gas, for example), and in the form to create a new Fillup, I want to limit the dropdown for the Car field to only Cars associated with the current user, but right now it's showing all users cars. I've seen a couple solutions that involve passing the request into the form from the view but I can't figure out how to do it using the Class Based Views I currently have set up. Here's my code:

models.py

class Fillup(models.Model):
    username = models.ForeignKey(User,on_delete=models.CASCADE)
    date = models.DateField(default=date.today)
    price_per_gallon = models.FloatField()
    trip_distance = models.FloatField()
    gallons = models.FloatField()
    car = models.ForeignKey('Car',on_delete=models.CASCADE)

    @property
    def total_sale(self):
        return round(self.price_per_gallon*self.gallons, 2)

    @property
    def mpg(self):
        return round(self.trip_distance/self.gallons, 4)


class Car(models.Model):
    username = models.ForeignKey(User,on_delete=models.CASCADE)
    name = models.CharField(max_length=25)
    make = models.CharField(max_length=25)
    model = models.CharField(max_length=25)
    model_year = models.IntegerField(choices=MODEL_YEARS)
    status = models.BooleanField(choices=STATUS)

    def __str__(self):
        return self.name

views.py

class FillupListView(ListView):
    model = Fillup
    context_object_name = 'fillup_list'
    ordering = ['-date']

    # NOT USING THIS YET
    # def get_queryset(self):
    #     return Fillup.objects.filter(user=self.request.user)

class CarListView(ListView):
    model = Car
    ordering = ['name']

class NewFillup(LoginRequiredMixin,CreateView):
    model = Fillup
    fields = ('date', 'price_per_gallon', 'trip_distance', 'gallons', 'car')
    redirect_field_name = 'fillup_list'

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

class NewCar(LoginRequiredMixin,CreateView):
    model = Car
    fields = ('name', 'make', 'model', 'model_year', 'status')
    redirect_field_name = 'car_list'

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

forms.py

class FillupForm(forms.ModelForm):

    def __init__(self, user, *args, **kwargs):
        super(FillupForm,self).__init__(*args, **kwargs)
        self.fields['car'].queryset = Car.objects.filter(username=user)

    class Meta():
        model = Fillup
        fields = ('date', 'price_per_gallon', 'trip_distance', 'gallons', 'car')


class CarForm(forms.ModelForm):

    class Meta():
        model = Car
        fields = ('name', 'make', 'model', 'model_year', 'status')

The overwriting of the init method in FillupForm was just one of the things I tried to get this to work, adapted from another Stackoverflow answer, but it didn't seem to have any effect. Any advice/examples to get this working would be appreciated! And let me know if I should supply any more pieces of my code

Upvotes: 0

Views: 1678

Answers (2)

Chowdahhh
Chowdahhh

Reputation: 159

I ended up getting my answer to this from r/djangolearning on Reddit.

I needed to add the following to both of my CreateViews:

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

They also pointed out that I needed to replace the fields=('blah blah blah') on both CreateViews with form_class=forms.Fillup/Car

I hope this helps someone with the same issue as me!

Upvotes: 1

Maneesh Bodakuntla
Maneesh Bodakuntla

Reputation: 1

You can do something like this in the init method.

        cars = Car.objects.filter(username=user)
        self.fields['car'].autocomplete = False
        self.fields['car'].queryset = users

Hope this helps.

Upvotes: 0

Related Questions