Direct assignment to the forward side of a many-to-many set is prohibited. User exercise.set() instead

  ajax, django, json, python

I have two models, Exercise and Workouts. I want to create a workout with a set of exercise. I have already able to send the array of exercise and workout details using POST and ajax, but I keep getting this error. I have read all other questions with this error, but my problem is two things: 1-the exercise item is already created, 2-I want to add more than one exercise item to the workout table. Any idea on how to do this?

models.py:

class Exercise(models.Model):
    BODYPART_CHOICES = (
        ('Abs', 'Abs'), ('Ankle', 'Ankle'),
        ('Back', 'Back'), ('Biceps', 'Biceps'),
        ('Cervical', 'Cervical'), ('Chest', 'Chest'), ('Combo', 'Combo'),
        ('Forearms', 'Forearms'), ('Full Body', 'Full Body'),
        ('Hip', 'Hip'),
        ('Knee', 'Knee'),
        ('Legs', 'Legs'), ('Lower Back', 'Lower Back'), ('Lumbar', 'Lumbar'),
        ('Neck', 'Neck'),
        ('Shoulders', 'Shoulders'),
        ('Thoracic', 'Thoracic'), ('Triceps', 'Triceps'),
        ('Wrist', 'Wrist'),
    )

    CATEGORY_CHOICES = (
        ('Cardio', 'Cardio'),
        ('Stability', 'Stability'),
        ('Flexibility', 'Flexibility'),
        ('Hotel', 'Hotel'),
        ('Pilates', 'Pilates'), ('Power', 'Power'),
        ('Strength', 'Strength'),
        ('Yoga', 'Yoga'),
        ('Goals & More', 'Goals & More'),
        ('Activities', 'Activities'),
        ('Rehabilitation', 'Rehabilitation'),
    )

    EQUIPMENT_CHOICES = (
        ('Airex', 'Airex'),
        ('BOSU', 'BOSU'), ('Barbell', 'Barbell'), ('Battle Rope', 'Battle Rope'), ('Bodyweight', 'Bodyweight'),
        ('Cables', 'Cables'), ('Cones', 'Cones'),
        ('Dumbbells', 'Dumbbells'), ('Dyna Disk', 'Dyna Disk'),
        ('Foam Roller', 'Foam Roller'),
        ('Kettlebells', 'Kettlebells'),
        ('Leg Weights', 'Leg Weights'),
        ('Machine', 'Machine'), ('Medicine Ball', 'Medicine Ball'),
        ('Plate', 'Plate'), ('Power Wheel', 'Power Wheel'),
        ('Ring', 'Ring'),
        ('Sandbag', 'Sandbag'), ('Stick', 'Stick'), ('Strap', 'Strap'), ('Suspension', 'Suspension'), ('Swiss Ball', 'Swiss Ball'),
        ('Theraball', 'Theraball'), ('Towel', 'Towel'), ('Tubbing / Bands', 'Tubbing / Bands'),
        ('Wobble Board', 'Wobble Board'),
    )
    name = models.CharField(max_length=200)
    photograph = models.ImageField(upload_to='img_exercises', blank=True, null=True)
    body_part = models.CharField(max_length=50, choices=BODYPART_CHOICES)
    equipment = models.CharField(max_length=200, choices=EQUIPMENT_CHOICES)
    equipment_two = models.CharField(max_length=200, choices=EQUIPMENT_CHOICES, default=None, blank=True, null=True)
    category = models.CharField(max_length=100, choices=CATEGORY_CHOICES)
    workout_tip = models.TextField(max_length=3000)
    cmf_url = models.URLField(max_length=400)

    def __str__(self):
        return self.name

class Workout(models.Model):
    name = models.CharField(max_length=200)
    exercises = models.ManyToManyField(Exercise)
    description = models.TextField(max_length=3000, default=None, blank=True, null=True)
    goals = models.TextField(max_length=3000, default=None, blank=True, null=True)
    workout_time = models.CharField(max_length=200, default=None, blank=True, null=True)
    difficulty = models.CharField(max_length=200, default=None, blank=True, null=True)    
    workout_rating = models.PositiveIntegerField(default=None, blank=True, null=True)
    notes = models.TextField(max_length=5000, blank=True, null=True)
    status = models.TextField(max_length=100, default='created')
    def __str__(self):
        return self.name

forms.py:

class WorkoutForm(forms.ModelForm):
    
    class Meta:
        model = Workout
        fields = ( 'name', 'exercises', 'description', 'goals', 'workout_time', 'difficulty')

javascript

  create_workout.addEventListener('click', e=>{
    //workout details
    const workout_form = document.getElementById('workout_form')
    const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    const exercises = workoutExercise
    const name = document.getElementById('id_name').value
    const description = document.getElementById('id_description').value
    const goals = document.getElementById('id_goals').value
    const time = document.getElementById('id_workout_time').value
    const difficulty = document.getElementById('id_difficulty').value
    //console.log(exercises)
    create_workout_function(csrftoken, name, description, goals, time, difficulty, workoutExercise)
    
  })
}

function create_workout_function(csrftoken, name, description, goals, time, difficulty, exercises){
  $.ajax({
    type: "POST",
    url: 'workout/create/',
    enctype: 'multipart/form-data',
    datatype: 'json',
    data: {
      csrfmiddlewaretoken: csrftoken,
      name: name,
      description: description,
      goals: goals,
      workout_time: time,
      difficulty: difficulty,
      exercises: exercises,
    },
    success: (response)=>{
      console.log(response)
    },
    error: (error)=>{
      console.log(error)
    }
  })
  //console.log(csrftoken, name, description, goals, time, difficulty, exercises)
}

Views.py

def create_workout(request):
    if request.is_ajax() and request.method == 'POST':
        # print(request.POST)
        name = request.POST.get('name')
        description = request.POST.get('description')
        goals = request.POST.get('goals')
        workout_time= request.POST.get('workout_time')
        difficulty = request.POST.get('difficulty')
        ex = Exercise.objects.get(Exercise=request.POST.get('exercise'))
        exercises = Exercise.objects.get(id=ex.id)

        Workout.objects.update_or_create(
            name = name,
            exercises = exercises,
            description = description,
            goals = goals,
            workout_time = workout_time,
            difficulty = difficulty
        )


        data={
            'msg': 'created'
        }
        return JsonResponse({'data': data})
    else:
        return JsonResponse({})

Source: Python Questions

LEAVE A COMMENT