django-restful-ios 使用者頭像上傳

meryin發表於2018-02-01

Django部分

Django DEMO地址 ios-swift DEMO地址

1. 軟體環境:

django ~1.11
Python 3.6.1
Anaconda 4.4.0
Mac sbulime

2. 新建專案

django-admin.py startproject django_uploadImg_userHeadChange_rest
複製程式碼

3. 新建APP

python manage.py startapp upload_test
複製程式碼

4. 新建 mySerializers.py檔案,專案構成如下

django-restful-ios 使用者頭像上傳

5. models.py

from django.db import models

class haveFunUser(models.Model):
	user_id = models.AutoField(primary_key=True)
	name = models.CharField(max_length=128)
	phone = models.CharField(max_length=11,unique=True)
	date_joined = models.DateTimeField(auto_now=True)  #DateField
	gender_choices = ((0,"男"),(1,"女"))
	sex = models.IntegerField(choices=gender_choices,default=1)
	age = models.PositiveIntegerField(default=18)
	address = models.CharField(max_length=80,null=True,blank=True)
	email = models.EmailField(null=True,blank=True)
	img = models.TextField(null=True,blank=True)
	user_type_choice=((0,"超級使用者"),(1,"普通使用者"))
	user_type = models.IntegerField(choices=user_type_choice,default=1)
	passwd = models.CharField(max_length=64)
	def __str__(self):
		return self.name,self.phone

class userHeadImage(models.Model):
    image_id = models.AutoField(primary_key=True)
    image = models.ImageField(max_length=None,upload_to='head_images',null=True, blank=True)
    uploaded_by = models.ForeignKey(haveFunUser)
複製程式碼

6. mySerializers.py

from django.contrib.auth.models import *
from rest_framework import serializers
from . import models
import time
from django.conf import settings



class ImageSerializer(serializers.ModelSerializer):
    image = serializers.ImageField(max_length=None, use_url=True) #use_url=True是否顯示完整的路徑
    def create(self, validated_data):
        data = self.context.get('request').data.dict()
        user_id = data['user_id']       
        print('xxxx=------',user_id,'xasaaaaa=---',validated_data)
        validated_data.update({'uploaded_by_id': user_id})
        return models.userHeadImage.objects.create(**validated_data)
    class Meta:
        model = models.userHeadImage
        fields = ('image_id','image')



#使用者基本資訊
class UserSerializer(serializers.ModelSerializer):
    time_join = serializers.SerializerMethodField()
    img = serializers.SerializerMethodField()
    def get_time_join(self,obj):
        t = obj.date_joined
        return t.strftime('%Y-%m-%d %X')
    def get_img(self,obj):
        image = ImageSerializer(models.userHeadImage.objects.filter(uploaded_by_id__exact=obj.user_id).first()).data
        if image:
            return image['image']
        else:
            return ''
    class Meta:
        model = models.haveFunUser
        fields = ('user_id','name', 'phone','time_join','sex','age','address','email','img','user_type','passwd')
複製程式碼

7. settings.py

註冊APP

INSTALLED_APPS = [
    'rest_framework',
    'upload_test',
]
複製程式碼

要想外網內網都能訪問需要:

ALLOWED_HOSTS = ['*']
複製程式碼

設定影象儲存的檔案路徑以及獲取影象的網路路徑

MEDIA_ROOT = os.path.join(BASE_DIR, 'image')
MEDIA_URL = '/media/'
複製程式碼

REST_FRAMEWORK設定

REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGINATE_BY': 10,
        'DEFAULT_PARSER_CLASSES': (
            'rest_framework.parsers.JSONParser',
            'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser',
            'rest_framework.parsers.FileUploadParser'
            ),
    }
複製程式碼

8. 在django_uploadImg_userHeadChange_rest下的urls.py中配置自己APP的URL檔案

from django.conf.urls import url,include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api-auth/',include('rest_framework.urls', namespace='rest_framework')),
    url(r'^haveFun/', include('upload_test.urls',namespace='haveFun')),
]+ static(settings.MEDIA_URL , document_root=settings.MEDIA_ROOT )
複製程式碼

9. views.py

#encoding:utf-8
from __future__ import unicode_literals
from django.shortcuts import render
from . import mySerializers as serializers
from upload_test import models
from django.http import HttpResponse
import json
from rest_framework  import viewsets
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import *
from rest_framework import permissions
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
from rest_framework import generics
from rest_framework import mixins
from rest_framework.views import APIView


class JSONResponse(HttpResponse):
	def __init__(self, data, **kwargs):
		content = JSONRenderer().render(data)
		kwargs['content_type'] = 'application/json'
		super(JSONResponse, self).__init__(content, **kwargs)



