Django 모델 층 은 다 중 표 관계 생 성과 다 중 표 작업 을 실현 합 니 다.

머리말
위의 글 의 내용 을 계속 하고 본 고 는 다 표 조작 을 소개 한다.django ORM 을 사용 하면 다 중 표 관 계 를 만 들 수 있 고 여러 장의 표 간 작업 도 지원 합 니 다.표 관 계 를 만 들 고 두 부분 을 조회 하여 django ORM 의 다 중 표 작업 을 설명 합 니 다.작가,도서,출판사 와 작가 의 정보 몇 장의 표를 사례 로 설명 한다.
테이블 관계 만 들 기
주의:실제 개발 에 서 는 외부 키 를 사용 하여 표 관 계 를 만 드 는 것 을 추천 하지 않 습 니 다.즉,직렬 업데이트 와 직렬 삭 제 를 사용 하지 않 고 논리 적 인 외부 키 관 계 를 사용 하여 표 관 계 를 만 드 는 것 을 추천 합 니 다.
상기 네 장의 표 에서 도서 와 출판사 라 는 두 표 의 관 계 는 한 쌍 이 많은 관계 에 속 하고 외부 키 는 조회 빈도 가 높 은 쪽 에 세 워 진다.작가 와 작가 의 상세 한 상황 표 는 1 대 1 관계 에 속 하고 외부 키 는 조회 빈도 가 높 은 쪽 에 세 워 집 니 다.작가 와 도 서 는 다 중 관계 에 속 하기 때문에 세 번 째 표 저장 관계 가 필요 합 니 다.외부 키 를 조회 빈도 가 높 은 쪽 에 세 우 는 것 을 권장 합 니 다.표를 만 들 때 는 데이터베이스 이전 명령 을 꼭 실행 해 야 합 니 다.
표 관 계 를 만 들 때 먼저 표 모형 을 만 든 다음 에 외 키 필드 를 추가 할 수 있 습 니 다.또한 django ORM 을 사용 하여 외 키 관 계 를 만 들 때 관련 외 키 필드 는 자동 으로 필드 에 추 가 됩 니 다id,표 와 표 사이 의 관 계 는 기본적으로 메 인 키 를 관련 필드 로 합 니 다.또한 표 관 계 를 만 들 때 실질 적 인 외 키 를 사용 하여 연결 하 는 것 을 권장 하지 않 고 논리 적 인 관 계 를 사용 하여 표 관 계 를 지정 합 니 다.

class Book(models.Model):
    name = models.CharField(max_length=60, verbose_name='   ')
    #      ,max_digits     8 , decimal_place      2 
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='    ')
    inventory_num = models.IntegerField(verbose_name='    ')
    sell_num = models.IntegerField(verbose_name='    ')
    #               ForeigenKey(to='  '),        , db_constraint=Flase            ,        
    publish = models.ForeignKey(to='Publish', on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='       ')
    #      ,  ManyToManyField(to='  '),author        ,       ORM,            ,  ORM              
    author = models.ManyToManyField(to='Author', on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='      ')


class Publish(models.Model):
    name = models.CharField(max_length=12, verbose_name='     ')


class Author(models.Model):
    name = models.CharField(max_length=10, verbose_name='    ')
    #        OneToOneField(to='  ')
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='        ')


class AuthorDetail(models.Model):
    age = models.IntegerField(verbose_name='  ')
    phone = models.CharField(max_length=11, verbose_name='   ')

또한 한 가 지 를 보충 해 야 합 니 다.여러 개의 표 관 계 는 모두 세 가지 생 성 방식 이 있 는데 그것 이 바로 전자 동 생 성,반자동 생 성 과 전 수 동 생 성 입 니 다.

#       - ManyToManyField,            
'''
                           ,    ,django ORM               
              
'''
class Book(models.Model):
 name = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author')
    
class Author(models.Model):
    name = models.CharField(max_length=32)
    
    
    
#       -  ForeignKey        
'''
              ,          ,      ORM       
'''
class Book(models.Model):
    name = models.CharField(max_length=32)
    
class Author(models.Model):
 name = models.CharField(max_length=32)
 
class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')
    
#      ,  ManyToManyField         
class Book(models.Model):
    name = models.CharField(max_length=32)
    authors = models.ManyToManyField(
        to='Author', #   ORM               
        through='Book2Author', #   ORM               
        through_fields=('book','author')  #           ,      ,           
                                     )
