how to add a row from different model to current model's POST method

hi guys, I am facing a problem that is I want to add a row from a different model to the current model ( both model has same fields ) . furthermore I want a functionality to create a exercise but if you want you can add that exercise is already provided in a diff model here is the code…

this is exercise model that has preloaded exercise

class Exercise(models.Model):
    body_part = models.CharField(max_length=255)
    muscle_name = models.CharField(max_length=255)
    exercise_name = models.CharField(max_length=255)
    sets = models.CharField(max_length=255)
    reps = models.CharField(max_length=255)

    def __str__(self) -> str:
        return self.exercise_name
    
    class Meta:
        ordering = ['body_part']

workout structure model that contains exercises you have create but I want to give feature to add this exercise from above model “Exercise”

class WorkoutStructure(models.Model):
    workout = models.ForeignKey(WorkoutList, on_delete=models.CASCADE, related_name='workout_lists')
    body_part = models.CharField(max_length=255,default="", blank=True)
    muscle_name = models.CharField(max_length=255,default="", blank=True)
    exercise_name = models.CharField(max_length=255, default="", blank=True)
    sets = models.CharField(max_length=255, default="", blank=True)
    reps = models.CharField(max_length=255, default="", blank=True)

    def __str__(self) -> str:
        return self.exercise_name
    
    class Meta:
        ordering = ['body_part']

please someone help me implement this

There is nothing special or unique about this. You do this in basically the same way you assign any other value to a model.

If you need more specific assistance, we’ll need to see the view that you’re trying to do this in.

thank you for replying this is view for WorkoutStrucure

class WorkoutExerciseListView(ListCreateAPIView):
    queryset = WorkoutStructure.objects.all()
    serializer_class = WorkoutCreateSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

and this is the corresponding Serializer for it

class WorkoutCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = WorkoutStructure
        fields = ['id', 'body_part', 'muscle_name', 'exercise_name', 'sets', 'reps', 'workout']

Ahhh, you didn’t mention that DRF was involved here. Maybe one of our members more familiar with DRF can help you.

I see that you’re using a Generic view, normally this generic views are for “generic” use-cases, as the name implies. In this case you don’t have a generic case, in that case you have two options:

  • Understand the create method and maybe tweaking it to work as you intend;
  • Creating a view to only handle the post and doing it manually.

Normally if you fight the framework to do a lot of customizations you’ll end up frustrated and with a code that is hard to maintain. So my suggestion is to this on yourself, and is not that hard.

So you have two models, that are essentially the same (apart from the db-design) is pretty straight forward to handle it.
First, let’s create the “same” serializer but for the WorkoutStructure model:

# Your original serializer
class WorkoutCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = WorkoutStructure
        fields = ['id', 'body_part', 'muscle_name', 'exercise_name', 'sets', 'reps', 'workout']

# The Exercise serializer
class ExerciseCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Exercise
        fields = ['body_part', 'muscle_name', 'exercise_name', 'sets', 'reps']

Then your view:

from rest_framework import response

class WorkoutExerciseListView(ListCreateAPIView):
    queryset = WorkoutStructure.objects.all()
    serializer_class = WorkoutCreateSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        # return self.create(request, *args, **kwargs)
        # Let's write our custom create, this is basically a rewrite of the create method
        struct_srlzr = WorkoutCreateSerializer(request.data)
        exercise_srzlr = ExerciseCreateSerializer(request.data)
        struct_srlzr.is_valid(raise_exception=True)
        exercise_srlzr.is_valid(raise_exception=True)

        struct = struct_srlzr.save()
        exercise = exercise_srlzr.save()
        out_data = WorkoutCreateSerializer(instance=struct)
        return response.Response(status=201, data=out_data.data)

You can do it in other ways also, but i think this may help you get there.
Hope it helps.

[Side note]
What i like to do and helps me understand better the framework is to see the actual definitions of the methods the framework gives me (in this case self.create from the ListCreateAPIView), with that i can see the exact code that are being used to do the “magic” - in the end there’s no magic, just code. If you’re using VSCode you can put your cursor above the method and press F12, or right-click and “Go to Definition” to see the code. You may also find out that are other methods involved, and if you’re curious keep following the “trail”, you’ll learn a lot from this journey
Cheers