class imageAPI(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = models.userHeadImage.objects.all()
    serializer_class = serializers.ImageSerializer

    def post(self, request, *args, **kwargs):
        data = request.data.dict()
        user_id = data['user_id']
        m = models.userHeadImage.objects.filter(uploaded_by_id__exact=user_id)
        for model in m:
            model.image.delete()
            print(model.image)
            model.delete()
        try:
            self.create(request, *args, **kwargs)
            image = models.userHeadImage.objects.get(uploaded_by_id__exact=user_id)
            return JSONResponse({'result':serializers.ImageSerializer(image).data,'desc':'upload success'}, status=HTTP_200_OK)
        except:
            return JSONResponse({'desc':'upload faile'},status=HTTP_400_BAD_REQUEST)

class UploadViewSet(imageAPI):
    queryset = models.userHeadImage.objects.all()
    serializer_class = serializers.ImageSerializer
    parser_classes = (MultiPartParser, )    

#用於登入

class UserLoginAPIView(APIView):
   queryset = models.haveFunUser.objects.all()
   serializer_class = serializers.UserSerializer
   permission_classes = (permissions.AllowAny,)

   def post(self, request, format=None):
       data = request.data
       username = data.get('name')
       password = data.get('passwd')
       if not models.haveFunUser.objects.filter(name__exact=username):
           return JSONResponse({'desc':'使用者名稱不存在'},status=HTTP_200_OK,)
       user = models.haveFunUser.objects.get(name__exact=username)
       if user.passwd == password:
           serializer = serializers.UserSerializer(user)
           new_data = serializer.data
           print(new_data)
           # 記憶已登入使用者
           self.request.session['user_id'] = user.user_id
           self.request.session['user_name'] = user.name
           return JSONResponse({'result':serializer.data,'desc':'登陸成功'}, status=HTTP_200_OK)
       return JSONResponse( {'desc':'password error'},status=HTTP_200_OK)

#用於註冊

class UserRegisterAPIView(APIView):
   queryset = models.haveFunUser.objects.all()
   serializer_class = serializers.UserSerializer
   permission_classes = (permissions.AllowAny,)

   def post(self, request, format=None):
       data = request.data
       username = data.get('name')
       phone = data.get('phone')
       print('registrt--->',data)
       dic = {}
       if models.haveFunUser.objects.filter(name__exact=username):
           return JSONResponse({'desc':'使用者名稱已存在'},status=HTTP_400_BAD_REQUEST)
       if models.haveFunUser.objects.filter(phone__exact=phone):
           return JSONResponse({'desc':'手機號碼已存在'},status=HTTP_400_BAD_REQUEST)
       serializer = serializers.UserSerializer(data=data)
       if serializer.is_valid(raise_exception=True):
           serializer.save()
           dic['result'] = serializer.data
           dic['desc']='註冊成功'
           return JSONResponse(dic,status=HTTP_200_OK)
       return JSONResponse({'desc':serializer.errors}, status=HTTP_400_BAD_REQUEST)
       
複製程式碼

10. APP中urls.py配置

from django.conf.urls import url,include
from . import views

urlpatterns = [

    url(r'^upload_head_image$', views.UploadViewSet.as_view()),

    url(r'^register$', views.UserRegisterAPIView.as_view()),
    url(r'^login$', views.UserLoginAPIView.as_view()),

]
複製程式碼

11. 開始執行專案

 python managey makemigrations
 python manage.py migrate
 python manage.py runserver 192.168.38.127:8000
複製程式碼

192.168.38.127:8000是我電腦自己的WiFiIP,當你手機和你電腦同一WiFi就可以連線專案進行測試

ios-swift部分

1. 網路庫Alamofire

圖片上傳UploadManage.swift
import Foundation
import Alamofire

func getUserHeadImageName()->String{
   guard let my = UserInfoModel.getUserInforModel() else {
       MBProgressHUD.showError("請先登入")
       return ""
   }
   let user_id = String(describing: my.user_id!)
   let date = Date()
   let timeFormatter = DateFormatter()
   timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
   let strNowTime:String = timeFormatter.string(from: date)
   return user_id + "_head_image" + strNowTime + ".jpg"
}


//上傳圖片到伺服器
func uploadImage(imageData : Data,filename:String,url:String,blcok: @escaping ([String: Any]?) -> Void){
    MBProgressHUD.showLoading("上傳中...")
   
   let uploadURL = BaseURL + url
   guard let my = UserInfoModel.getUserInforModel() else {
       blcok(nil)
       MBProgressHUD.showError("請先登入")
       return 
   }
   let user_id = String(describing: my.user_id!)
   Alamofire.upload(
       multipartFormData: { multipartFormData in
           //採用post表單上傳
           //withName:和後臺伺服器的name要一致
           multipartFormData.append(imageData, withName: "image", fileName: filename, mimeType: "image/jpeg")
           multipartFormData.append(user_id.data(using: String.Encoding.utf8)!, withName: "user_id")
           
           
   },to: uploadURL,encodingCompletion: { encodingResult in
       switch encodingResult {
       case .success(let upload, _, _):
           upload.responseJSON { response in
               guard let result = response.result.value else {
                   blcok(nil)
                   MBProgressHUD.showError("上傳失敗")
                   return
                   
               }
               print("json:\(result)")
               guard let dict = result as? [String: Any] else {
                   blcok(nil)
                   MBProgressHUD.showError("上傳失敗")
                   return
               }
               guard let image = dict["result"] as? [String: Any] else{
                   blcok(nil)
                   MBProgressHUD.showError("上傳失敗")
                   return
                   
               }
               MBProgressHUD.showSuccess("上傳成功")
               blcok(image)
           }
           upload.uploadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
               print("圖片上傳進度: \(progress.fractionCompleted)")
           }
       case .failure(let encodingError):
           MBProgressHUD.showError(encodingError as! String)
           blcok(nil)
           return
       }
   })
}
複製程式碼
頭像上傳介面ChangHeadImageViewController.swift
import UIKit
import Photos