class Author(models.Model):
    name = models.CharField(max_length=32) 
    
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
다 중 표 데이터 조작-첨삭 수정
먼저 다 중 표 작업 의 첨삭 수정 작업 을 소개 합 니 다.다 중 표 의 조회 데이터 조작 이 조금 번 거 롭 기 때문에 따로 부뚜막 을 엽 니 다.
1 대 다&1 대 1 관계-첨삭
1 대 1 과 1 대 1 의 추가 삭제 작업 은 기본적으로 일치한다.
데이터 추가
데 이 터 를 추가 하 는 방법 은 두 가지 가 있 는데 하 나 는 실제 필드 를 통 해 추가 하 는 것 이 고 다른 하 나 는 가상 필드 대상 의 할당 을 통 해 추가 하 는 것 이다.

#   1:      
book_obj = models.Book.objects.create(name='    ', price=10.2, publish_id=1)

#   2,        ,                   
publis_obj = models.Publish.objects.filter(pk=1).first()
book_obj = models.Book.objects.create(name='    ', price=10.2, publish=publis_obj)

데이터 삭제
실제 프로젝트 개발 에서 데 이 터 를 삭제 하 는 것 은 실제 삭 제 된 것 이 아니 라 불 형식의 필드 로 이 데 이 터 를 삭제 하 는 지 여 부 를 표시 하 는 것 임 을 설명해 야 한다.
데 이 터 를 삭제 할 때 on 을 지정 하지 않 으 면delete=models.DO_NOTING 기본 값 은 직렬 업데이트 직렬 삭제 입 니 다.

models.Publish.objects.filter(pk=1).delete()
데이터 수정
데 이 터 를 수정 하 는 것 은 데 이 터 를 늘 리 는 것 과 마찬가지 로 두 가지 방식 이 있다.

#   1
models.Book.objects.filter(pk=1).update(publish_id=1)

#   2
pub_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=pub_obj)

다 대 다 관계.-첨삭,수정.
먼저 명확 한 것 은 여러 쌍 의 추가 삭제 수정 은 세 번 째 관계 표를 조작 하 는 것 입 니 다.그러나 세 번 째 관계 표 는 django 가 자동 으로 만 든 것 입 니 다.어떻게 코드 를 통 해 세 번 째 표 에 들 어 갑 니까?다 중 키 관 계 는 북 테이블 에 구축 되 어 있 으 며,다 중 키 필드 는 author 필드 이 므 로 북 을 통 해obj.author 는 세 번 째 시 계 를 조작 할 수 있 습 니 다.
django 가 자동 으로 만 든 세 번 째 표 의 다 중 관계 에 대해 django 는 데 이 터 를 조작 하 는 추가 적 인 방법 을 제공 합 니 다.
다 중 관계 추가-add()
add()방법 은 세 번 째 관계 표 에 데 이 터 를 추가 합 니 다.괄호 안에 숫자 도 전달 할 수 있 고 대상 도 전달 할 수 있 으 며 여러 개의 동시 작업 을 지원 합 니 다.

#   1,    id 
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.author.add(1)  #    1 1  , id 1    id 1   
book_obj.author.add(2, 3)   #       ,1 2   1 3

#   2,        
book_obj = models.Book.objects.filter(pk=2).first()
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
author_obj3 = models.Author.objects.filter(pk=3).first()
book_obj.author.add(author_obj1)    #   1   
book_obj.author.add(author_obj2, author_obj3) #   2 

다 중 관계 삭제-remove()
remove()방법 은 세 번 째 표 에 데 이 터 를 삭제 하 는 데 사 용 됩 니 다.마찬가지 로 괄호 안에 숫자 도 전달 할 수 있 고 대상 도 전달 할 수 있 으 며 여러 개의 데 이 터 를 동시에 조작 할 수 있 습 니 다.

#   1:     
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.author.remove(2)  #   book_id 1 author_id  2   
book_obj.authors.remove(1, 3)  #     

#   2:      
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.remove(author_obj1, author_obj2)

다 중 관계 수정-set()
set()방법 은 세 번 째 표를 수정 하 는 데 사 용 됩 니 다.이 방법 은 덮어 쓰기 동작 입 니 다.새로운 관계 로 이전의 관 계 를 덮어 씁 니 다.이 방법의 매개 변 수 는 목록 이나 원 그룹 이 어야 합 니 다.숫자 나 대상 을 가리 키 고 여러 개의 데 이 터 를 동시에 조작 할 수 있 습 니 다.

#   1:         
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.author.set([2])  #  book_id 1   author_id   2
book_obj.authors.set([1, 2])  #         id=1  id=2   

#   2:        
author_obj2 = models.Author.objects.filter(pk=2).first()
author_obj3 = models.Author.objects.filter(pk=3).first()
book_obj.authors.set([author_obj2, author_obj3])

