在一个html表单中处理多个模型

时间:2015-01-17 05:15:30

标签: django django-forms django-templates django-views

用户将拥有与其特定相册相关的照片。

所以这就是模型:

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
        })

形式:

<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>

如果我只需要上传一个带有该表格的文件(照片),这样就可以了。

更新

但是,我想要做的是,显示至少三个用于将照片上传到新相册的输入:

<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>

这样做时,只会保存最后一个pform。其他两个pform被忽略。如何相应地保存所有三种形式的照片(pform)?

或者还有其他方法吗?非常感谢您的帮助!谢谢。

1 个答案:

答案 0 :(得分:4)

使用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>