Django ModelChoice字段条件ForeignKey

时间:2018-08-20 21:16:49

标签: django python-3.x django-models django-forms django-views

我整个下午都在冲浪,已经有一段时间了。

我正在尝试弄清楚如果用户驾驶了这种类型的汽车,如何从本质上将外键作为下拉选项。出于示例目的,并使其尽可能简单...

假设我有一个CarsManufacturers和一个UserProfile模型。

我有一个Cars的模型……

class Cars(models.Model):

    car_name = models.CharField(max_length=80)    
    class = models.ForeignKey(Manufacturer,null=True,on_delete=models.DO_NOTHING,related_name='car_manufacturer')

我有一个Manufacturers的模型……

class Manufacturers(models.Model):

        manu_name = models.CharField(max_length=80)  

然后我有一个UserProfile模型。...

class Userprofile(models.Model):

   user = models.OneToOneField(User,on_delete=models.CASCADE)
   user_name = models.CharField(max_length=80)    
   car_owned = models.ForeignKey(Car,null=True,on_delete=models.DO_NOTHING,related_name='car_owned')

到目前为止一切顺利...

我有一个视图,其中列出了所有Manufacturers,这也很好。它在下面的表格视图中显示了我期望的所有制造商。

class ManufacturerForm(forms.Form):

    dropdown = forms.ModelChoiceField(queryset=Manufacturer.objects.all())

    def __init__(self, *args, **kwargs):
        super(ManufacturerForm, self).__init__(*args, **kwargs)
        self.fields['dropdown'].widget.attrs['class'] = 'choices1'
        self.fields['dropdown'].empty_label = ''

我正在使用下面的FORMVIEW来显示表单...

class ManufacturerView(LoginRequiredMixin,FormView):
    form_class = ManufacturerForm
    template_name = 'Directory/HTMLNAME.html'

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

    def form_valid(self, form):
        manufacturer = form.cleaned_data['dropdown']
        return HttpResponseRedirect(reverse("NAME:manufacturer",kwargs={'pk':manufacturer.pk}))

一切正常。但是,我不知道如何将制造商下拉列表限制为仅用户驾驶的汽车。我试图从本质上将下拉列表限制为仅与基于用户个人资料拥有的汽车相关的制造商。我已经研究了反向查找,并且还尝试了类似于下面概述的方法来解决我的问题...

class ManufacturerForm(forms.Form):

    dropdown = forms.ModelChoiceField(queryset=Manufacturer.objects.filter(car_manufacturer=1)

    def __init__(self, *args, **kwargs):
        super(ManufacturerForm, self).__init__(*args, **kwargs)
        self.fields['dropdown'].widget.attrs['class'] = 'choices1'
        self.fields['dropdown'].empty_label = ''

但这显然只给我记录Manufacturer模型的记录1。我试图弄清楚如何仅显示基于个人拥有的数据与单个用户相关的记录。我可以列出所有制造商,然后仅显示ListView中相关的记录,但是我试图将下拉列表限制为仅ListView中有相关记录的地方。预先感谢您的任何想法。

2 个答案:

答案 0 :(得分:1)

您只错过了几点:
1)以UserProfile身份通过kwargs['user']

kwargs['user'] = UserProfile.objects.get(user=self.request.user)  

2)在表单的user签名中添加__init__参数,并在此处覆盖dropdown.queryset

class ManufacturerForm(forms.Form):
    dropdown = forms.ModelChoiceField(queryset=Manufacturer.objects.all())

    def __init__(self, user, *args, **kwargs):
        super(ManufacturerForm, self).__init__(*args, **kwargs)
        self.fields['dropdown'].widget.attrs['class'] = 'choices1'
        self.fields['dropdown'].empty_label = ''
        self.fields['dropdown'].queryset = Manufacturer.objects.filter(car_manufacturer__car_owned=user)

我也建议您将您的Car - User关系重写为ManyToMany。如果我正确理解您的信息,则用户可以拥有多辆汽车:

  

将下拉列表限制为仅显示以下内容的制造商   与汽车 s 有关的用户拥有

如果我理解的正确,您还希望跟踪用户曾经拥有(但现在不再拥有)的汽车。
如果您重写Car - User关系,那么您可能没有任何理由仅保留其他UserProfile来保持username模型。如果是这样,您的models.py应该如下所示:

class Manufacturer(models.Model):
    name = models.CharField(max_length=80)


class Car(models.Model):
    name = models.CharField(max_length=80)
    klass = models.ForeignKey(Manufacturer, null=True, on_delete=models.DO_NOTHING, related_name='car_manufacturer')
    owners = models.ManyToManyField(User, through='Ownership')


class Ownership(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    car = models.ForeignKey(Car, on_delete=models.CASCADE)
    active = models.BooleanField(default=True)   # True if user owns the car at the moment

答案 1 :(得分:0)

我认为这全都取决于您的订单和模型之间的关系,也许尝试在ManyToManyManufacturer之间添加Car关系,这样一个制造商就可以制造许多汽车:

Class Manufacturer(models.Model):

name = models.CharField(max_length=80)
car = models.ManyToManyField(Car)

然后可能是做某事的情况,例如:

qs = Manufacturer.objects.all(car=user.car_owned)

dropdown = forms.ModelChoiceField(qs)

在您的views.py文件中:

form = ManufacturerForm(request.POST, user=request.user)

(您可能需要检查以上内容是否有效,因为我不确定Forms是否可以传入请求对象)。

免责声明:我看到您使用的是基于class的视图...因此,我可能需要调整以上内容。