Django - Автоматическое заполнение отношения "многие-ко-многим-полям

Я пытаюсь сделать форму, которая автоматически заполняет отношение "многие-ко-многим" для моей модели пользователя. Цель состоит в том, чтобы иметь кнопку отправки, которая добавляет объект экземпляра представления (объект SingelWorkout) к отношению полей "многие ко многим" в моей пользовательской модели.

Представление точно отображает правильный объект, а форма отображается так, как было задумано в шаблоне. Я не хочу, чтобы пользователь видел выбор полей "многие ко многим". Кроме кнопки отправки, я стараюсь, чтобы вся логика происходила на бэкенде. Как я могу назначить экземпляр объекта полю в форме? Это должно происходить в views.py или forms.py?

Вот почему моя модель пользователя выглядит следующим образом:

class FitnessUser(AbstractUser):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField(max_length=60)
    age_category = models.ForeignKey(
        AgeGroup,
        on_delete=models.CASCADE,
        blank=True,
        null=True
    )
    goal = models.IntegerField(default=1 ,choices=Purpose.choices)
    weight = models.CharField(max_length=30)
    height = models.CharField(max_length=30)
    gender = models.ForeignKey(
        Gender,
        on_delete=models.CASCADE,
        blank=True,
        null=True
    )
    exercise_frequency = models.IntegerField(default=1 ,choices=Frequency.choices)
    template_id = models.ForeignKey(
        Workout_template,
        on_delete=models.CASCADE,
        blank=True,
        null=True
        )
    completed_workouts = models.ManyToManyField(SingleWorkout)

    def get_absolute_url(self):
        return reverse('detail', args=[self.id])

Это моя форма в файле forms.py:

class CustomWorkoutChangeForm(UserChangeForm):
    class Meta(UserChangeForm):
        model = FitnessUser
        fields = ('completed_workouts',)
        exclude = ('completed_workouts',)
        UserChangeForm.password = None

Вот как выглядит мой вид:

class WorkoutUpdateView(LoginRequiredMixin, UpdateView):
    model = SingleWorkout
    template_name = 'workout/daily_view.html'
    form_class = CustomWorkoutChangeForm
    success_url = reverse_lazy("template")

    def get_context_data(self, **kwargs):
        context = super(WorkoutUpdateView, self).get_context_data(**kwargs)
        context['workout'] = SingleWorkout.objects.get(slug = self.kwargs['slug'])
        return context

Мой html-шаблон выглядит следующим образом:

{{workout}}
<br>
workout:
<br>
{{ workout.exercise_1 }}
<br>
{{ workout.description_1 }}
<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Confirm">
</form>

Придумал решение. Я создал представление, которое получает объект экземпляра на основе url slug объекта, а также получает пользователя по его pk. Оттуда добавляет объект экземпляра в поле пользователя many to many, затем перенаправляет обратно на предыдущую страницу.

Создано новое представление:

def update_workout_data(request, slug):   
    workout = SingleWorkout.objects.get(slug=slug)
    endUser = FitnessUser.objects.get(pk = request.user.pk)
    endUser.completed_workouts.add(workout)
    endUser.save()
    return redirect(reverse('daily', kwargs={'slug':workout.slug}))

Обновленный внешний вид HTML. Я также изменил html и его детальное представление так, чтобы ссылка на обновление перенаправляла на отдельное представление обновления, в зависимости от необходимости добавить/удалить отношение.

{% block content %}
Daily View
<br>
{{exercise}}
<br>
workout:
<br>
<br>
{% if exercise.name in workouts %}
<h5>Workout Already Completed</h5>
<form method="POST" action="{% url 'remove' slug=exercise.slug %}">
    {% csrf_token %}
    <button type="submit">Reset</button>
</form>
{% else %}
<form method="POST" action="{% url 'update' slug=exercise.slug %}">
    {% csrf_token %}
    <button type="submit">Complete</button>
</form>
{% endif %}
{% endblock content %}

Обновленный детальный вид

    def get_context_data(self, **kwargs):
        context = super(WorkoutDetailView, self).get_context_data(**kwargs)
        user = FitnessUser.objects.get(pk = self.request.user.pk)
        context['exercise'] = SingleWorkout.objects.get(slug = self.kwargs['slug'])
        context['workouts'] = {}
        for workout in user.completed_workouts.all():
            context['workouts'][workout.name] = workout
        return context
Вернуться на верх