-
객체 관계 매핑 (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
Q
복잡한 쿼리조건 구성
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