I am learning django. I am attempting to create a website that logs a user's workout. The user will be able to make premade workouts.
For each workout routine, there will be a workout name and it will consist of different exercises and the number of sets per exercise. In order to achieve this, I have created a custom through model so I can associate a number of sets to each exercise for that premade workout routine.
The trouble I am having is that in order to create a workout routine I need to use the WorkoutRoutine model in order to create a WorkoutRoutine object. Then I also need to use SetAmount in order to assign an exercise associated with a number of sets to the WorkoutRoutine.
Here is my models.py:
from django.db import models
from django.contrib.auth import get_user_model
from django.core.validators import MaxValueValidator, MinValueValidator
class WorkoutRoutine(models.Model):
title = models.CharField(max_length=25)
owner = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
exercise = models.ManyToManyField(
'Exercise',
through='SetAmount',
related_name='workoutRoutines'
)
def __str__(self):
return self.title
class Exercise(models.Model):
name = models.CharField(max_length=25)
def __str__(self):
return self.name
class SetAmount(models.Model):
workout_routine = models.ForeignKey(
'WorkoutRoutine',
related_name='set_amounts',
on_delete=models.CASCADE, null=True
)
exercise = models.ForeignKey(
'Exercise',
related_name='set_amounts',
on_delete=models.SET_NULL,
null=True,
blank=True
)
set_amount = models.IntegerField(
default=0,
validators=[
MaxValueValidator(100),
MinValueValidator(0),
]
)
def __str__(self):
return str(self.set_amount)
Here is my views.py:
from django.shortcuts import render
from django.views.generic import ListView, CreateView
from .models import WorkoutRoutine
class WorkoutRoutineListView(ListView):
model = WorkoutRoutine
template_name = 'workout_routines.html'
class WorkoutCreateView(CreateView):
model = WorkoutRoutine
template_name = 'workout_creation.html'
fields = ('title','exercise',)
Is there a way I can edit WorkoutCreateView(CreateView) in order to allow what I am trying to do? Or should I be building a function to achieve what I am trying to do?
CodePudding user response:
You should override the form_valid()
method of CreateView. This is called if, well, your form is valid. Then you can create your SetAmount instance there.
def form_valid(self, form):
# Easy way to obtain the through model (aka SetAmount)
SetAmount = WorkoutRoutine.exercise.through
# Assuming the exercise is selected in the form
exercise = form.cleaned_data['exercise']
# Create a SetAmount instance with the correct workout_routine and exercise from the form
SetAmount.objects.create(
workout_routine=form.instance,
exercise=exercise,
set_amount=100 # Swole
)
return super().form_valid(form)