[Django] Resolve Error: get() returned more than one SomeModel -- it returned 6! 오류 해결하기 개발 삽질이야기

MultipleObjectsReturned at /some/url

get() returned more than one SomeModel -- it returned 6!

Django 개발을 하다가 위와같은 오류를 보았다면 필시,
Model 간의 Many to one relationship 을 확인해 보아야 한다.

Model A : Model B = 1 : N
의 관계를 가져야 한다고 했을때,

models.ForeignKey(...) 코드를 어떤 모델에 넣어야 할까?
정답은!
.
.
.
N 에 해당하는 Model B 이다.

위의 에러는 ForeignKey 선언을 1 에 해당하는 Model A 에 넣어놓은 상태에서 아래와 같은 코드를 사용했을때 나타난다.

<에러 재현>
class B(models.Model):    
# some codes ...
a_id = models.IntegerField()

class A(models.Model):
# some codes ...
b_objects = models.ForeignKey(B, db_column='id', to_field='a_id')

# A model 객체 1개만 불러온뒤, 그에 연결된 B 모델 객체들을 출력
a_obj = A.objects.first()
print(a_obj.b_objects) # <-- 불러온 A 모델 객체가 B 모델의 객체 6개를 가져올 경우, 여기서 에러가 남
<정상 코드>

class A(models.Model):
# some codes ...

class B(models.Model):
# some codes ...
a_obj = models.ForeignKey(A, db_column='a_id', related_name='b_objects')


# A model 객체 1개만 불러온뒤, 그에 연결된 B 모델 객체들을 출력
a_obj = A.objects.first()
print(a_obj.b_objects) # <-- B Model 에 있는 related_name 을 사용하여 객체들을 불러옴 에러 안남

<요약 & 결론>

One-to-many 관계를 Django ORM 으로 구현하고자 할때는,

왠만하면 many 에 해당하는 모델에 ForeignKey() 를 넣도록 하자.

related_name 속성을 잘만 이용한다면, 편하게 one 으로부터 many 모델객체를 불러올 수 있다.

여기서 주의할점은, related_name 을 사용한 파일에서 many 에 해당하는 모델을 import 하고 있어야 한다는것 ! ! !
만약에 이를 빠뜨리면 해당 필드가 없다는 오류가 뜰것이다.

[Django] ContentType Framework app_label 업데이트 전 알아두어야 할것 개발 삽질이야기

Django 에는...  content_type framework 라 하여,
모델을 정의할때 단일 객가 여러 다른 모델과 Generic 하게 Relation을 가질 수 있도록 하는 기능이 있다.
즉, 국경을 뛰어넘는 멀티 Relation !!! 이 가능한.. 뭐 그런게 있음.

그런데 이때, 그 relation을 걸수 있도록 해당 모델의 정보를 기록하는 테이블이
django_content_type

여기에 app_label 이라는 필드가 있는데, 이 값은 해당 모델의 코드가 위치한 django application 명을 의미하고.
model 이라는 필드는 테이블 명을 의미한다.

django 가 처음 구동 될 시, 이 django_content_type 테이블의 app_label 과 model 필드의 정보에 근거하여
모든 모델의 generic relation 그래프?를 초기화 한다.

한번 웹서버가 구동된 이후에는 django_content_type 값을 업데이트 하여도,

서비스에 반영되진 않는다.


그러므로 문제가 되는것이 만일 Generic Relation 에 사용되는 모델 코드의 위치의 application 변경이 이루어 진다면!!!
프로젝트의 리얼 배포를 앞두고 아래의 순서를 반드시 지켜야 한다.

1. django_content_type 에 날릴 write query 실행
2. 코드 배포

-----------------------

이글을 쓴 본인은
코드 배포 > django_content_type 데이터 update 
순으로 배포를 진행했다가 뒤늦게 깨닫고 화들짝 놀라 다시 uwsgi 를 restart 하였다.

그리고, 앞으로는 이 실수를 반복하지 않기위해 이렇게... 별것도 아닌것 같아 보이는
포스팅을... 쓴 것이다.
( 절대 별것이다 ! ! ! ! )

여러분은 처음부터 실수 안하시길!!!


[Slack Tip] macOS Sierra에서 원화(₩) 대신 백 쿼트(`) 입력하기 잡다한 지식들

백쿼트(`) 는 슬랙 에서 꽤 유용하게 쓰이는 문자열이다.

그런데 요놈이 mac sierra 부터 에서 원화 문자열로 출력되는바람에 골치를 썩인다는 점..
그래서 이래저래 방법을 찾다가 아래 가이드라인을 따라해서 해결햇다. ㅋㅋㅋ



-----------------------------------------------------------------

