Create Django Form Fields with a For Loop

Viewed 140

I have 3 models:

# app/models.py


class Platform(models.Model): 
    name = models.CharField(max_length=50)

    def __str__(self): 
        return self.name

class Streamer(models.Model): 
    name = models.CharField(max_length=50)
    
    def __str__(self): 
        return self.name

class Account(models.Model): 
    name = models.CharField(max_length=50)
    streamer = models.ForeignKey(Platform, on_delete=models.CASCADE)
    platform = models.ForeignKey(Platform, on_delete=models.CASCADE)

    def __str__(self): 
        return self.name

In the Platform model, I have 3 objects (Instagram, Twitch, YouTube):

>>> from app.models import *
>>> Platform.objects.bulk_create([
... Platform(name="Instagram"),
... Platform(name="Twitch"),
... Platform(name="YouTube"),
... ])
>>>

I want to have a Streamer Creation form that:

  1. Creates a streamer object
  2. Creates an account for each platform available (all optional).

So at the end I want the form to look like this:

# app/forms.py


class StreamerForm(forms.Form):
    streamer = CharField(max_length=50)
    instagram_username = CharField(max_length=50)
    twitch_username = CharField(max_length=50)
    youtube_username = CharField(max_length=50)

but without having to manually define each platform on the username fields, something like:

# app/forms.py


class StreamerForm(forms.Form):
    streamer = CharField(max_length=50):
    for platform in platforms: 
        # somehow...
        platform_username = models.CharField(max_length=50)

What's the best way to go about doing this?

Not sure if this part is necessary to share, but this is what the view would look like:

# app/forms.py


class StreamerCreate(View):
    def get(self, request):
        form = StreamerForm()
        return render(request, 'app/streamer_create.html', {'form':form})

    def post(self, request): 
        form  = StreamerForm(request.POST)
        if form.is_valid:
            # Create the streamer
            streamer = Streamer.objects.create(name=form.cleaned_data['streamer'])
            # Create one account for each platform and assign it to the streamer
            for platform in Platform.objects.all():
                if form.cleaned_data[f'{platform.name.lower()}_username']:
                     username = form.cleaned_data[f'{platform.name.lower()}_username']
                     Account.objects.create(name=username, platform=platform, streamer=streamer)
            return redirect('home')

Couldn't find a clear duplicate that answers this question clearly, but if there is a good one that speaks well to newer Django users please feel free to share.

0 Answers
Related