class ChangHeadImageViewController: UIViewController {
   let imgv = UIImageView()
   
   override func viewDidLoad() {
       super.viewDidLoad()
       self.title = "頭像"
       self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "編輯", style: .done, target: self, action: #selector(edit))
       initUI()
   }
   
   func initUI()
   {
       imgv.frame = self.view.bounds
       self.view.addSubview(imgv)
       let user = UserInfoModel.getUserInforModel()
       imgv.contentMode = .top
       imgv.mb_setImage(withUrlString: user?.img, placeholderImgName: "Ico_MCustomerCenter")
   }

   func edit()
   {
       
       let alertSheet = UIAlertController(title: "頭像編輯", message: nil, preferredStyle: .actionSheet)
       let phoneAction = UIAlertAction(title: "相簿", style: .default, handler: {action in
           self.fromAlbum(type:.photoLibrary)
       })
       let camerAction = UIAlertAction(title: "相機", style: .default, handler: { action in
           self.fromAlbum(type:.camera)
       })
       let archiveAction = UIAlertAction(title: "完成", style: .destructive, handler: {
           action in
           print(action)
       })
       alertSheet.addAction(phoneAction)
       alertSheet.addAction(camerAction)
       alertSheet.addAction(archiveAction)
       self.present(alertSheet, animated: true, completion: nil)

   }
   //選取相簿
   func fromAlbum(type:UIImagePickerControllerSourceType) {
       let photos = PHPhotoLibrary.authorizationStatus()
       if photos == .notDetermined {
           PHPhotoLibrary.requestAuthorization({status in
               if status != .authorized{
                  MBProgressHUD.showError("請在設定裡設定許可權")
                   return
               }
           })
       }
       let picker = UIImagePickerController()
       picker.delegate = self
       picker.allowsEditing = true
       picker.modalPresentationStyle = .overFullScreen
       if type == .photoLibrary
       {
           if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
               
               picker.sourceType = UIImagePickerControllerSourceType.photoLibrary
               
               self.present(picker, animated: true, completion: {
                   () -> Void in
               })
           }else{
               MBProgressHUD.showError("沒有相簿許可權")
           }
       }
       else
       {
           if UIImagePickerController.isSourceTypeAvailable(.camera){
               
               picker.sourceType = UIImagePickerControllerSourceType.camera
               self.present(picker, animated: true, completion: {
                   () -> Void in
               })
           }else
           {
               MBProgressHUD.showError("沒有相機許可權")
           }
       }
       
       
   }
   
   
}

extension  ChangHeadImageViewController:UIImagePickerControllerDelegate,UINavigationControllerDelegate
{
  @objc func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion:nil)
   }
  @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
       let imageSelected = info[UIImagePickerControllerEditedImage] as? UIImage
         picker.dismiss(animated: true, completion:nil)
       if  imageSelected != nil {
           let data = UIImageJPEGRepresentation(imageSelected!, 0.3)
           uploadImage(imageData: data!, filename:getUserHeadImageName(), url: "/haveFun/upload_head_image",blcok: { ( dict) in
               guard let image = dict!["image"] as? String else{return}
               let user = UserInfoModel.getUserInforModel()
               user?.img = image
               UserInfoModel.saveUserInforModel(user!)
               self.imgv.mb_setImage(withUrlString:user?.img, placeholderImgName: "Ico_MCustomerCenter")
               
               } )
       }
   }

}

複製程式碼

相關文章