Search code examples
pythondjangomany-to-manydjango-intermediate-table

Django: How do I create a view to update multiple records on an intermediate model with a Many-to-Many-through relationship?


I am a beginner to Django, and am creating an RSVP site to handle multiple events and keep track of guests to those events. I have a model for Guest, for Event, and an intermediate model for GuestEvent. I would like a page to loop through every GuestEvent for a Guest and allow me to update the attending, adults, and children fields in GuestEvent. I will never need to create or delete these fields through the front-end.
I am currently trying to use the class-based UpdateView, but could easily switch to a different view. I've tried to use django-betterforms and django-extra-views, but didn't have any luck with either. I've also made a few attempts at following tutorials for formsets and inline formsets with no success. My models look like this:

class Event(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True)
    date = models.DateTimeField('event date')
    guests = models.ManyToManyField('Guest', through='GuestEvent')

class Guest(models.Model):
    first_name = models.CharField(max_length=45, null=True, blank=True)
    last_name = models.CharField(max_length=45, null=True, blank=True)
    events = models.ManyToManyField('Event', through='GuestEvent')

class GuestEvent(models.Model):
    guest = models.ForeignKey('Guest', related_name='guests')
    event = models.ForeignKey('Event', related_name='events')
    attending = models.NullBooleanField()
    adults = models.IntegerField(null=True, blank=True)
    children = models.IntegerField(null=True, blank=True)

What would be the best way to get these intermediate records in some sort of update view?


Solution

  • I think I have this mostly working now with Django-Extra-Views. My view looks like this:

    class GuestEventInline(InlineFormSet):
        model = GuestEvent
        fields = [ 'attending', 'adults', 'children' ]
        extra = 0
        can_delete=False
    
    class Invite2View(UpdateWithInlinesView):
        template_name = "weddings/invite2.html"
        model = Guest
        inlines = [ GuestEventInline ]
    

    And my template looks like this:

    <form action="" method="post" class="form-horizontal">
        {% csrf_token %}
        {{ form }}        
        {% for formset in inlines %}
            {{ formset.id }}
            {{ formset.management_form}}
            {%for subform in formset%}
                <h4>{{ subform.instance.event }}</h4></a>
                {{ subform.as_p }}
            {% endfor %}
        {% endfor %}
        {% buttons submit='Save' %}{% endbuttons %}
    </form>