【问题标题】:Is this the wrong logic for image uploading with django? form.is_valid = false这是用 django 上传图片的错误逻辑吗? form.is_valid = false
【发布时间】:2015-11-06 13:40:35
【问题描述】:

我真的是 django 的新手,我不确定我是否完全了解表单的工作原理或如何使用它们。我一直在浏览一些关于文件上传的教程,但看起来有很多不同的方式。我将只包括从上到下的整个过程。

我收到 500 错误,因为 form.is_valid 不返回 true。

我将非常感谢任何帮助/提示 :)

profile.html

<form role="form" enctype="multipart/form-data" ng-submit="profile.upload_picture()">
    <input id="id_image" type="file" class="" name="image" ng-model="profile.image">
    <input type="hidden" value="{{ profile.user.email }}" ng-model="profile.email">
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

ProfileController.js

function upload_picture() {
    ProfileHandler.setProfilePicture(vm.image, vm.email);
}

ProfileHandler.js

function setProfilePicture(profile_pic, email) {
    return $http.post('/api/v1/profile/picture/', {
        profile_pic: profile_pic,
            email: email
        }).then(imageSuccessFn, imageErrorFn);
    }

ProfilePictureView

class ProfilePictureView(views.APIView):
    def post(self, request):
        if request.method == 'POST':
            form = ProfileImageForm(request.POST, request.FILES)
            if form.is_valid():
                str_data = request.body.decode('utf-8')
                data = json.loads(str_data)
                email = data.get('email', None)
                acc = Account.objects.get(email=email)
                acc.model_pic = form.cleaned_data['image']
                acc.save()
                return Response({
                    'status': 'Accepted',
                    'message': 'Image uploaded.'
                }, status=status.HTTP_202_ACCEPTED)
            else:
                return Response({
                    'status': 'Internal server error',
                    'message': 'Form not valid'
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        else:
            return Response({
                'status': 'Method not allowed',
                'message': 'Only post is accepted'
            }, status=status.HTTP_405_METHOD_NOT_ALLOWED)

ProfileImageForm

class ProfileImageForm(forms.Form):
    image = forms.FileField(label='Select a profile Image')

帐户模型

class Account(AbstractBaseUser):
    ....
    image = models.ImageField(upload_to='profile_images', blank=True)
    ....

网址(部分网址除外)

urlpatterns = patterns(
    '',
    url(r'^api/v1/', include(router.urls)),
    .....,
    url(r'^api/v1/profile/picture/$', ProfilePictureView.as_view(), name='profile'),
    url('^.*$', IndexView.as_view(), name='index'),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_URL);

Settings.py

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

【问题讨论】:

  • 尝试通过在if form.is_valid() ... else ... 的else 子句中添加print form.errors 来打印出验证错误,看看实际错误是什么
  • "
    • image
      • 此字段为必填项。
    • "
  • 发布 ProfilePictureView 的模板文件。
  • 我认为这是我迷路的地方。我只有 profile.html 作为“前端”。我猜模板是将html与表单连接起来的东西?我上面发布的就是我所拥有的一切..

标签: django django-models django-forms django-file-upload


【解决方案1】:

您的表单中没有 csrf 令牌输入 (documentation)。另外,在表单中添加method="post" 属性。

<form role="form" method="post" enctype="multipart/form-data" ng-submit="profile.upload_picture()">
    {% csrf_token %}
    <input id="id_image" type="file" class="" name="image" ng-model="profile.image">
    <input type="hidden" value="{{ profile.user.email }}" ng-model="profile.email">
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

【讨论】:

    【解决方案2】:

    您需要在 profile.htm 文件中的表单中添加 {% csrf_token %}。

    <form>
        {% csrf_token %}
    </form>
    

    这一行的作用是在表单中添加一个隐藏的输入字段,其中包含一个标记。令牌与表单一起提交,Django 会自动检查令牌的值,以查看此 post 请求是否实际上来自您的“前端”而不是其他人的。

    另外,添加method="post":

    <form method="post">
    </form>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-06
      • 2020-04-06
      • 2014-01-10
      • 2020-05-09
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      相关资源
      最近更新 更多