baterson
@baterson
python/django

Как загрузить Изображение DjangoREST + Angular?

Привет, я пытаюсь написать простое приложение с использованием DjangoREST и Angular, использую эти технологии впервые и похоже просто не понимаю как архитектура REST должна выглядеть.
Код django:
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')]

Когда я отправляю данные через форму /api/photo во встроенном шаблоне django_rest, GET и POST работает исправно.
Когда я пытаюсь отправить файл через Angular я получаю:

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

Angular код:
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 Работает исправно и все файлы загружаются на страницу
app.controller('getController', ['$scope', '$http', function($scope, $http){
	$http.get('/api/photo/').success(function(data){
		$scope.photos = data;
	}).error(function(data) {
		$scope.photos = data;
	});
}]);

Для загрузки данных я использовал этот гайд
код из гайда:
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 код:
<div ng-controller = "myCtrl">
    <input type="file" file-model="myFile"/>
    <button ng-click="uploadFile()">upload me</button>
</div>

Пожалуйста, помогите хотя бы понять, где мне искать причину. В Angular или на сервере. Я весь день пытаюсь решить проблему загрузки файлов в Angular,а возможно проблема с REST api и я не понимаю куда копать.
  • Вопрос задан
  • 2126 просмотров
Решения вопроса 1
baterson
@baterson Автор вопроса
python/django
Проблема решена, статья про загрузку файлов
Для загрузки нужно добавить parser_classes в сериалайзер и переопределить метод perform_create
serializer.py:
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'))

Так же в app.service нужно поменять строчку загрузки файла, fd.append('file', file)
на имя указанное в модели
fd.append('img', file)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Попробуйте использовать Postman (расширение для браузера) и проверьте, что вам вернет ваш REST в ответ на запрос следующего вида, а дальше будем смотреть (Джанго не знаю :))

9a4fc4e38a234d9baa3ff7243119ae68.png

P.S. а для Angular лучше возьмите готовый модуль для загрузки файлов, как пример
Ответ написан
DrMartiner
@DrMartiner
Full-Stack WEB Developer on Django & AngualrJS
Твой путь 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: пример на Coffee Script позволит сориентироваться с readme к библиотеке
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы