Django 使用 ModelForm 覆盖 __init__ 表单方法

Django override __init__ form method using ModelForm

我有一个外键 (zone_set) 作为表单中的选择字段。它应该只显示当前项目的 zone_set 。如您所见,情况并非如此,因为它显示的 zone_set: I belong to an other project, I should not be displayed here 不属于当前项目。

请帮忙!

这是我的表格,但它不起作用

class ODMatrixForm(forms.ModelForm):

    class Meta:
        model = ODMatrix
        # fields = '__all__'
        exclude = ('size', 'locked',)

    def __init__(self, current_project=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if current_project:
            queryset = ZoneSet.objects.filter(project=current_project)
            self.fields['zone_set'].queryset = queryset

创建 ODMatrix 的视图

def create_od_matrix(request, pk):
    """A roadnetwork depends on a project. It
     must be created inside the project"""
    
    current_project = Project.objects.get(id=pk)
    form = ODMatrixForm(initial={'project': current_project})
    if request.method == 'POST':
        print(request)
        od_matrix = ODMatrix(project=current_project)
        # form = ODMatrixForm(request.POST, instance=od_marix)
        form = ODMatrixForm(data=request.POST, instance=od_matrix)
        if form.is_valid():
            form.save()
            messages.success(request, "OD matrix cessfully created")
            return redirect('od_matrix_details', od_matrix.pk)

    context = {
        'project': current_project,
        'form': form}
    return render(request, 'form.html', context)

您创建了 __init__ 作为 Meta class 的构造函数,这应该是 ODMatrixForm 的构造函数,所以:

class ODMatrixForm(forms.ModelForm):
    
    #       🖟 part of ODMatrixForm, not Meta
    def <strong>__init__</strong>(self, current_project=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if current_project:
            self.fields['zone_set'].queryset = ZoneSet.objects.filter(
                project=current_project
            )
    
    class Meta:
        model = ODMatrix
        # fields = '__all__'
        exclude = ('size', 'locked',)

在视图中,构造ODMatrixForm对象时需要传递current_project

from django.shortcuts import get_object_or_404

def create_od_matrix(request, pk):
    current_project = get_object_or_404(Project, pk=pk)
    if request.method == 'POST':
        form = ODMatrixForm(<strong>current_project</strong>, request.POST, request.FILES)
        if form.is_valid():
            form.instance.project = current_project
            form.save()
            messages.success(request, 'OD matrix cessfully created')
            return redirect('od_matrix_details', od_matrix.pk)
    else:
        form = ODMatrixForm(<strong>current_project=current_project</strong>)
    context = {
        'project': current_project,
        'form': form
    }
    return render(request, 'form.html', context)

Note: It is often better to use get_object_or_404(…) [Django-doc], then to use .get(…) [Django-doc] directly. In case the object does not exists, for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using .get(…) will result in a HTTP 500 Server Error.