Django Form Label for Many-to-Many with Extra Fields

I'm working on a Django application at work that has several Many-to-Many relationships that have extra fields attached to them. Setting this up using the "through" parameter on the field definition is described in the Django documentation.

My trouble came in when it came time to render this information out to the user in a form so they could update the extra fields.  From the user's perspective the relationship can't be changed, but the extra fields could be.

Extending Django's example usage about band membership, if the user were viewing the information for "The Beatles" and including a formset for all band members the form would normally render something like this:

Group Name: The Beatles
Members:
    Group: The Beatles
    Person: Ringo Starr
    Date Joined: 14 August 1962
    -
    Group: The Beatles
    Person: John Lennon
    Date Joined: 01 August 1960
    -
    [etc.]

But this is a little obtuse if the purpose of the form is to allow the user to edit the "Date Joined" value for each band member.  We can whittle the form down by telling the formset to only render the "Date Joined" field [by passing fields=('date_joined',) to modelformset_factory], but then we get this:

Group Name: The Beatles
Members:
    Date Joined: 14 August 1962
    -
    Date Joined: 01 August 1960
    -
    [etc.]

Now we can't tell to which person each date applies.

Adjusting the form so that the label "Date Joined" was instead the appropriate band members name seems like such a simple thing to change.  But I didn't want to hand-write the form as it was already being automatically built and rendered for me using using modelformset_factory and Crispy-Forms.

It took me most of a day to figure it out and in the end it was pretty simple.  I only need to implement a custom Form that overrides the constructor and sets the label using the object instance before it gets thrown away:

class MembershipForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MembershipForm, self).__init__(*args, **kwargs)
        if kwargs['instance'] and kwargs['instance'].person:
            self.fields['date_joined'].label = kwargs['instance'].person.name
        else:
            self.fields['date_joined'].label = 'No Person'
    class Meta:
        model = Membership
        fields = ['date_joined']

And now our output looks something like:

Group Name: The Beatles
Members:
    Ringo Starr: 14 August 1962
    -
    John Lennon: 01 August 1960
    -
    [etc.]

Since it took me most of a day to figure this out, and I couldn't find anything specifically addressing this on the Internet, I wrote this up so hopefully the next person (or me in the future once I've forgotten this) will have an easier time figuring it out.

Christmas Break

Okay, the first thing to know about our break is that we've been sick almost the entire time. Heather threw up on Christmas Eve, and Corinne started a fever on Christmas afternoon. But Heather was mostly fine after throwing up, and Corinne's fever cleared up after a day. After that, it was basically just a cold for each of them: congestion, coughing, runny noses...you know, the usual. Nothing too dramatic. And there were plenty of up times in between the periods of misery.

(Also, a lot of these pictures are not great. They're mostly candid shots of the girls in their natural states of frenzy, which lends itself to blurriness. But I wanted to get them blogged anyway.)

We've had some fun playing with different arrangements of the fort (I learned that blocking the TV is not ideal, but they found a way around it regardless):

Heather gave Kyle Wii Sports Resort for Christmas. I think he's played it for a couple of minutes so far, but she's dedicated quite a bit of time to it:

By the 28th, this kid was not looking great. She was snotty and eye-goopy and coughing and all-around yucky. Her mood was a bit improved, though.

We had made a date to go to the zoo with the Spencers on the 29th, and we figured the girls were doing pretty good, health-wise. Heather seemed to be mostly recovered from her cold, and while Corinne was still a bit yicky, she was going to be in the stroller most of the time anyway. And we knew everybody needed to get out of the house, so off we went!

Liam, Heather, and Emma

The goats are always a hit.

The zoo was Thursday. Kyle spent Friday-Sunday at death's door. I was also sick, but not as bad. (My biggest issue was the migraines flared by the congestion.) Aaaand the girls got worse again. New Year's Eve was Heather's turn to spike a fever, so we didn't do any special festivities that night.

Corinne is currently obsessed with moving her food to other containers. Also, practicing her spoon technique.

Heather comes by her bookworm tendencies honestly, at least. I love it!
Trains, yo! And tangrams!

January 2nd, we got the girls in to see the doctor. Corinne's fever was gone by then, but this virus was just dragging on forever. Both girls were still super snotty and coughing and lethargic, though Heather was showing real signs of recovery. Corinne was diagnosed with the first ear infection either of the girls have had. Very special! So she started antibiotics and started improving very quickly.

I don't know if it's clear what Corinne is doing here, but it's one of her current passions: feeding the critters.

Corinne loves pillow corners MORE THAN LIFE.

Wednesday morning, Heather was bopping around, happy as a lark. That night, she crashed pretty hard. Thursday afternoon, she had a fever. Thursday night, she had a coughing fit so long and hard she was vomiting and I had to call the nurse line for suggestions to make it stop so she could eat (pro tip: there are basically none).

So this was us back at the doctor's office again on Friday, where Heather was diagnosed with an ear infection. Same ear as Corinne, even! The doc pointed out that that's one thing they really didn't need to share.

Both girls are doing much better now. For reals, I think. [fingers crossed!] Heather still wakes up very congested, and she didn't go to church this morning. (Actually, none of us went to church on Christmas or New Year's Day. And Kyle missed 2 full days and 2 half days of work this last week. This illness has been a beast!)

I'm hopeful that Heather will be able to go to school tomorrow, but I'm not 100% certain it'll be a great experience if she does. I'm envisioning her coughing for the first 2 hours and crying/screaming for the rest because she's worn out. But she'll be devastated if she has to stay home. So I guess we'll see how she is in the morning!

Coloring this afternoon.