简体   繁体   English

获取不属于不同 model 的多对多关系的对象?

[英]Get objects that are not in manytomany relationship of a different model?

Lets say I have two models and a form:假设我有两个模型和一个表单:

class Person(models.Model):
    first_name      = models.CharField(max_length=255)
    last_name       = models.CharField(max_length=255)

class Car(models.Model):
    plate   = models.CharField(max_length=255)
    persons = models.ManyToManyField(Person)
class CarAddForm(forms.ModelForm):
    plate           = forms.CharField()
    persons         = forms.ModelMultipleChoiceField(queryset=Person.objects.all())

    class Meta:
        model = Car
        fields = [
            'plate',
            'persons'
        ]

Is there a way to get ModelMultipleChoiceField queryset of people that are NOT associated with any car?有没有办法获取与任何汽车无关的人的 ModelMultipleChoiceField 查询集? In case of editing Car model object, the queryset should contain people that are NOT associated with any car PLUS people that are associated with the car being edited在编辑 Car model object 的情况下,查询集应包含与任何汽车无关的人员以及与正在编辑的汽车相关联的人员

PS: maybe there is a better way to achieve this? PS:也许有更好的方法来实现这一点?

You can make use of the limit_choices_to --(Doc) argument of ManyToManyField as您可以使用ManyToManyFieldlimit_choices_to --(Doc)参数作为

class Car(models.Model):
    plate = models.CharField(max_length=255)
    persons = models.ManyToManyField(
        Person,
        limit_choices_to={"car__isnull": True}
    )

Alternatively, you can also alter the queryset argument of ModelMultipleChoiceField as或者,您也可以将ModelMultipleChoiceFieldqueryset参数更改为

class CarAddForm(forms.ModelForm):
    plate = forms.CharField()
    persons = forms.ModelMultipleChoiceField(
        queryset=Person.objects.filter(car__isnull=True)
    )

    class Meta:
        model = Car
        fields = [
            'plate',
            'persons'
        ]

You can specify a filter for the query:您可以为查询指定过滤器:

from django.db import models

class CarAddForm(forms.ModelForm):
    ...
    persons = forms.ModelMultipleChoiceField(
        queryset=Person.objects\
            .annotate(car_count=models.Count('cars'))\
            .filter(car_count=0))
    ...

Another options is to override the forms __init__() method.另一种选择是覆盖 forms __init__()方法。 Maybe like this:也许是这样的:

from django.db import models

class CarAddForm(forms.ModelForm):
    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['person'].queryset = self.fields['person'].queryset\
            .annotate(car_count=models.Count('cars'))\
            .filter(car_count=0))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM