Django: как отфильтровать поле формы на основе отношения "многие ко многим"?

В настоящее время, когда пользователь создает задачу, он может назначить ее всем пользователям. Я хочу, чтобы они могли назначать задачу только на основе членов проекта. Мне кажется, что концепция, которую я имею сейчас, работает, но мне нужно заменить ????.

projects/models.py

class Project(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    members = models.ManyToManyField(USER_MODEL, related_name="projects")

tasks/models.py

class Task(models.Model):
    name = models.CharField(max_length=200)
    start_date = models.DateTimeField()
    due_date = models.DateTimeField()
    is_completed = models.BooleanField(default=False)
    project = models.ForeignKey(
        "projects.Project", related_name="tasks", on_delete=models.CASCADE
    )
    assignee = models.ForeignKey(
        USER_MODEL, null=True, related_name="tasks", on_delete=models.SET_NULL
    )

tasks/views.py

class TaskCreateView(LoginRequiredMixin, CreateView):
        model = Task
        template_name = "tasks/create.html"
        # fields = ["name", "start_date", "due_date", "project", "assignee"]
    
        form_class = TaskForm
    
        def get_form_kwargs(self):
            kwargs = super(TaskCreateView, self).get_form_kwargs()
            kwargs["user"] = self.request.user
            kwargs["project_members"] = ??????????
            return kwargs

tasks/forms.py

class TaskForm(ModelForm):
    class Meta:
        model = Task
        fields = ["name", "start_date", "due_date", "project", "assignee"]

    def __init__(self, *args, **kwargs):
        user = kwargs.pop("user")
        project_members = kwargs.pop("project_members")
        super(TaskForm, self).__init__(*args, **kwargs)
        self.fields["project"].queryset = Project.objects.filter(members=user)
        self.fields["assignee"].queryset = Project.objects.filter(
            members=?????????
        )

Проблема здесь в том, что ваша задача не знает, какие члены являются релевантными для включения в качестве назначенных, пока вы не выбрали проект, к которому принадлежит задача, а проект и назначенный выбираются в одной форме, поэтому Django еще не знает, кто является релевантным.

Самый простой способ справиться с этим - убедиться, что вызов создания задачи связан с проектом, для которого она будет создана - например,

Обновите ваши URL-адреса для работы с ID проекта

Path('create-task/<int:project_id>', TaskCreateView.as_view(), name='create_task')

Обновить представление

class TaskCreateView(LoginRequiredMixin, CreateView):
    model = Task
    template_name = "tasks/create.html"
    # fields = ["name", "start_date", "due_date", "assignee"]
    #NB: I have remove project from the field list, you may need to do the same in your form as it is handled elsewhere
    form_class = TaskForm

    def get_form(self, *args, **kwargs):
        form = super(TaskForm, self).get_form(*args, **kwargs)
        form.fields['assignee'].queryset = Project.members.filter(project_id = self.kwargs['project_id'])

    def form_valid(self, form):
        form.instance.project_id = project.self.kwargs['project_id']
        return super(CreateTask, self).form_valid(form)

Добавить ссылки

<a href="{% url create_task project_id %}">Create Task for this project</a>

Это создаст ссылку на странице подробностей проекта или под проектом в представлении списка на "создать задачу для этого проекта", перенося информацию о проекте в представление через URL. В противном случае вам придется прибегнуть к более сложным вызовам ajax, которые будут динамически заполнять список потенциальных назначенцев на основе выбора в выпадающем списке проекта

Вернуться на верх