Django - 在内联表单集中过滤ForeignKey下拉菜单

时间:2017-01-27 21:10:49

标签: python django

我有以下型号:

models.py

class Train(models.Model):
    pass

class City(models.Model):
    train = models.ForeignKey(Train)
    name = models.CharField(max_length=100)

class Route(models.Model):
    train = models.ForeignKey(Train)
    name = models.CharField(max_length=100)

class Travel(models.Model):
    train = models.ForeignKey(Train)
    current_city = models.ForeignKey(City, related_name = 'current')
    through = models.ForeignKey(Route)
    next_city = models.ForeignKey(City, related_name = 'next')

我正在使用内联表单集创建与特定列车相关的Travel实例,其中包含以下内容:

views.py

class TrainInfoUpdate(UpdateView):
    model = Train
    fields = []
    success_url = reverse_lazy('train-list')

    def get_context_data(self, **kwargs):
        data = super(TrainInfoUpdate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['travels'] = TravelFormSet(self.request.POST, instance=self.object)
        else:
            data['travels'] = TravelFormSet(instance=self.object)
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        travels = context['travels']
        with transaction.atomic():
            self.object = form.save()

            if travels.is_valid():
                travels.instance = self.object
                travels.save()
        return super(TrainInfoUpdate, self).form_valid(form)

forms.py

class TrainForm(ModelForm):
    class Meta:
        model = Train

class CityForm(ModelForm):
    class Meta:
        model = City

class RouteForm(ModelForm):
    class Meta:
        model = Route

class TravelForm(ModelForm):
    class Meta:
        model = Travel

CityFormSet = inlineformset_factory(Train, City, form=CityForm, extra=1)

RouteFormSet = inlineformset_factory(Train, Route, form=RouteForm, extra=1)

TravelFormSet = inlineformset_factory(Train, Travel, form=TravelForm, extra=1)

这为我提供了所有城市和路线的下拉菜单,但我想将它们仅限于与该列车相关的城市和路线,我该如何实现?

2 个答案:

答案 0 :(得分:0)

this的帮助下,我设法通过在views.py中定义一个查询集来找到解决方案,如下所示:

def get_context_data(self, **kwargs):
    data = super(TrainInfoUpdate, self).get_context_data(**kwargs)
    cities_query = City.objects.all().filter(train=self.object)
    routes_query = Route.objects.all().filter(train=self.object)
    if self.request.POST:
        data['travels'] = TravelFormSet(self.request.POST, instance=self.object)
        for form in data['travels']:
            form.fields['current_city'].queryset = cities_query
            form.fields['next_city'].queryset = cities_query
            form.fields['through'].queryset = routes_query
    else:
        data['travels'] = TravelFormSet(instance=self.object)
        for form in data['travels']:
            form.fields['current_city'].queryset = cities_query
            form.fields['next_city'].queryset = cities_query
            form.fields['through'].queryset = routes_query
    return data

答案 1 :(得分:0)

您可以使用formfield_callback参数inlineformset_factory来自定义查询集。内联文档源代码说明了formfield_callback参数:

  

formfield_callback是一个可调用的模型字段和   回报       一个表格领域。

对于您的情况,解决方案是:

def custom_form_field_callback(field, **kwargs):
    cities_query = City.objects.filter(filter_field=filter_value)
    if field.name == "city":
         return City(queryset= cities_query) 
    else:
         return field.formfield(**kwargs)

CityFormSet = inlineformset_factory(Train, City, formfield_callback=custom_form_field_callback)

注意:如果您没有自定义ModelForm,那么您不需要将form=CityForm参数传递给inlineformset_factory