首页 > 解决方案 > Exclude option in select that's already choosen by user

问题描述

Is it possible to exclude options that is already choosed by user and stored in a table?

This is the tables from teh models.py

class Fruit(models.Model):
name = models.CharField(max_length=250, unique=True, blank=False, null=False)
sort= models.ForeignKey('FruitSort', on_delete=models.SET_NULL, null=True, blank=False)

def __str__(self):
    return '%s (%s)' % (self.name, self.sort.name)

class UserFruit(models.Model):
    Comment = models.CharField(max_length=55)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    fruit = models.ForeignKey('Fruit', on_delete=models.CASCADE)

    class Meta:
        unique_together = (("user", "fruit",),)

This is the forms.py that generate my form.

class UserFruit(forms.ModelForm):

class Meta:
    model = UserFruit
    fields = ('comment', 'fruit')

def __init__(self, *args, **kwargs):
    super(UserFruit, self).__init__(*args, **kwargs)
    for visible in self.visible_fields():
        visible.field.widget.attrs['class'] = 'form-control form-style-alt'
        self.fields['comment'].widget.attrs['placeholder'] = 'comment'
        self.fields['fruit'].empty_label = 'Please, choose fruit'

Now the views.py

class Fruit(generic.CreateView):
    form_class = UserFruit
    template_name = 'fruit.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(instance=UserFruit.objects.filter(user=request.user).first())
        fruit = UserFruit.objects.filter(user=request.user)
        return render(request, self.template_name, {'form': form, 'fruit': fruit})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save()
        return redirect('fruit')

And finally the template.

 <h3>Add a juicy fruit</h3>
        <form method="post">
            {% csrf_token %}
                <div class="form-group">
                    <div>
                        <span class="text-danger">{{ error }}</span>
                    </div>
                {{ form.fruit }}
                {{ form.comment }}
                    <button class="btn" type="submit"> Save</button>
                </div>
        </form>

I want to exclude, or disable, fruits that the user already have added. I don't seem to find a DRY and smooth solution for this. I can loop through from the databse and exclude via javascript. But seems tacky.

Ideas are much appreciated!

标签: pythondjangodjango-forms

解决方案


的。例如,您可以将user参数传递给表单,并作为Fruit尚未选择的查询集选择,例如:

class UserFruitForm(forms.ModelForm):

    class Meta:
        model = UserFruit
        fields = ('comment', 'fruit')

    def __init__(self, user, *args, **kwargs):
        super(UserFruit, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control form-style-alt'
        self.fields['comment'].widget.attrs['placeholder'] = 'comment'
        self.fields['fruit'].empty_label = 'Please, choose fruit'
        self.fields['fruit'].queryset = Fruit.objects.exclude(
            userfruit__user=user
        )

但是您在CreateView. 您可以简单地让 theCreateView完成几乎所有的工作:

from django.urls import reverse_lazy

class Fruit(generic.CreateView):
    form_class = UserFruitForm
    template_name = 'fruit.html'
    success_url = reverse_lazy('fuit')

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update(user=self.request.user)
        return kwargs

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context.update(fruit=UserFruit.objects.filter(user=self.request.user))
        return context

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

请将表格重命名为UserFruitForm. 现在,您在模型和表单之间引入了名称冲突。通过重命名它,您所指的内容就很清楚了。UserFruitUserFruit


推荐阅读