Reverse accessors는 관계를 뒤집어서 접근할 수 있게 해줌
>> poetry shell # poetry shell 접속
>> python manage.py shell # 장고를 실행하면서 파이썬 터미널을 사용할 수 있게 해줌
>>> from rooms.models import Room
>>> room = Room.objects.get(pk=1)
>>> room
<Room: Beautiful House in 서울>
>>> room.price
1
# room이 user를 가리키고 있음, reverse accessor란 owner가 어떤방을 가지고 있는 지 아는 것
>>> room.owner
<User: jaejunkim>
>>> room.owner.username
'jaejunkim'
# filter를 통해 방의 주인 아는 법
# 방의 주인을 찾는 것과 같은 코드는 매우 자주 사용할 수 밖에 없기에 일일히 filter를 쓸 수는 없음
# 따라서 reverse를 사용해야함
Room.objects.filter(owner__username=room.owner)
<QuerySet [<Room: Beautiful House in 서울>, <Room: Apt in 서울>]>
>>> Room.objects.filter(owner__username__startswith='jae')
<QuerySet [<Room: Beautiful House in 서울>, <Room: Apt in 서울>]>
# user.rooms
# user.reviews
# user.wishlists
# 위와 같이 user의 방들, 리뷰들, 위시리스트 같이 볼 수 있어야함, 이를 가능하게 하는 것이 reverse
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
class GenderChoices(models.TextChoices):
MALE = ("male", "Male")
FEMALE = ("female", "Female")
class LanguageChoices(models.TextChoices):
KR = ("kr", "Korean")
EN = ("en", "English")
class CurrencyChoices(models.TextChoices):
WON = "won", "Korean Won"
USD = "usd", "Dollar"
first_name = models.CharField(
max_length=150,
editable=False,
)
last_name = models.CharField(
max_length=150,
editable=False,
)
avatar = models.ImageField(blank=True)
name = models.CharField(
max_length=150,
default="",
)
is_host = models.BooleanField(
default=False,
)
gender = models.CharField(
max_length=10,
choices=GenderChoices.choices,
)
language = models.CharField(
max_length=2,
choices=LanguageChoices.choices,
)
currency = models.CharField(
max_length=5,
choices=CurrencyChoices.choices,
)
# User를 통해 room에 접근하는법
# -> User가 가진 romm을 찾는거
>>> from users.models import User
>>> me = User.objects.get(pk=1)
>>> me
<User: jaejunkim>
>>> me.rooms # 기본적으로는 에러가 발생함
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'User' object has no attribute 'rooms'
# dir 사용
# dir: 모든 속성, 클래스의 메소드, 클래스의 인스턴스를 보여줌
# User가 가진 모든 속성 및 메소드
['CurrencyChoices', 'DoesNotExist', 'EMAIL_FIELD', 'GenderChoices', 'LanguageChoices', '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', 'avatar', 'booking_set', 'chattingroom_set', 'check', 'check_password', 'clean', 'clean_fields', 'currency', 'date_error_message', 'date_joined', 'delete', 'email', 'email_user', 'experience_set', 'first_name', 'from_db', 'full_clean', 'gender', 'get_all_permissions', 'get_constraints', 'get_currency_display', 'get_deferred_fields', 'get_email_field_name', 'get_full_name', 'get_gender_display', 'get_group_permissions', 'get_language_display', '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', 'groups', 'has_module_perms', 'has_perm', 'has_perms', 'has_usable_password', 'id', 'is_active', 'is_anonymous', 'is_authenticated', 'is_host', 'is_staff', 'is_superuser', 'language', 'last_login', 'last_name', 'logentry_set', 'message_set', 'name', 'natural_key', 'normalize_username', 'objects', 'password', 'pk', 'prepare_database_save', 'refresh_from_db', 'review_set', 'room_set', 'save', 'save_base', 'serializable_value', 'set_password', 'set_unusable_password', 'unique_error_message', 'user_permissions', 'username', 'username_validator', 'validate_constraints', 'validate_unique', 'wishlist_set']
# 위의 배열을 보면 내부에 room_set, wishlist_set등과 같이 지정하는 메소드들이 있음, 이게 reverse accessor임
# User.rooms와 같음
>>> me.room_set.all()
<QuerySet [<Room: Beautiful House in 서울>, <Room: Apt in 서울>]>
>>> admin = User.objects.get(name='admin')
>>> admin.room_set.all()
<QuerySet []>
# user가 foreign key로 들어간 모든 자원에 적용할 수 있음, room,booking, reviews, wishilist등
# 특정 카테고리가 들어간 room
>>> category
<Category: Experiences: Food and Drink>
>>> category.room_set.all()
<QuerySet [<Room: Apt in 서울>]>