USER

django 가 서버가 켜질 때 초기화 순서

  1. INSTALLED_APPS의 각 항목을 imports 합니다.(위에서 아래로)
    • 이 과정에서 직간접적으로 모델을 import 해서는 안된다.
    • 1번 단계에서 app을 import 하는 동안에 불필요한 제약들을 피하기 위해 이 단계에서는 모델을 가져오지 않는다.
  2. 각 어플리케이션의 models를 import한다.
    • 2단계가 완료가 되면, get_model()과 같은 모델에서 작동하는 APIs를 사용할 수 있게 된다.
  3. AppConfigready() 메서드를 실행한다.

  1. 1단계에서 artricles부터 import 시작
  2. 2단계에서 articles 부터 model을 import 시작
  3. 2단계에서 accounts에서 mdel을 import 시작
    • 2단계가 완료된 후에야 get_user_model()을 사용할 수 있는데 아직 accounts app이 INSTALLED APP의 작성 순서 때문에 아직 IMPORT 가 완료되지 않은 상황이기 때문에, get_user_model()이 어떤 User model을 return 해야 하는지 django가 알 수 없는 상태이다.

get_user_model()

  • return 값이 class

settings.AUTH_USER_MODEL

  • return 값이 str

:warning: 결론

  • 모든 곳에서 User Model을 호출 할 때는 get_user_model()
  • 단, models.py에서만 settings.AUTH_USER_MODEL

컬럼 추가할 때 !

$ python manage.py makemigrations
You are trying to add a non-nullable field 'user' to article without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py

이러한 상황에 놓인다.

1번은 추가 할 컬럼의 내용을 뭘 채울 것이냐 묻는 것

2번은 취소

sqlite3 db 확인

sqldb

이런 상태로 변경

after_sqldb

gravatar 프로필 이미지

  1. 사용하기 위한 회원가입 후
    1. Model Custom
    2. Custom tmeplate tags and filters
  2. django에 적용하기

django에 적용하기

  1. hash 생성
#articles.views.py
import hashlib
#-------------------- hashlib // gravatar-----------------------
if request.user.is_authenticated:
    gravatar_url = hashlib.md5(request.user.email.encode('utf-8').lower().strip()).hexdigest()
else:
    gravatar_url = None
  • views에만 작성하면, 다른 페이지에는 적용 x, => account로 넘겨서 범용성 확대
#accounts.form.py 에 추가할 내용
#----- Custom 하기 (원하는 내용만을 조작하기 위함)
from django.contrib.auth.forms import UserCreationForm

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        fields = UserCreationForm.Meta.fields + ('email',)
#accounts.views.py
# UserCreationForm => CustomUserCreationForm으로 변경
from .forms import CustomUserCreationForm

def signup(request):
    if request.user.is_authenticated:
        return redirect('articles:index')
   
    if request.method == 'POST':
        # embed()
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            # form.save() 를 통해 변환된 user 클래스의 인스턴스를 auth_login의 인자로 전달
            user = form.save()
            auth_login(request, user)

            return redirect('articles:index')
    else:
        form = CustomUserCreationForm()
    context = {'form': form}
    return render(request, 'accounts/auth_forms.html', context)
  1. gravatar 이미지 요청

    • base.html 파일에 필요한 코드 작성
    ...
       
    {% load gravatar %}
       
    <img src="https://s.gravatar.com/avatar/?s=80" alt="gravatar">
       
    ...
    
    • templatetags파일 생성 및 관련 py 파일 생성
    articles or accounts
    |____
    |    |
    |    __init__.py
    |    |
    |    gravatar.py
    
    import hashlib
    from django import template
       
    register = template.Library() # 기존 template 라이브러리에 아래의 함수를 추가한다.
       
       
    @register.filter # 이 부분!
    def makemd5(email): # 함수 앞에 인자 
        return hashlib.md5(email.encode('utf-8').lower().strip()).hexdigest()
    

M:N

Model relationships

  1. Many to one
  2. Many to many

User : Article = M : N

  • User는 여러 개의 Article에 Like 할수 있고,
  • Article은 여러 user 로부터 Like 받을 수 있다.

의사와 환자

모델링은 현실 세계를 최대한 유사하게 반영하기 위해서 해야 한다.

환자와 의사의 예약 시스템을 구축하라는 프로젝트