세 번 째 표 의 특정한 대상 의 바 인 딩 관 계 를 비 웁 니 다-clear()
clear()방법 은 세 번 째 관계 표 의 한 대상 의 연결 관 계 를 비 웁 니 다.

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.author.clear()
다 중 표 조회
다 중 표 조회 작업 을 하기 전에 하나의 개념,무엇이 정방 향 조회 와 역방향 조회 인지 알 아야 한다.
4.567917.정방 향 조회:외부 키 가 어느 표 에 있 는 지 조회 하 는 것 은 바로 정방 향 조회 이다.예 를 들 어 책 을 통 해 출판 사 를 조회 하 는 것 이다4.567917.역방향 조회:관련 된 표 에서 외부 키 필드 가 있 는 표 는 바로 역방향 조회 이다.예 를 들 어 출판 사 를 통 해 책 을 조회 하 는 것 이다하위 조회
만약 에 조회 가 비교적 복잡 할 때 하위 조회 방식 을 사용 할 수 있다 면 하위 조 회 는 단계별 로 조회 한 다 는 뜻 이 고 먼저 조회 한 결 과 를 나중에 조회 하 는 조건 으로 한다.
정방 향 조회
검색 필드 를 누 르 고 있 습 니 다.여러 결과 가 외부 키 필드.all()가 필요 하 다 면 검색 결과 가 여러 개 인지 어떻게 판단 합 니까?.all()을 추가 하지 않 은 상태 에서 얻 은 결 과 는 응용 이름 입 니 다.모델 이름.None,예 를 들 어 first.Author.None 와 같은 상황 에서 ORM 문 구 는 오류 가 없 음 을 설명 합 니 다.검색 한 결과 가 여러 개 있 을 뿐.all()을 추가 해 야 합 니 다.검색 결과 가 하나 일 때 모델 대상 을 얻 습 니 다.여러 개 일 경우 Query Set 대상 입 니 다.

#        :       1           
book_obj = models.Book.objects.filter(pk=1).first()
res = book_obj.publish  # Publish object (1)
print(res.name)

#        :       1   
book_obj = models.Book.objects.filter(pk=1).first()
res = book_obj.author  # first.Author.None,       
res_many = book_obj.author.all()  # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    
#        :    lili   
author_obj = models.Author.objects.filter(name='lili').first()
res = author_obj.author_detail
print(res.phone)

역방향 조회
역방향 조회 가 1 대 1 이 라면 표 명 소문 자 입 니 다.한 쌍 이 많 거나 여러 쌍 이 많 을 때 역방향 조 회 는 소문 자-set 를 나타 내 는 것 입 니 다.또한 여러 가지 결과 가 있 으 면 소문 자 를 나타 내 고 다시 를 추가 해 야 합 니 다.set.all(),결과 가 정방 향 조회 와 같은 방법 이 있 는 지 판단 합 니 다.검색 결과 가 하나 일 때 모델 대상 을 얻 습 니 다.여러 개 일 경우 Query Set 대상 입 니 다.

#        ,               
publish_obj = models.Publish.objects.filter(name='  ').first()
res = publish_obj.book_set.all()  # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>

#        ,     lili    
author_obj = models.Author.objects.filter(name='lili').first()
res = author_obj.book_set  # first.Book.None,       
res_many = author_obj.book_set.all()
print(res_many)  # <QuerySet [<Book: Book object (1)>]>

#        ,      119   
author_detail_obj = models.AuthorDetail.objects.filter(phone='119').first()
res = author_detail_obj.author
print(res.name)

리스트 조회
연결 표 조 회 는 MySQ 에서 SQL 문장의 연결 표 조회 처럼 django 의 ORM 에서 더 블 밑줄 연결 표 조회(크로스 표 조회)를 사용 할 수 있 습 니 다.연표 조 회 는 한 줄 의 코드 로 결 과 를 조회 할 수 있 고 연표 조회 도 정반 향 관 계 를 따른다.
정방 향 조회

#        :       1         
#         ,     publish   ,        values('names')  ,                       ,    __        
res = models.Book.objects.filter(pk=1).values('name', 'publish__name')  # <QuerySet [{'name': '    ', 'publish__name': '  '}]>

#        ,       1     
res = models.Book.objects.filter(pk=1).values('author__name')  # <QuerySet [{'author__name': 'lili'}, {'author__name': 'nana'}]>

#        ,  lili       
res = models.Author.objects.filter(name='lili').values('name', 'author_detail__phone').first()
print(res.get('name'), res.get('author_detail__phone'))

역방향 조회

#        :       1           
res = models.Publish.objects.filter(book__id=1).values('name', 'book__name')  # <QuerySet [{'name': '  ', 'book__name': '    '}]>

