TIL Day 67.

Jen Devver·2024년 5월 21일

내배캠 TIL

목록 보기
74/91

Django 최종 팀 프로젝트

Admin 페이지

기존에 시험 삼아 만들었던 Django Admin을 우리 프로젝트에 맞게 수정해 기능 구현

CustomUserAdmin 생성

  • 문제 1: 장고에서 기본으로 쓰는 User 모델을 쓰고 있었는데 해당 모델은 필드 추가 시 유저 생성 폼 내의 필드 순서가 섞였음
  • 해결방안: 따라서 CustomUserAdmin을 생성해서 add_fieldsets 옵션으로 필드 추가와 필드의 순서를 정해줌
  • 문제 2: password를 옵션에 넣지 않았을 때 비밀번호가 문자열 그대로 저장되었음
  • 해결방안: add_fieldsets 에 password1, 2 를 추가해 주어 비밀번호로 해싱 처리될 수 있도록 함
  • 문제 1: 메뉴를 새로 create 할 때 해시태그가 없으면 메뉴 생성이 되지 않는데 메뉴 create 화면에서 해시태그를 새로 만들어줄 수 없었던 문제
  • 해결방안: 임시방편으로 해시태그에 null=True, blank=True를 넣어주어 해시태그를 일단 생성한 뒤 메뉴 작성 시 선택가능하도록 수정
  • 문제 2: 메뉴 작성, 수정 시 모든 유저가 작성한 해시태그가 조회 가능했던 문제
  • 해결방안: staff의 경우 본인이 작성한 해시태그만 조회 가능하도록 수정
@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):

    def get_form(self, request, obj, **kwargs):
        form = super(MenuAdmin, self).get_form(request, obj, **kwargs)
        # print("form>>>>>>>>>>>", form)
        # print("dir>>>>>>>>>>>>>>>", dir(form))  #### 내부를 볼 수 있음..!!
        # print("base_fields >>>>>>>>>> ", form.base_fields)
        if request.user.is_superuser:
            form.base_fields['hashtags'].queryset = Hashtag.objects.all()
        elif request.user.is_staff:
            form.base_fields['hashtags'].queryset = Hashtag.objects.filter(hashtag_author_id=request.user)
        return form

get_form() 함수를 오버라이드해서 조건문으로 분기 처리해 줌.
여기서 print()문의 경우 튜터님께서 도와주신 흔적..

HashtagAdmin 생성

  • 문제 1: 해시태그 create 시 작성 유저를 아무나 선택할 수 있었던 문제
  • 해결방안:HashtagAdmin에서 readonly_fields=("hashtag_authors",) 를 추가해주어 수정 불가하도록 하고, save_model() 함수를 오버라이드해서 로그인한 작성자의 이름이 자동으로 입력되도록 수정
  • 문제 2: 해시태그 수정 페이지에서 해당 해시태그를 가지고 있는 메뉴가 하나만 조회되는 문제
  • 해결방안: (팀원이 해결) 수정 페이지에서 메뉴를 조회하게 하지 않도록 하고 메뉴에 대한 해시태그는 메뉴에서만 수정 가능하도록 바꾸면서 Hashtag 모델에 있던 menu 필드를 삭제해줌. 기존에 불러오던 manytomany 테이블을 사용하지 않고 Menu 테이블에서 hashtags 필드를 참조해 불러옴. 대신 해시태그 리스트에서 해당 해시태그의 메뉴가 무엇인지 볼 수 있도록 하기 위해서 오브젝트를 가지고 와서 문자열로 변환해 뿌려줌.
## 메뉴에서 해당 메뉴의 해시태그를 모두 조회
@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):
    readonly_fields = ("store", "store_id")
    list_display = ("food_name", "price", "get_hashtags")
    search_fields = ("food_name", "price")
    
    def get_hashtags(self, obj):
        return ", ".join([hashtag.hashtag for hashtag in obj.hashtags.all()])

    get_hashtags.short_description = "Hashtags" ## 리스트에서 테이블 헤드 역할
    
    