요점만 간단히 요약하면 아래와 같음

  1. ~/Library 폴더로 이동해서 KeyBindings 폴더를 추가한다.
  2. ~/Library/KeyBindings 폴더에 DefaultkeyBinding.dict 파일을 만든다.
  3. DefaultkeyBinding.dict 파일에 아래의 코드를 추가한다.
      "" = ("insertText:", "`");  
}




[여행] 리스본에서 한국가는 길: 구입한 Taxfree 제품에 대한 Tax Refund 받기 잡다한 지식들

얼마전에 스페인 + 리스본 여행을 다녀왔는데,,,
Tax refund 관련하여 어려움을 겪은게 좀 있어서.. 
한번 끄적여 봅니다. ㅎㅎ

스페인 + 포르투갈에서 구입한 tax free 제품의 리펀을 받기위해 하도 삽질을 많이 해서.. ㅋㅋ
그냥 다른분들은 그런 일 없으시길 바라며.. 적습니다.

일단, 급하신 분들을 위해 결론만 말한다면,

Tax refund 는 해외에서 물건 구입시 영수증상품을 잘 챙겨놓았다가 
마지막 한국으로 돌아오는 길의 첫번째 공항에서 한꺼번에 영수증 stamp 받기 + 환불 받기 를 잘 하시면 됩니다

그럼 자세한 내용 start...
---------------------------------------------------


이 글은 리스본 에서 곧바로 한국으로 되돌아 가는 (중간에 경유 포함) 여행자들 중

Tax free 물품을 가지고 있는 사람들 이 Tax refund 을 받기 쉽도록 이해를 돕고 그 방법을 알려주는 글이다.


<Tax Free, Tax Refund 대체 뭐죠 ??>

해외로 여행을 가서 구입하게되는 모든 물품은 주로 거기서 사용한다기 보다 우리나라로 가지고 돌아오기 마련이다.
즉, 해외에서 구입하지만 사용은 우리나라에서 하게되는 것 !!!
모든 물건은 판매할때 그 나라에서만 부과하는 세금이 따로 붙어서 가격이 결정되는데, 이 붙는 세금을 되돌려 받고자 하는 것이다.

즉, 예를 들어 내가 일본에서 세금을 붙여 판매한 물건을 삿다고 치자.
그런데 난 일본사람도 아니고 거기서 그 물건을 쓸것도 아닌데 굳이 비싸게 그나라 세금까지 내어줄 수 없다는 것이다.!!!
그러니,,, 한국 되돌아오는길에.. 내가 물건사면서 추가로 낸 세금 돌리도!!! 하는 것이 택스 리펀인 것이다.

그러나 ... 우리나라로 가지고 들어오면 우리나라 세금이 또 우릴 기다리고 있쥐...
그게 바로 공항에서 입국할때 작성하는 관세 신고서가 되겠다 ㅋㅋㅋ

그 있지 않습니까.. 가끔 얌체 직구 사재기 하는 분들 공항 나오다 걸려서 캐리어 까발려지고 벌금 팍팍 먹는 그거...

그럼 왜 택스프리 하는지에 대한 설명은 여튼 여기까지...


<리스본에서 Tax Refund 는 어디서? 어떻게? 받을 수 있나>


1. 여행 국가 내, 지정 TaxRefund 영업점

- 어느 나라이던, 공항이 아닌 도시 특정 지점에서 (주로 번화가) 택스리펀 서비스를 하는 곳을 찾을 수 있다.
   (리스본의 경우, .Centro Colombo Shopping Centre 혹은 plaza de figueira 근방에 택스 리펀하는 곳이 있다)

- 이곳에 가게되면 신용카드(벌금 부과용) 정보, 여권, Taxfree 제품 구입 영수증 을 확인한뒤 Tax Refund 를 해준다.

- 여기서 주의할점 !! 
   1. 포르투갈에서 구입한 물품에 대해 지불한 세금만 돌려받을 수 있다...
   2. 여기서 택스리펀을 받았다 치더라도 공항에서 택스 리펀 받은 물품들에 대한 신고+영수증 스탬프 는 따로 받아야 한다.

- 즉 한마디로 줄이면... 택스리펀을 중간에 받는건 맞는데 공항에서의 택스리펀 신고 절차가 줄어드는 건 아니라는거...
   그러므로.... 택스리펀 받을 금액이 크고, 급전이 필요한게 아니라면 굳이 이런 피곤한 짓을 할 이유가 없다.


2. 공항 면세 구역의 TaxRefund 영업점

- 한국으로 향하는 항공 여정의 출발점인 경유에 상관없이 첫번째 공항에서 Tax 리펀을 받게 된다.
   뭐... 경유가 포함된경우, 첫번째 공항에서 화물을 부치면 마지막공항까지 자동으로 화물은 이동되기 때문에 뭐 당연한 이야기 이지만;; ㅋ

