B
B
baterson2016-03-06 21:36:17
Angular
baterson, 2016-03-06 21:36:17

How to load DjangoREST + Angular Image?

Hi, I'm trying to write a simple application using DjangoREST and Angular, this is my first time using these technologies, and I just don't seem to understand what a REST architecture should look like.
django code:
models.py:

class Photo(models.Model):

  img = models.ImageField(upload_to='photos/', max_length=254)
  text = models.CharField(max_length=254, blank=True)

serializers.py:
class PhotoSerializer(serializers.ModelSerializer):

  class Meta:
    model = Photo
    fields = ('img','text')

views.py:
class PhotoViewSet(viewsets.ModelViewSet):
  
  queryset = Photo.objects.all()
  serializer_class = PhotoSerializer

photo_router = DefaultRouter()
photo_router.register(r'photo', PhotoViewSet)

URLs.py:
urlpatterns = [
    url(r'^api/', include(photo_router.urls)),
    url(r'^$', index, name='index')]

When I submit data via the /api/photo form in the built-in django_rest template, GET and POST work properly.
When I try to send a file through Angular I get:

POST 127.0.0.1:8000/api/photo 400 (Bad Request)
in response:
img: ["No file was submitted."]

Angular code:
app.js:
var app = angular.module('myApp', ['ngRoute', 'angularFileUpload']);
app.config(function ($routeProvider) {
  
  $routeProvider
      .when('/', {
      	templateUrl: 'http://127.0.0.1:8000/static/js/angular/templates/home.html'
      })
});
app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

get_controller.js Works fine and all files are loaded on the page
app.controller('getController', ['$scope', '$http', function($scope, $http){
  $http.get('/api/photo/').success(function(data){
    $scope.photos = data;
  }).error(function(data) {
    $scope.photos = data;
  });
}]);

To load the data, I used this guide
code from the guide:
app.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;
            
            element.bind('change', function(){
                scope.$apply(function(){
                    modelSetter(scope, element[0].files[0]);
                });
            });
        }
    };
}]);
app.service('fileUpload', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, uploadUrl){
        var fd = new FormData();
        fd.append('file', file);
        $http.post(uploadUrl, fd, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
        .success(function(){
        })
        .error(function(){
        });
    }
}]);
app.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
    
    $scope.uploadFile = function(){
        var file = $scope.myFile;
        console.log('file is ' );
        console.dir(file);
        var uploadUrl = "/api/photo/";
        fileUpload.uploadFileToUrl(file, uploadUrl);
    };
    
}]);

html code:
<div ng-controller = "myCtrl">
    <input type="file" file-model="myFile"/>
    <button ng-click="uploadFile()">upload me</button>
</div>

Please, help at least to understand where to me to search for the reason. In Angular or on the server. I've been trying all day to solve the problem of uploading files in Angular, and maybe a problem with the REST api and I don't understand where to dig.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
B
baterson, 2016-03-10
@baterson

Problem solved, article about uploading files
To upload, you need to add parser_classesto the serializer and override the perform_create
serializer.py method:

from rest_framework.parsers import MultiPartParser, FormParser

class PhotoViewSet(viewsets.ModelViewSet):

    queryset = Photo.objects.all()
    serializer_class = PhotoSerializer
    parser_classes = (MultiPartParser, FormParser,)

    def perform_create(self, serializer):
        serializer.save(img=self.request.data.get('img'))

Also in app.serviceyou need to change the file download line fd.append('file', file)
to the name specified in the model
fd.append('img', file)

V
Vladislav Yandimirkin, 2016-03-07
@vlaad360

Try using Postman (browser extension) and check what your REST will return in response to a request of the following form, and then we will look (I don’t know Django :))
PS and for Angular it’s better to take a ready-made module for uploading files, as an example

A
Alexey Kuzmin, 2016-03-07
@DrMartiner

Your path is ng-file-upload

$scope.choiceFile = () ->
    partsName = $scope.file.name.split('.')
    partsName.pop()
    $scope.file.humanName = partsName.join('.')
    
    $scope.file = _.extend $scope.file,
        progress: 0
        isUploading: false
        isError: false
        isComplete: false

$scope.uploadFile = (file) ->
    file.isUploading = true

    Upload.upload(
        url: '/api/file/'
        data:
            file: file
            param1: 1
            param2: 2
    ).then( (resp) ->
        file.isComplete = true
        console.log "успешно загружен #{file.name}"
    , (resp) ->
        file.isError = true
        console.log "Ошибка при загрузке #{file.name}"
    , (evt) ->
        file.progress = parseInt(100.0 * evt.loaded / evt.total)
    )

<button ngf-select
        class="btn btn-info hidden-lg hidden-md"
        accept="*/*"
        ngf-pattern="*/*"
        ngf-change="choiceFile()"
        ng-model="file">
    Choice to upload
</button>

PS: an example on Coffee Script will help you navigate the readme to the library

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question