Как обновить конкретное поле manytomany в django

#django #many-to-many #modelform #m2m #create-view

#django #многие ко многим #modelform #m2m #создать-просмотр

Вопрос:

Моя модель области имеет атрибут exercise с ManyToManyField для моей модели Exercise:

 class Area(models.Model):
    name = models.CharField(max_length=100)
    exercise = models.ManyToManyField(Exercise)

class Exercise(models.Model):
    name = models.CharField(max_length=100)
  

В моем AreaView отображается список областей, каждая из которых ссылается на свой собственный список конкретных упражнений, показанный AreaDetailView:

 class AreaView(ListView):
    model = Area
    template_name = 'workouts/areas.html'

class AreaDetailView(DetailView):
    model = Area
    template_name = 'workouts/exercises.html'

    def get_context_data(self, **kwargs):
        context = super(AreaDetailView, self).get_context_data(**kwargs)
        context['e_form'] = AddExerciseForm
        return context
  

например:

 areas.html
- abs
- biceps
- cardio
- legs ...

exercises.html
Abs
- Ab-wheel
- Cable-crunch
- Plank ...

Biceps
- Barbell curl
- Cable curl
- Dumbbell curl
  

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

Вот моя форма:

 class AddExerciseForm(forms.ModelForm):
    class Meta:
        model = Exercise
        fields = ['name']
  

Мой шаблон:

 <form action="{% url 'exercise_add_new' %}" method="post">
    {% csrf_token %}
    {{ e_form }}
    <button type="submit">Save changes</button>
</form>
  

Мой URL:

 path('exercise-add-new', ExerciseFormView.as_view(), name='exercise_add_new'),
  

И вот мой CreateView, который должен обрабатывать логику:

 class ExerciseFormView(CreateView):
    form_class = AddExerciseForm
    success_url = '/'

    def form_valid(self, form):
        form.save()
        new_ex = Exercise.objects.latest('id')
        area = Area.objects.get(id=1)
        area.exercise.add(new_ex)
        return super(ExerciseFormView, self).form_valid(form)
  

Это позволяет мне нормально обновить первый объект в моей модели области, но мне нужно настроить значение переменной area , form_valid чтобы обновить текущий «идентификатор». Например, если я нажму на «Бицепс», а затем заполню форму, я хочу добавить упражнение, связанное с «id = 2»

Я пробовал area = Area.objects.get(id=self.kwargs['id']) и другие подобные варианты, но пока ничего из того, что я пробовал, не сработало

Ответ №1:

В ExerciseFormView вы пытаетесь добавить новое упражнение в область или создать новую область?
При добавлении нового упражнения вам нужно будет передать area-id URL что-то вроде add_exercise/<area_id> , если делать последнее, это должно быть просто.

У вас есть area-id URL-адрес, который вы можете сделать, как показано ниже

 path('exercise-add-new/<int:area_id>/', ExerciseFormView.as_view(), 
        name='exercise_add_new')
  

Затем обновите свой view , как показано ниже

 def form_valid(self, form):
    form.save()
    area = Area.objects.get(pk=self.kwargs["area_id"])
    new_ex = Exercise.objects.latest('id')
    area.exercise.add(new_ex)
    return super(ExerciseFormView, self).form_valid(form)
  

Также обновите шаблон как :

 <form method="post">
    {% csrf_token %}
    {{ e_form }}
    <button type="submit">Save changes</button>
</form>
  

Комментарии:

1. Привет @Coderaemon спасибо за ваш ответ. Я пытаюсь добавить новое упражнение в область, которая уже существует. Я обновил свой вопрос, чтобы показать свои самые последние усилия

2. Я обновил свой ответ. Пожалуйста, проверьте и дайте мне знать, работает ли это.

3. Отлично! Мне просто нужно было вернуть действие обратно в форму вместе с area.id , и оно работает правильно. Большое спасибо за вашу помощь