기본 콘텐츠로 건너뛰기

Django join 기초



장고 INNER JOIN 을 거는 법!!!
아래의 테이블 모델을 살펴보자.

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices')
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

- Question 과 Choice 라는 2개의 모델 (테이블) 을 만들었다
- Choice 에 question 이라는 ForeignKey가 걸린 것이 보일것이다. 이것은 Choice 모델의 테이블에 "question_id" 라는 필드를 만들게 되고, 모델 설계 상, Question : Choice = 1 : N 의 구조를 낳게 된다.

- related_name 이 choices 인 것에 주목하자.  이것은 Question model 입장에서 Choice model 을 어떤식으로 명명할지에 대한 값이다.

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

조인은 데이터를 SELECT 할때, 기준이되는 모델에 따라 거는 방향이 다른데
아래와같이 2가지 종류가 있다.

1. Many-to-one : Choice 모델을 기준으로 Question 데이터를 불러올 경우.

요건 참 쉽다. 일단 참고할만한 원문 Documentation 내용 링크는 아래와 같다.

choice_data_with_question = Choice.objects.select_related('question')

- 위와같이

2. One-to-many : Question 모델을 기준으로 Choice 데이터를 불러올 경우

이게 좀 문젠데, 일단 Documentation 내용은 아래와 같다.

크게 2가지 방법이 있는데, 하나씩 설명하도록 하겠다.

첫번째 방법 : prefetch_related() 사용하기

>> 이것은 Question 모델이 Choice 에서 지정한 related_name 인 choices 라는 Attribute 로 Choice 모델의 Default Manager를 연동시켜 놓는 것을 말한다. 말이 좀 어려운데, 쉽게 말하면 question_list 의 각 element 인 question 에 question.choices = Choices.objects 가 붙어있는 상태를 만드는 일이라고나 할까...? 그리고 이것은 실직적으로 아직 쿼리를 실행시키는 함수가 call 되지 않은 상태이기 때문에 

<View 쪽>

def get_context_data():
    context["questions"]  = Question.objects.prefetch_related('choices')
    return context

<Template 쪽>

{% for question in questions %}
    <b>{{ question.question_text }}</b>
    <ul>
        {% for choice in question.choices.all %}
            <li>{{ choice.choice_text }}</li>
        {% endfor %}
    </ul>
{% endfor %}

※ Choice 모델에서 related_name 을 지정하지 않았을 경우에는 템플릿 쪽에서 question.choice_set.all 을 사용하면 된다.
두번째 방법 : annotate() 사용하기


def get_context_data():
question_data_with_choices = Question.objects.annotate(choice_id=F('choices__id'), choice_text=F('choices__choice_text'), votes=F('choices__votes')).annotate(Count('id))



=============================================================================================
- Many to oneselect_related() 를 잘 사용하면 된다
- One to manyprefetch_related() 혹은 annotate() 를 잘 사용하면 된다, 



댓글

이 블로그의 인기 게시물

우분투[ubuntu] 런처(윈도우 메뉴)에 아이콘 추가 하기.

안녕하세요.  KANO 입니다. 오늘은 간단하게 우분투 바로가기 아이콘 생성을 해 볼 건데요. 우분투 혹은 리눅스 사용자들은 프로그램을 설치 하지 않고, 프로그램을 실행해야 하는 프로그램들이 있습니다 . 예) 이클립스. 등등.. 이것을 조금 편하게 할 수 없을까? 생각하다가 저도 만들어 보는 시간을 갖으면서 글을 적어 봅니다. 제가 등록할 프로그램은 Pycharm 2017.03 버전인데요. 우분투에서 우분투 소프트웨어 관리자에서 추가가 가능 하긴 합니다..( _ _ )   현재 런쳐 메뉴의 프로그램에는 Pycharm이 보이지 않는데요. 아이콘 등록을 위하여 터미널을 열어서 명령어로 실행할 수 있게 만들어 봅시다  sudo ln -s  실행 파일 경로,  symlink 경로 입니다.  실행파일 경로만 바꿔 주시면  될 것 같네요.. ㅎㅎ 그럼 한번 실행을 해보도록 하죠~ 정상적으로 실행이 되네요.  그럼 이제 아이콘을 생성해보도록 합니다. 아이콘 생성 방법은 2가지 인데요 우선 첫번째 방법을 이용해 보도록 하죠. .desktop 파일을 생성 하는 방법입니다. 런처 아이콘 경로에  만들려는 이름.desktop 을 생성합니다. 저는 pycharm 이라서 Pycharm.desktop 이라고 vi 편집기를 이용하여 파일을 생성 할께요. vi 편집기가 열리면 다음과 같이 적어 주세요.  [Desktop Entry] Version =x.y    #프로그램 버전 (안 적어도 무방합니다.) Name=프로그램 이름 Comment=프로그램 설명 Exec=프로그램 실행 명령어 #저는 pycharm.sh 를 입력했습니다. Icon=아이콘 경로 Terminal=false #터미널 실행 여부 입니다. (True : 실행, False:실행안함) Type=Application #실행 형식입니다. 이건 수정하지 말아주세요~ Catego

[linux] ubuntu 16.04 메뉴, 런처 없어짐.. (hide menu, luncha...)

우분투 사용을 하다가 보면 가끔 필요 없는 프로그램 을 삭제 해야 할 때 가 있다. ex) sudo apt-get remove --purge XXXXXXX 삭제를 하고 제부팅을 하면.. 하하하하하하~~!!! 메뉴 어디갔나요?;;;;ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 멘탈이 나갈거같네요..\ 우선 아는데로 쳐보기로 합니다.. sudo apt-get install ubuntu-desktop sudo apt-get install unity-control-center sudo apt-get install unity-control-center-signon sudo apt-get install gnome-control-center-unity sudo reboot 여기서 해결이 되나요??';  저는 안되서 구글링을... Enter the following commands:- Ctrl+Alt+F1 login there with username and password WARNING! THE FOLLOWING COMMAND WILL TERMINATE YOUR ACTIVE SESSION! try: sudo service lightdm restart If restarting lightdm doesn't fix the problem, install aptitude and then install unity : sudo apt-get install aptitude sudo apt-get update && sudo aptitude -f install && sudo aptitude dist-upgrade sudo aptitude install unity Read the outputs carefully. If you do have broken dependencies, aptitude will give you the "solution" of NOT installing u

[심심] Oracle 초성검색 함수 만들기

 안녕하세요!  오랫만에 돌아온 카노 입니다. 오늘은 너무 심심해서 오라클(DB) 를 갖고 초성 찾기 함수를 만들어 볼 생각 입니다. 예) fn_korinitialkeyword('홍길동') return : ㅎㄱㄷ select * from 테이블 where fn_korinitialkeyword(직원명컬럼) like '%ㅎㄱㄷ%' 이런식으로 검색이 되도록 만들 꺼에요~ 함수 코드는  function fn_korinitialkeyword( str in varchar2) return varchar2 is    returnStr varchar2(100);     cnt number := 0;     tmpStr varchar2(10); begin        if str is null then       return '';       end if;              cnt := length(str);        for i in 1 .. cnt       loop         tmpStr := substr(str,i,1);                        returnStr := returnStr ||       case when tmpStr < 'ㄱ' then substr(tmpStr, 1, 1)             when ascii('ㄱ') <= ascii(tmpStr) and ascii(tmpStr) <= ascii('ㅎ') then chr(ascii(tmpStr))             when tmpStr < '나' then 'ㄱ'             when tmpStr < '다' then 'ㄴ'             when tmpStr < '라' then 'ㄷ'             when tmpStr < '마'