## 해시태그에서 해당 해시태그를 가진 메뉴들 조회    
@admin.register(Hashtag)
class HashtagAdmin(admin.ModelAdmin):
    readonly_fields = ("hashtag_author",)
    list_display = ("hashtag", "hashtag_author", "get_menus")
    list_filter = ("hashtag_author",)
    
    def get_menus(self, obj):
    return ", ".join([menu.food_name for menu in obj.menu_items.all()])

    get_menus.short_description = "Menus" ## 리스트에서 테이블 헤드 역할

오늘의 새 지식

함수를 타고 들어가는 방법

@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):

    def get_form(self, request, obj, **kwargs):
        form = super(MenuAdmin, self).get_form(request, obj, **kwargs)
        # print("form>>>>>>>>>>>", form)
        # print("dir>>>>>>>>>>>>>>>", dir(form))  #### 내부를 볼 수 있음..!!
        # print("base_fields >>>>>>>>>> ", form.base_fields)
        if request.user.is_superuser:
            form.base_fields['hashtags'].queryset = Hashtag.objects.all()
        elif request.user.is_staff:
            form.base_fields['hashtags'].queryset = Hashtag.objects.filter(hashtag_author_id=request.user)
        return form

이 코드에서 주석 처리된 부분이 튜터님께 질문하러 갔을 때 단계 별로 도와주신 부분.
원래 return super().get_form(request, obj, **kwargs) 로 써 두었는데
1. form 으로 super().~ 부분을 받아줌
2. form이 잘 받아와지는지 프린트로 찍어봄

form>>>>>>>>>>> <class 'django.forms.widgets.MenuForm'>
  1. 해당 form 의 안쪽을 보기 위해서 dir() 함수를 프린트 해 봄
dir>>>>>>>>>>>>>>> ['Meta', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__html__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bound_items', '_clean_fields', '_clean_form', '_get_validation_exclusions', '_html_output', '_meta', '_post_clean', '_save_m2m', '_update_errors', '_widget_data_value', 'add_error', 'add_initial_prefix', 'add_prefix', 'as_div', 'as_p', 'as_table', 'as_ul', 'base_fields', 'changed_data', 'clean', 'declared_fields', 'default_renderer', 'errors', 'field_order', 'full_clean', 'get_context', 'get_initial_for_field', 'has_changed', 'has_error', 'hidden_fields', 'is_multipart', 'is_valid', 'media', 'non_field_errors', 'order_fields', 'prefix', 'render', 'save', 'template_name', 'template_name_div', 'template_name_label', 'template_name_p', 'template_name_table', 'template_name_ul', 'use_required_attribute', 'validate_unique', 'visible_fields']
  1. 어떤 함수가 해당될 지 확인. 여기서 튜터님은 hashtag가 있는지 여쭤보셨고, 없으니 base_fields 를 보아야 할 것 같다고 하심

  2. base_fields 를 프린트 해봄

base_fields >>>>>>>>>>  {'food_name': <django.forms.fields.CharField object at 0x10787e4a0>, 'price': <django.forms.fields.IntegerField object at 0x10787e650>, 'hashtags': <django.forms.models.ModelMultipleChoiceField object at 0x10787e740>}
  1. 여기서 조회된 필드는 food_name, price, hashtags 여서 form의 base_fields 에서 hashtags를 쿼리셋으로 하고, Hashtag.objects.all()로 모든 해시태그를 불러오거나 Hashtag.objects.filter(hashtag_author_id=request.user) 로 해당되는 유저가 작성한 해시태그만 불러오도록 함.

튜터님이 젭으로 보내주신 코드는 form.base_fields['user'].queryset = Hashtag.objects.filter(....) 였고 95% 다 알려주신 거라고 하셨는데 실질적으로는 98% 정도 알려주신 거였다...

profile
발전 중...

0개의 댓글