0

I am really new to django, and I'm not sure I completely understand how forms work or how to use them. I've been looking through a couple tutorials concering file-uploading, but there are a lot of different ways it seems. I'll just include the whole process from top to bottom.

I get a 500 error, because form.is_valid does not return true.

I'll be really gratefull for any help/tips :)

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

AccountModel

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

Urls (excluded some urls)

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/'
Wtower
  • 18,848
  • 11
  • 103
  • 80
Patidati
  • 1,048
  • 2
  • 12
  • 19
  • Try to print out the validation error by adding `print form.errors` to the else clause of `if form.is_valid() ... else ...` and see what's the actual error – Cheng Nov 06 '15 at 13:51
  • "
    • image
      • This field is required.
    "
    – Patidati Nov 06 '15 at 13:55
  • Post the template file for the ProfilePictureView. – Cheng Nov 06 '15 at 13:56
  • I think this is where i'm lost.. I only have the profile.html as 'frontend'. I'm guessing templates are what connects the html with the form? What I posted above is all I've got.. – Patidati Nov 06 '15 at 14:01
  • @Cheng http://pastebin.com/UFCtBS2B – Patidati Nov 06 '15 at 14:03
  • Your `profile.html` should contain a form that allows users to specify a file path to upload. When the user clicks on submit, the urls.py starts to figure out which view should it redirect the submitted form data to. Do a print out and see if request.FILES is empty. – Cheng Nov 06 '15 at 14:08
  • aah, but isn't that why I use services? ProfileHandler.js in this case – Patidati Nov 06 '15 at 14:18
  • You don't need to write any js to handle the submit. The submitted form data will be in `request.data` any uploaded files will be in `request.files` – Cheng Nov 06 '15 at 14:19
  • ""detail": "CSRF Failed: CSRF token missing or incorrect."" – Patidati Nov 06 '15 at 14:22

2 Answers2

0

You don't have a csrf token input in your form (documentation). Also, add method="post" attribute to the form.

<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>
nima
  • 6,566
  • 4
  • 45
  • 57
0

You need to add {% csrf_token %} in your form in the profile.htm file.

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

What this line will do is to add an hidden input field inside your form which contains a token. The token is submitted along with the form, and Django automatically checks the value of the token to see if this post request is actually coming from your "frontend" rather than somebody else's.

Also, add method="post":

<form method="post">
</form>
Cheng
  • 16,824
  • 23
  • 74
  • 104