본문 바로가기
airbnb clone coding

[Django] 7_2. ORM: Admin Methods / ForeignKey Filter

by busybee-busylife 2024. 7. 14.
반응형

Admin Methods 

1) list_display에 'total_amenities'를 추가 

2) rooms > models.py에 없는 내용이므로 에러 발생 

 

3) rooms > admin.py에서 메서드로 추가 가능 

 

 

4) rooms > models.py에서도 추가 가능 

 

 

 

 

ForeignKey Filter 

Reverse Accessor(역방향 접근자)

oreignKey, OneToOneField, ManyToManyField 등을 사용할 때 자동으로 생성되는 속성

모델 간의 관계를 정의할 때 두 모델 사이의 역방향 관계에 접근할 수 있게 해주는 개념

외래 키나 다대다 관계를 통해 연결된 관련 객체들을 쉽게 조회할 수 있음

(해당 모델의 인스턴스에서 관련된 다른 모델의 인스턴스에 접근할 수 있다) 

ex. user_1은 여러개의 사진을 업로드 할 수 있다 

    <-> user_1의 profile에서 user_1이 업로드한 모든 사진을 볼 수 있다 

ex. room_1에 얼마나 많은 review가 만들어졌는지 알 수 있다 

    <-> 그 중 한 review의 user가 어떤 review들을 작성했는지 알 수 있다 

"Reverse is everywhere."

 

ForeignKey를 이용한 필터링 

특정 room_1을 위해 만들어진 review가 얼마나 있는지

하나의 user가 생성한 room이 얼마나 있는지

>>> from rooms.models import Room

>>> room_1 = Room.objects.get(pk=1) 
>>> room_1
<Room: Beautiful House>

>>> room_1.price
20  

>>> room_1.owner
<User: busybee>

>>> room_1.owner.username
'busybee'
# room_1 owner의 username을 검색

>>> Room.objects.filter(owner__username="busybee")
<QuerySet [<Room: Beautiful House>]>
# owner의 username으로 필터링

>>> Room.objects.filter(owner__username__startswith="b")
<QuerySet [<Room: Beautiful House>]>

review.user : 해당 review를 작성한 user 정보 

user.reviews : 해당 user가 작성한 review 정보 

 

 

🤜 미션: 한 user가 만든 모든 room 정보 조회하기 🤛

1) room에서 필터링: 반복적으로 사용해야한다 

2) user 관점에서 바라보기: 위 필터링 기능들은 이미 우리 user모델에 built-in 되어있다

>>> from users.models import User

>>> me = User.objects.get(pk=1)

>>> me
<User: busybee>

>>> dir(me)
['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']

>>> me.room_set.all()
<QuerySet [<Room: Beautiful House>]>

    dir(me): 'me'가 가진 속성, 메서드를 출력     'ㅇㅇ_set':'me'의 reverse accesor   

    ex. rooms 모델은 category에 대해 foreignkey를 가지고 있음: category 모델은 room_set을 받는다 

 

 

Reverse Accessors의 이름 변경하기 

모델 A가 모델 B의 foreign key를 가지고 있으면: 모델 B는 저절로 '모델 A_set'를 받는다

이때 reverse accessor의 이름을 임의로 변경할 수 있다 

ex. room_set -> rooms 

 

✍️ 방법 ✍️

모델 A에서 related_name을 추가한다rooms > models.py

owner = models.ForeignKey("users.User", on_delete=models.CASCADE)

owner = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name="rooms")

이제 user는 'room_set'이 아닌 'rooms'를 갖는다 

 

amenities, category에서도 변경해준다

amenities = models.ManyToManyField("rooms.Amenity", related_name='rooms')

 category = models.ForeignKey("categories.Category", null=True, blank=True, on_delete=models.SET_NULL, related_name='rooms')

>>> from users.models import User
>>> me = User.objects.get(pk=1)
>>> me
<User: busybee>

>>> me.rooms.all()
<QuerySet [<Room: Beautiful House>]>

이제 rooms로 작업할 수 있다 

 

foreign key/many to many를 갖는 나머지 모델들도 위와 같이 수정할 수 있다 

 

 

Recap

하나의 Review는 하나의 User에 속한다 

하나의 Review는 하나의 Room에 속한다 

 

하나의 User는?? 

room_set으로 확인할 수 있다 

foreign key를 가지고 있는 모델은 'ㅇㅇㅇ_set'이 저절로 생성된다

 'ㅇㅇㅇ_set'의 이름을 변경할 수 있다 

반응형