Django: Prepopulate Formset with ManyToMany Relationship and additional Fields

Viewed 27

I have two models with an M2M relationship and extra fields: A menu is a compilation of many courses (i.e. dishes). The M2M relationship is reflected in MenuItem class/table. MenuItem has two additional fields: course_type (i.e. starter, appetizer, etc.) and course_position (to keep track of the position).

models.py

class Menu(models.Model):
    creator = models.ForeignKey(User, related_name='creator_id_menu', on_delete=models.PROTECT)

    menu_name = models.CharField(max_length=100, default='', verbose_name=_('menu name'), help_text=_('i.e. saturday night fajita night'))
    menu_description = models.CharField(max_length=300, default='', verbose_name=_('menu description'), help_text=_('this menu will blow your mind...'))
    menu_item = models.ManyToManyField(Course, through='MenuItem', blank=True)
    

class Course(models.Model):
    creator = models.ForeignKey(User, related_name='creator_id_course', on_delete=models.PROTECT)

    course_name = models.CharField(max_length=100, help_text=_('give your creation a nice name!'))
    course_description = models.CharField(max_length=300, default='', verbose_name=_('course description'), help_text=_('give your creation a brief description!'))

    
class MenuItem(models.Model):    
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name=_('menu name'))
    course = models.ForeignKey(Course, on_delete=models.PROTECT, verbose_name=_('course name'))
    course_type = models.CharField(choices=CourseType.choices, max_length=3, verbose_name=_('course type'))
    course_position = models.PositiveSmallIntegerField(verbose_name=_('course position'))

forms.py

class CourseForm(forms.ModelForm):
    course_type = forms.ChoiceField(choices=MenuItem.CourseType.choices)
    course_description = forms.Textarea()

    class Meta:
        model = Course
        fields = ['course_name', 'course_description']   

CourseFormset = modelformset_factory(Course,
                                     form=CourseForm,
                                     extra=0)

I can prepopulating the ModelFormset with the data from Course, but don't know, how to correctly access the MenuItem instance. That is why, my views.py misses the request.POST processing.

views.py

def update_menu_with_courses(request, pk):    
    context = {}
    menu_instance = Menu.objects.get(id=pk)

    # initializing forms
    menu_form = MenuCreationForm(request.POST or None, instance=menu_instance)
    menu_items = menu_instance.menu_item.all()

    course_formset = CourseFormset(request.POST or None, queryset=menu_items, prefix='course')

    context['menu_form'] = menu_form
    context['course_formset'] = course_formset

    return render(request, 'menus/update_menu_courses.html', context)

My question:

  • How do I prepopulate a ModelFormset with M2M relationship and extra fields in the M2M Table.
  • How do I update the M2M extra fields in MenuItem
0 Answers
Related