의사 1 : 환자 N

  1. 1:N의 한계

    In [1]: doctor1 = Doctor.objects.create(name='justin')
       
    In [2]: doctor2 = Doctor.objects.create(name='zzulu')
       
    In [3]: patient1 = Patient.objects.create(name='tak', doctor=docotr1)
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-3-31b2c7054c93> in <module>
    ----> 1 patient1 = Patient.objects.create(name='tak', doctor=docotr1)
       
    NameError: name 'docotr1' is not defined
       
    In [4]: patient1 = Patient.objects.create(name='tak', doctor=doctor1)
       
    In [5]: patient2 = Patient.objects.create(name'harry', doctor=doctor2)
      File "<ipython-input-5-420201ce078f>", line 1
        patient2 = Patient.objects.create(name'harry', doctor=doctor2)
                                                    ^
    SyntaxError: invalid syntax
       
       
    In [6]: patient2 = Patient.objects.create(name='harry', doctor=doctor2)
       
    In [7]: doctor1
    Out[7]: <Doctor: 1번 의사 justin>
       
    In [8]: doctor2
    Out[8]: <Doctor: 2번 의사 zzulu>
       
    In [9]: patient1
    Out[9]: <Patient: 1번 환자 tak>
       
    In [10]: patient3 = Patient.objects.create(name='tak', docotr=doctor2)
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-10-7a8d757e3c08> in <module>
    ----> 1 patient3 = Patient.objects.create(name='tak', docotr=doctor2)
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)
         80         def create_method(name, method):
         81             def manager_method(self, *args, **kwargs):
    ---> 82                 return getattr(self.get_queryset(), name)(*args, **kwargs)
         83             manager_method.__name__ = method.__name__
         84             manager_method.__doc__ = method.__doc__
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\query.py in create(self, **kwargs)
        418         and returning the created object.
        419         """
    --> 420         obj = self.model(**kwargs)
        421         self._for_write = True
        422         obj.save(force_insert=True, using=self.db)
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\base.py in __init__(self, *args, **kwargs)
        499                     pass
        500             for kwarg in kwargs:
    --> 501                 raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
        502         super().__init__()
        503         post_init.send(sender=cls, instance=self)
       
    TypeError: Patient() got an unexpected keyword argument 'docotr'
       
    In [11]: patient3 = Patient.objects.create(name='tak', doctor=doctor2)
       
    In [12]: patient3.doctor.name
    Out[12]: 'zzulu'
       
    In [13]: patient4 = Patient.objects.create(name='harry', doctor=doctor1)
       
    In [14]: patient4
    Out[14]: <Patient: 4번 환자 harry>
       
    In [15]: patient4 = Patient.objects.create(name='harry', doctor=doctor1, docotr=doctor2)
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-15-9d06ea59f86c> in <module>
    ----> 1 patient4 = Patient.objects.create(name='harry', doctor=doctor1, docotr=doctor2)
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)
         80         def create_method(name, method):
         81             def manager_method(self, *args, **kwargs):
    ---> 82                 return getattr(self.get_queryset(), name)(*args, **kwargs)
         83             manager_method.__name__ = method.__name__
         84             manager_method.__doc__ = method.__doc__
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\query.py in create(self, **kwargs)
        418         and returning the created object.
        419         """
    --> 420         obj = self.model(**kwargs)
        421         self._for_write = True
        422         obj.save(force_insert=True, using=self.db)
       
    ~\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\base.py in __init__(self, *args, **kwargs)
        499                     pass
        500             for kwarg in kwargs:
    --> 501                 raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
        502         super().__init__()
        503         post_init.send(sender=cls, instance=self)
       
    TypeError: Patient() got an unexpected keyword argument 'docotr'
       
    In [16]: patient4 = Patient.objects.create(name='harry', doctor=doctor1, doctor=doctor2)
      File "<ipython-input-16-2775590f4f3f>", line 1
        patient4 = Patient.objects.create(name='harry', doctor=doctor1, doctor=doctor2)
                                                                       ^
    SyntaxError: keyword argument repeated
       
    
  2. 중개모델 생성

  3. 중개모델을 직접 거치지 않고 바로 가져올 수는 없을까?

    • Through option
    • MTOM 필드는 실제 물리적인 필드가 db에 생기는 것이 아니다.
  4. Doctor도 patients로 참조할 수 없을까??

    • related_name
      • 참조되는 대상이 참조하는 대상을 찾을 때(역참조), 어떻게 불러올지에 대해 정의 한다.
      • 필수적으로 사용하는 건 아니지만, 사용해야할(필수적인) 상황이 발생할 수 있다.

    중개 모델을 쓸 필요 없는가? 아니다.

    • 예약한 시간 정보를 담는가더나 하는 경우( 추가적인 필드가 필요한 경우)에는 반드시 중개모델을 만들어서 진행을 해야하되는 상황도 있다. 다만, 그럴 필요가 없는경우 위와 같이 해결할 수 있다.

Like

  • user는 여러 article에 좋아요를 누를 수 있고,
  • article은 여러 user로부터 좋아요를 받을 수 있다.
    • article.user: 게시글을 작성한 유저 - 1:N
    • airticle.like_users : 게시글을 좋아요한 유저 - M:M
    • user.like_articles : 유저가 좋아요를 누른 게시글 (역참조, related_name) - M:N
    • user.article_set : 유저가 작성한 게시글(역참조) - 1:N