- 택스리펀을 받는 방법은 아래의 2가지 경우가 있을 수 있다.

첫번째, Tax Free 제품을 위탁 수하물(=Checked Baggage) 로 가지고 갈 경우, (= 화물로 부치는 경우)

비행기 티켓을 Check out 하기 전에 미리 customer taxfree 섹션에서 화물에 넣을 제품을 확인시켜주고 영수증에 stamp 를 받는다.
(Tip.  customer taxfree 섹션이 어딘지 모른다면 공항 또는 항공사 직원처럼 생긴분에게 Taxfree ?? no carry on !! 이라고 물어보면 알려줄 것이다.)

> 스탬프 받은 영수증은 잘 소지품으로 챙긴뒤, 화물을 Check In 한다.

> 출국수속을 밟아 공항 검색대를 지나 면세 Zone 까지 들어간다.

 > 면세점 입구에서 Global Blue 라는 간판이 쓰인곳으로 가 영수증과 여권을 제출하면 환불을 받을 수 있다.
(+ 글로벌 블루가 tax free 환불해주는 여러 회사중 하나인것 같은데.. 만일 자신이 가지고 있는 영수증이 다른 회사라면 글로벌 블루 옆에 다른 회사 지점들도 있으므로 그것을 찾아 환불을 받을것)


두번째, Tax Free 제품을 휴대 수하물(=Carry on Baggage)로 가지고 갈 경우 (= 기내 반입 할 경우)

> Check in 및 출국 수속을 마치고 면세 Zone으로 들어간다.

> Customer taxfree 라고 쓰여있는 곳에가서 자신이 지참하고 있는 tax free 제품을 확인시켜주고 영수증에 Stamp 를 받는다.

> 그 다음부터는 화물로 부쳤을 떄와 똑같다.
Global Blue 라는 간판이 쓰인곳으로 가 영수증과 여권을 제출하면 환불을 받을 수 있다.
(+ 글로벌 블루가 tax free 환불해주는 여러 회사중 하나인것 같은데.. 만일 자신이 가지고 있는 영수증이 다른 회사라면 글로벌 블루 옆에 다른 회사 지점들도 있으므로 그것을 찾아 환불을 받을것)



[디버깅로그] Django: the current database router prevents this relation 오류 해결법 개발 삽질이야기

Django 개발 중 다음 에러가 발생해서 어려움을 겪었는데요.
Cannot assign "<TV4SectionList: TV4SectionList object>": the current database router prevents this relation.

해결방법을 공유합니다.
위 에러는 아래 코드 두 번째 줄에서 발생했어요.

section_list_map = TV4SectionListMap()
section_list_map.section = TV4SectionList.objects.get(pk=section_uid)
section_list_map.save()

TV4SectionListMap 의 section 필드는 TV4SectionList를 가리키는 foreign키에요.
새로운 TV4SectionListMap을 만들기 위해 기존 TV4SectionList 아이템 중 하나를 section_list_map.section에 넣을 필요가 있어서 저렇게 했는데 위와 같은 에러가 발생했습니다.

해결 방법은 두 번째 줄을 다음과 같이 바꾸는 거에요.

section_list_map.section = TV4SectionList.objects.using('user_master').get(pk=section_uid)

위 에러가 발생한 이유와 해결된 이유는 다음과 같아요.
현재 프로젝트 django settings DATABASES 에 master와 slave이 설정되었어요.

section_list_map = TV4SectionListMap()
section_list_map.section = ....

생성한 객체에서 필드값을 바꿀 때는 master DB를 기준으로,

TV4SectionList.objects.get(pk=section_uid)

필드값을 가져올 때는 slave DB에서 가져와요.
foregin 키로 관계 설정이 되어있어, Join 을 해 주어야 하는데, DB가 달라 연결이 안된거에요.

section_item.section = TV4SectionList.objects.using('user_master').get(pk=section_uid)

using() 메소드에 settings DATABASES 에 master로 설정된 이름을 넘겨주면 master DB에서 바로 get할 수 있어요.

====================================================================================

즉, 한마디로 요약하자면...!!

DB Routher 설정에 의해 데이터를 읽어오는 DB, Write 하는 DB가 다를경우, ORM 코딩 시, 데이터 부정합이 발생할 수 있다.

그러므로, 저 에러가 나면 일단 참조 데이터가 어느 DB 소속인지를 들여다 보면 되겟다.



1 2 3 4 5 6 7 8 9 10 다음


통계 위젯 (블랙)

33220
783
120540

GoogleAdsenseResponsive

Cluster map