ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ORM
    Django/OZ 2024. 3. 8. 18:52

    객체 관계 매핑 (Object–relational mapping)

    (oz-django-py3.12) (base) hotbari@yeonsuui-MacBookPro oz-Django % python manage.py shell
    Python 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from boards.models import Board
    id가 1인 객체 불러오기
    >>> board = Board.objects.get(id=1)
    >>> board.user
    <User: hotbari>
    >>> board.user.id
    1​
    (oz-django-py3.12) (base) hotbari@yeonsuui-MacBookPro oz-Django % python manage.py shell
    Python 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)

     

    모듈 불러오기

    >>> from users.models import User
    >>> 
    >>> from boards.models import Board
    >>> Board.objects.all()
    <QuerySet [<Board: common 모델 상속받음>]>

     

    객체에 담아 읽어오기

    >>> board = Board.objects.get(id=1)
    >>> type(board)
    <class 'boards.models.Board'>
    >>> board.id
    1
    >>> board.title
    'common 모델 상속받음'
    >>> board.content
    'created_at, updated_at 필드가 추가됩니다.'
    >>> board.created_at
    datetime.datetime(2024, 3, 8, 4, 36, 26, 904422, tzinfo=datetime.timezone.utc)
    >>>

     

    get을 사용할 때 return 데이터가 2개 이상이면 문제 발생하기 때문에

    Filter를 사용하여 데이터 가져오기

    *gte는 greater than equal (*gt, gte, lt, lte)

    >>> Board.objects.filter(likes__gte=0)
    <QuerySet [<Board: common 모델 상속받음>]>

     

     

     

    Board에 User FK 연결

    from django.db import models
    from django.utils import timezone
    
    #CommonModel import
    from common.models import CommonModel
    
    
    # Create your models here.
    class Board(CommonModel):
        title = models.CharField(max_length=30)
        content = models.TextField()
        date = models.DateTimeField(default=timezone.now)
        likes = models.PositiveBigIntegerField(default=0)
        reviews = models.PositiveBigIntegerField(default=0)
        writer = models.CharField(max_length=30)
        
        # FK 연결
        # user 데이터가 삭제되면 Board 데이터도 삭제
        user = models.ForeignKey("users.User",on_delete=models.CASCADE)
    
        # 제목 보여주기
        def __str__(self):
            return self.title

    기존의 데이터는 1이라는 유저로 추가

     

    db.sqlite3에서 FK가 연결된 것을 확인할 수 있다.

    기본 데이터로 설정한 1이 들어가있다

    (oz-django-py3.12) (base) hotbari@yeonsuui-MacBookPro oz-Django % python manage.py shell
    Python 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from boards.models import Board
    >>>
    ## id=1인 데이터 불러오기
    >>> board = Board.objects.get(id=1)
    >>> board.user
    <User: hotbari>
    >>> board.user.id
    1

     

    데이터 업데이트 & 하나씩 읽어오기 & 필더 함수 사용하기

    >>> board.title
    'common 모델 상속받음'
    >>> ## 제목 업데이트
    >>> board.title = '업데이트된 제목'
    >>> board.save()
    >>> 
    >>> board.title
    '업데이트된 제목'
    >>> 
    >>> boards = Board.objects.all() ## 데이터 읽어오기
    >>> boards
    <QuerySet [<Board: 업데이트된 제목>]>
    >>> ## 현재 데이터는 하나지만 다수일 때 하나씩 읽어오기
    >>> for i in boards:
    ...     print(i.title)
    ... 
    업데이트된 제목
    >>> for i in boards:
    ...     print(i.user.username)
    ... 
    hotbari
    >>>
    >>> ## 필터 함수 사용법
    >>> ## user 모델 불러오기
    >>> from users.models import User
    >>> User.objects.filter(is_business=False)
    <QuerySet [<User: hotbari>]>
    >>> ## 특정 내용을 포함한 데이터 반환
    >>> Board.objects.filter(title__contains='업데이트')
    <QuerySet [<Board: 업데이트된 제목>]>
    >>>

     

    데이터 추가하기

    >>> python manage.py shell
    >>> ## 그냥 Board를 부르면 에러
    >>> Board
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    NameError: name 'Board' is not defined
    >>> ## import 필요
    >>> from boards.models import Board
    >>> Board
    <class 'boards.models.Board'>
    >>>
    >>> Board.objects.all()
    <QuerySet [<Board: 업데이트된 제목>]>
    >>>
    >>> ## User import
    >>> from users.models import User
    >>> 데이터추가, default값이 있는 필드는 default값으로 대체
    >>> Board.objects.create(title="title2",content="Hello",writer='sungchan',user=User.objects.get(pk=1))
    <Board: title2>
    >>> Board.objects.all()
    <QuerySet [<Board: 업데이트된 제목>, <Board: title2>]>
    >>>

     

    두번째 데이터의 필드만 읽어오려면 filter 기능을 사용하는게 좋다

    >>> title2 = Board.objects.filter(title='title2')
    >>> for i in title2:
    ...     print(i)
    ... 
    title2
    >>> for i in title2:
    ...     print(i.title)
    ...     print(i.writer)
    ...     print(i.content)
    ...     print(i.likes)
    ... 
    title2
    sungchan
    Hello
    0

     

    데이터 삭제

    >>> ## 데이터 삭제(title2를 삭제해본다, 객체는 이미 불러왔음=title2)
    >>> title2.delete()
    (1, {'boards.Board': 1})
    >>> Board.objects.all()
    <QuerySet [<Board: 업데이트된 제목>]>
    >>>
    >>> Board.objects.all().count()
    1

     

    복잡한 쿼리조건 구성

    from django.db.models import Q
    
    # or
    # filter(Q(<condition_1>|Q(<condition_2>)
    Board.objects.filter(Q(content__contains="내용") | Q(likes__gt=10))
    
    # and
    # filter(<condition_1>, <condition_2>)
    Board.objects.filter(content__contains="내용", likes__gt=10) # 여러 조건 적용 가능
    
    # not
    # filter(~Q(<condition>))
    User.objects.filter(~Q(is_business=False))
    
    # count
    Board.objects.filter(content__contains="내용", likes__gt=10).count()
    
    len([1,2,3])
    len(QuerySet[1,2,3])
    len(user.board_set.all()) => 안먹힌다.
    
    user.board_set.all().count()

     

    reverse accessors

    부모-자녀 관계에서 FK는 자녀가 갖고 있다. (여기서는 Board-User, User가 FK를 가짐)

    따라서 board.user는 가능하지만 user.board는 불가능

    역참조를 위해 reverse accessors 사용

    >>> user = User.objects.get(id=1)
    >>> user
    <User: hotbari>
    >>> user.board
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    AttributeError: 'User' object has no attribute 'board'
    >>> dir(user)
    ['DoesNotExist', 'EMAIL_FIELD', 'Meta', 'MultipleObjectsReturned', 'REQUIRED_FIELDS', 'USERNAME_FIELD', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_check_column_name_clashes', '_check_constraints', '_check_db_table_comment', '_check_default_pk', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_indexes', '_check_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_model_name_db_lookup_clashes', '_check_ordering', '_check_property_name_related_field_accessor_clashes', '_check_single_primary_key', '_check_swappable', '_check_unique_together', '_do_insert', '_do_update', '_get_FIELD_display', '_get_expr_references', '_get_field_value_map', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_session_auth_hash', '_get_unique_checks', '_meta', '_password', '_perform_date_checks', '_perform_unique_checks', '_prepare_related_fields_for_save', '_save_parents', '_save_table', '_set_pk_val', '_state', '_validate_force_insert', 'acheck_password', 'adelete', 'arefresh_from_db', 'asave', 'board_set', 'check', 'check_password', 'clean', 'clean_fields', 'date_error_message', 'date_joined', 'delete', 'email', 'email_user', 'first_name', 'from_db', 'full_clean', 'get_all_permissions', 'get_constraints', 'get_deferred_fields', 'get_email_field_name', 'get_full_name', 'get_group_permissions', 'get_next_by_date_joined', 'get_previous_by_date_joined', 'get_session_auth_fallback_hash', 'get_session_auth_hash', 'get_short_name', 'get_user_permissions', 'get_username', 'grade', 'groups', 'has_module_perms', 'has_perm', 'has_perms', 'has_usable_password', 'id', 'is_active', 'is_anonymous', 'is_authenticated', 'is_business', 'is_staff', 'is_superuser', 'last_login', 'last_name', 'logentry_set', 'natural_key', 'normalize_username', 'objects', 'password', 'pk', 'prepare_database_save', 'refresh_from_db', 'save', 'save_base', 'serializable_value', 'set_password', 'set_unusable_password', 'unique_error_message', 'user_permissions', 'username', 'username_validator', 'validate_constraints', 'validate_unique']
    >>> ## 역참조 함수는 board_set
    >>> user.board_set
    <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x110800950>
    >>> user.board_set.all()
    <QuerySet [<Board: 업데이트된 제목>]>
    >>>

     

    더보기

    필드명_set 함수는 FK 지정에 있어 생겨난다. feed,review와 user의 경우,

    user.feed_set 과 user.reivew_set 으로 사용할 수 있다.

    'Django > OZ' 카테고리의 다른 글

    EmailField & CharField Difference  (0) 2024.03.18
    Django 3일차 - Rest framework  (0) 2024.03.09
    Django 2일차 - Admin Panel  (0) 2024.03.07
    Django 2일차  (1) 2024.03.07
    URL, VIEW 개념  (0) 2024.03.06
Designed by Tistory.