def arbitrary_image():
'''
작성자:장소은
내용: arbitrary_image()함수와 BytesIO를 사용하여 50x50픽셀의 임시 이미지(png형식) 생성
작성일:2023.06.13
'''
size = (50, 50)
image = Image.new("RGBA", size)
temp_img = BytesIO()
image.save(temp_img, format="PNG")
temp_img.name = "image.png"
temp_img.seek(0)
return temp_img
class ProductTest(APITestCase):
'''
작성자: 장소은
내용: 일반유저가 상품 post 했을 때, admin유저가 post했을 때 testcode 작성
다중이미지 업로드 기능 업데이트
작성일: 2023.06.07
업데이트: 2023.06.23
'''
@classmethod
def setUpTestData(cls):
date = timezone.now() + timedelta(seconds=random.randint(0, 86400))
cls.user_data = {
"email": "test@google.com",
"username": "testuser",
"password": "Xptmxm123@456"
}
cls.user = User.objects.create_user(**cls.user_data)
cls.admin = User.objects.create_superuser(
email="adminuser@test.com", username="관리자소은", password="Xptmxm123@456")
cls.admin_data = {"email": "adminuser@test.com",
"password": "Xptmxm123@456"}
cls.faker = Faker()
cls.category_data = {
'category_name': "카테고리",
'category_number': 1
}
cls.category = ShopCategory.objects.create(**cls.category_data)
cls.product_data = {
'product_name': "상품",
'product_desc': "테스트",
'category': cls.category.id,
'product_date': date,
'product_price': 10000,
'product_stock': 123,
"images": [
{
"id": 1,
"product": 1,
"image_file": ""
}]
}
image_file = arbitrary_image()
cls.product_data["images"][0]["image_file"] = image_file
def setUp(self):
self.admin_access_token = self.client.post(
reverse('log_in'), self.admin_data).data['access']
self.access_token = self.client.post(
reverse('log_in'), self.user_data).data['access']
def test_user_post_product(self):
image_file = arbitrary_image()
self.product_data["images"][0]["image_file"] = image_file
self.product_data["uploaded_images"] = [image_file]
url = reverse("product_view", kwargs={"category_id": self.category.id})
response = self.client.post(
path=url,
data=self.product_data,
HTTP_AUTHORIZATION=f"Bearer {self.admin_access_token}",
)
print(response.data)
self.assertEqual(response.status_code, 201)
테스트코드 처음에는 이미지업로드 기능없이 작성했다가 나중에 다중이미지 업로드 기능을 추가해서
업데이트 했다.. 배포 시 내 테스트코드가 fail이 되어서 1시간만에 헐레벌떡 작성했음..
arbitrary_image 함수로 임시 이미지 생성(50x50크기)하고 BytesIO객체인 temp_img를 사용해서 PNG형식의 이미지를 생성함
이미지를 읽는 방법은 OpenCV를 사용해서 읽거나, PIL를 이용해서 읽거나, 이미지 파일을 Binary 형태로 읽은 다음 ( = byte 단위로 읽는다는 의미 ) jpg로 decoding하는 방법이 있다.
https://ballentain.tistory.com/50 (참고)
#1. 첫 번째로 PIL 라이브러리의 Image 모듈을 사용하여 50x50 크기의 RGBA 포맷의 임시 이미지를 생성. 이 때, tempfile.NamedTemporaryFile 함수를 사용하여 임시 파일을 만들고, 이미지를 해당 임시 파일에 저장하는 식. 임시 파일의 경로를 반환하는 함수다.
def arbitrary_image():
size = (50, 50)
image = Image.new("RGBA", size)
temp_img = tempfile.NamedTemporaryFile(suffix='.png')
image.save(temp_img, "png")
temp_img.seek(0)
return temp_img.name
테스트 fail Error 내용은 다음과 같았음
.{'uploaded_images': {0: [ErrorDetail(string='제출된 데이터는 파일이 아닙니다. 제출된 서식의 인코딩 형식을 확인하세요.', code='invalid')]}}
제출된 데이터가 유효한 파일이 아니라고 떴다. 왜냐면 얘는 생성된 임시파일의 경로를 반환하는 함수라서 상품 데이터에 할당된 값이 임시 이미지 파일의 경로였고 이미지 데이터 자체는 요청에 전달되지 않아서 그랬던 것! 테스트코드에서는 데이터를 직접 할당 해줘야해서 다른 방법을 찾았음
#2. BytesIO 객체를 사용하여 이미지를 버퍼메모리에 저장하고 이미지를 temp_img에 저장한 후(temp_img는 임시 메모리 버퍼를 가리키는 파일 객체), temp_img의 이름을 "image.png"으로 했다. 마지막으로 temp_img 반환한다. 이미지를 PNG 형식으로 버퍼에 저장한 것
def arbitrary_image():
size = (50, 50)
image = Image.new("RGBA", size) #Image 모듈을 사용하여 RGBA 포맷의 빈 이미지를 생성
temp_img = BytesIO()
image.save(temp_img, format="PNG") #BytesIO 객체를 사용해서 이미지 PNG 형식으로 메모리에 저장
temp_img.name = "image.png"
temp_img.seek(0) #파일 포인터를 이미지의 시작 위치로 이동
return temp_img
따라서 첫 번째 함수는 파일 시스템에 임시 이미지 파일을 생성하고 파일 경로를 반환하고, 두 번째 함수는 메모리에 임시 이미지를 생성하고 BytesIO 객체를 반환
'내일배움캠프 > 내일배움캠프 TIL' 카테고리의 다른 글
내일배움캠프 TIL 69일차 - 예외처리 해결 (0) | 2023.06.16 |
---|---|
내일배움캠프 TIL 68일차 - 코드 개선하기 (리액트, url통일의 중요성) (0) | 2023.06.16 |
내일배움캠프 66일차 TIL - DRF 설정 및 권한 오류 (0) | 2023.06.13 |
내일배움캠프 65일차 TIL - 리액트로 프론트 구현하기 (1) | 2023.06.11 |
내일배움캠프 64일차 TIL - 카카오 로그인.. (0) | 2023.06.11 |