MihaiMiY
MihaiMiY

Reputation: 23

Django using more than one forms in one page from same model

I want to use more than one forms in the same page from the same model.

Ok, lets take it easy.

I have Social modules that have 3 attributes (network, url and image) charfield. I've added 4 values in Social database (Facebbok, Twitter, Youtube, Pinterest)

In the settings view (settings.html) i want to have all 4 forms (for Facebook, Twitter etc.) to edit them.

Something like that:

Facebook: text input (that contains the current facebook url)

Youtube: text input (that contains the current youtube url)

etc.

So when i go to settings.html i can change, update social url for all networks.

I have something like this for General Settings module (that have 3 fields, Title, Slug, Description and 1 attribute cuz the website have 1 title, 1 slug and 1 description). For this one is pretty simple i can use get_object_or_404 because Settings module have just 1 value and i can select it.. but the problem is Social Module have more values and i want to have on my page all forms from them so i can edit how ever i want.

views.py

def settings(request):
sidebar_items = Sidebar.objects.order_by('position')
social_items = Social.objects.order_by('network')
settings = get_object_or_404(Settings, pk = 1)
if request.method == "POST":
    form_settings = SettingsForm(request.POST, instance = settings)
    if form_settings.is_valid():
        settings = form_settings.save(commit = False)
        settings.save()
        return HttpResponseRedirect('/dashboard/settings')
else:
    form_settings = SettingsForm(instance = settings)

context = {'sidebar_items' : sidebar_items, 'form_settings' : form_settings, 'social_items' : social_items}
return render(request, 'dashboard/settings.html', context)

Upvotes: 0

Views: 1425

Answers (1)

Brandon Taylor
Brandon Taylor

Reputation: 34553

Django doesn't care how many forms you want to initialize in your view. If they're for the same model, you can use a formset. Otherwise, you can initialize and create objects however you want.

Example:

def your_view(request):

    social_items = Social.objects.order_by('network')
    forms = []
    for index, social_item in enumerate(social_items):
        forms.append(SocialForm(request.POST or None, instance=social_item,
            prefix="form_{}".format(index)))

    if request.method == 'POST':
        for form in forms:
            if form.is_valid():
                form.save()

        # do whatever next

    return render(request, 'some-template.html', {'forms': forms})

You don't need three separate form tags in your template. You can submit all of the data in one post. Django will try to hydrate an instance of each model from the POST data, and return any errors if that fails.

In your template, you'll need to iterate over the form instances:

# some-template.html

<form action="." method="post" enctype="x-www-form-urlencoded">
    {% for form in forms %}
    <ol>
        <li>
            {{ form.network }}
            {{ form.network.errors }}
        </li>
        <li>
            {{ form.url }}
            {{ form.url.errors }}
        </li>
        <li>
            {{ form.image }}
            {{ form.image.errors }}
        </li>
    </ol>
    {% endfor %}

    <button type="submit">Save</button>
</form>

Upvotes: 2

Related Questions