#        :       1        
res = models.Author.objects.filter(book__id=1).values('name', 'book__name')  # <QuerySet [{'name': 'lili', 'book__name': '    '}, {'name': 'nana', 'book__name': '    '}]>

#        :    id 1         
res = models.AuthorDetail.objects.filter(author__id=1).values('author__name', 'phone')  # <QuerySet [{'author__name': 'lili', 'phone': '119'}]>

#      :       1       ,        ,        ,             
res = models.Book.objects.filter(pk=1).values('author__author_detail__phone')  # <QuerySet [{'author__author_detail__phone': '119'}, {'author__author_detail__phone': '120'}]>

취 합 조회
취 합 조 회 는 일반적으로 그룹 과 함께 사용 되 며,취 합 조 회 는 최대 치,최소 치,평균 값 등 통계 도 구 를 사용 합 니 다.취 합 함수 의 가 져 오 는 방식 from django.db.models import Max,Min,Sum,Count,Avg 는 그룹 을 나 누 지 않 고 취 합 함 수 를 사용 하려 면 aggregate()방법 에서 사용 해 야 합 니 다.

from django.db.models import Min,Max,Sum,Count,Avg
#         
res = models.Book.objects.aggregate(Avg('price'))
print(res)
#              
res = models.Book.objects.aggregate(Max('price'),Sum('price'),Count('pk'))
print(res)
그룹 검색
집합 함 수 는 보통 그룹 과 함께 사용 합 니 다.그룹 조회 방법 은 annotate 입 니 다.기본적으로 models.그룹 근 거 를 그룹 근거 로 합 니 다.즉,표 의 메 인 키 로 그룹 을 나 눕 니 다.annotate()방법 앞 에 values()가 나타 나 면 values 에서 지정 한 값 에 따라 그룹 을 나 눕 니 다.패 킷 조회 지원크로스 테이블 조회.

from django.db.models import Sum, Max, Min, Avg, Count

# 1.          
res = models.Book.objects.annotate(author_num=Count('author')).values('name', 'author_num')  # author_num                           ,         

# 2.                 
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')

# 3.           
#        ,          ,          1   
res = models.Book.objects.annotate(author_num=Count('author')).filter(author_num__gt=1).values('name', 'author_num')

# 4.             
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price')

F 와 Q 조회
F 조회
F 조 회 는 표 의 한 필드 의 데이터 값 을 얻 을 수 있 습 니 다.특히 표 의 두 필드 간 의 비교 연산 에 적합 합 니 다.문자 형식의 데 이 터 를 조작 할 때 F 는 문자열 의 조합 을 직접 할 수 없고 Concat 와 Value 를 빌려 야 합 니 다.

from django.db.models import F

# 1.               
res = models.Book.objects.filter(sell_num__gt=F('inventory_num'))

#           20 
res = models.Book.objects.update(price=F('price')+20)

F.문자열 에 대한 조 회 는 Concat 와 Value 두 가지 방법 을 사용 해 야 합 니 다.

#                 
from django.db.models.functions import Concat
from django.db.models import F, Value

models.Book.objects.update(name=Concat(F('name'),Value('  ')))

질문
filter()를 사용 하여 조건 필 터 를 할 때 논리 와 and 의 동작 을 사용 합 니 다.여러 개의 필터 조건 을 or 또는 not 의 관계 로 바 꾸 려 면 Q 조 회 를 통 해 확인 해 야 합 니 다.Q 조회 에서|or 의 관 계 를 나타 내 고~not 의 관 계 를 나타 낸다.

import django.db.models import Q

#         100      20   
res = models.Book.objects.filter(~Q(sell_num__gt=100) | Q(price__lt=20))

또한 Q 조 회 는 검색 조건 의 왼쪽 도 문자열 로 바 꿀 수 있 는 또 다른 고급 용법 도 있다.

#      Q   
q = Q()
#   q        
q.connector = 'or'
q.children.append(('sell_num__gt',100))
q.children.append(('price__lt',200))
res = models.Book.objects.filter(q)
# filter    Q        ,        and  ,    
print(res)
django 트 랜 잭 션 시작
MySQL 은 데이터 의 안전 을 위해 하나의 사무 체 제 를 가지 고 있 습 니 다.django 는 MySQL 을 연결 할 수 있 으 면 django 는 MySQL 의 사무 체 제 를 지원 할 수 있 습 니 다.다음 코드 는 django 에서 사 무 를 시작 하 는 것 입 니 다:

from django.db import transaction

try:
    with transaction.atomic():   #  with         orm          
        ...
except Exception as e:
    print(r)
...

Django 모델 층 의 다 중 표 관계 생 성과 다 중 표 작업 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 Django 다 중 표 작업 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기