Processing multiple model forms in one html form

The user will have photos that will be associated with their particular album.

So this was the model for this:

class Album(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
    update = models.DateTimeField(auto_now_add=False, auto_now=True)

class Photo(models.Model):
    photo_privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
    user = models.ForeignKey(User)
    caption = models.TextField()
    image = models.ImageField(upload_to=get_upload_file_name)
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)

Views.py:

def create_album(request, user_name):
    user = User.objects.get(username=unquote(user_name))
    if request.method=='POST':
        pform = AlbumPhotoForm(request.POST, request.FILES)
        aform = AlbumForm(request.POST)
        p_valid = pform.is_valid()
        a_valid = aform.is_valid()
        if p_valid and a_valid:
            photo = pform.save(commit=False)
            album = aform.save(commit=False)
            photo.user = user
            album.user = user
            album.save()
            photo.album = album
            photo.save()
            return HttpResponseRedirect('/'+user.username+'/photos')
        else:
            return render(request, 'create_album.html',{
                'pform':pform,
                'aform':aform
            })
    else:
        pform = AlbumPhotoForm()
        aform = AlbumForm()
        return render(request, 'create_album.html', {
            'pform':pform,
            'aform':aform
        })

And the form:

<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
    {{ aform.as_p }}

    {{ pform.as_p }}
    <input type="submit" value="Create and Upload Album"/>
</form>

This works great if I need to upload only one file (photo) with this form.

Update:

However, what I want to do is show a minimum of three inputs for uploading photos to a new album:

<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
    {{ aform.as_p }}

    {{ pform.as_p }}
    {{ pform.as_p }}
    {{ pform.as_p }}
    <input type="submit" value="Create and Upload Album"/>
</form>

However, only the last one is saved pform. And the other two are pformignored. How can I save all three forms of photography ( pform) accordingly?

Or is there another way? Your help will be greatly appreciated! Thank.

+4
source share
1 answer

formsets. , :

from django.forms.models import formset_factory

PhotoFormSet = formset_factory(AlbumPhotoForm, can_delete=False,
                               min_num=1, validate_min=True,
                               max_num=3, validate_max=True,
                               extra=3)

def create_album(request, user_name):
    user = User.objects.get(username=unquote(user_name))
    if request.method=='POST':
        form = AlbumForm(request.POST)
        formset = PhotoFormSet(request.POST, request.FILES)
        if all([form.is_valid(), formset.is_valid()]):
            album = form.save(commit=False)
            album.user = user
            album.save()
            for photo_form in formset:
                if photo_form.cleaned_data:
                    photo = photo_form.save(commit=False)
                    photo.album = album
                    photo.user = user
                    photo.save()
            return redirect('/%s/photos' % user.username )
    else:
        form = AlbumForm()
        formset = PhotoFormSet()
    return render(request, 'create_album.html',
                  {'form': form, 'formset': formset})

:

<form action="." method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}    
    <table>
        {{ formset }}
    </table>    
    <input type="submit" value="Create and Upload Album"/>
</form>
+4

All Articles