USER 1:N M:N
USER
django 가 서버가 켜질 때 초기화 순서
INSTALLED_APPS
의 각 항목을 imports 합니다.(위에서 아래로)- 이 과정에서 직간접적으로 모델을 import 해서는 안된다.
- 1번 단계에서 app을 import 하는 동안에 불필요한 제약들을 피하기 위해 이 단계에서는 모델을 가져오지 않는다.
- 각 어플리케이션의 models를 import한다.
- 2단계가 완료가 되면,
get_model()
과 같은 모델에서 작동하는 APIs를 사용할 수 있게 된다.
- 2단계가 완료가 되면,
AppConfig
의ready()
메서드를 실행한다.
- 1단계에서 artricles부터 import 시작
- 2단계에서 articles 부터 model을 import 시작
- 2단계에서 accounts에서 mdel을 import 시작
- 2단계가 완료된 후에야
get_user_model()
을 사용할 수 있는데 아직 accounts app이 INSTALLED APP의 작성 순서 때문에 아직 IMPORT 가 완료되지 않은 상황이기 때문에,get_user_model()
이 어떤 User model을 return 해야 하는지 django가 알 수 없는 상태이다.
- 2단계가 완료된 후에야
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 확인
이런 상태로 변경
gravatar 프로필 이미지
- 사용하기 위한 회원가입 후
- Model Custom
- Custom tmeplate tags and filters
- django에 적용하기
django에 적용하기
- 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)
-
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
- Many to one
- Many to many
User : Article = M : N
- User는 여러 개의 Article에 Like 할수 있고,
- Article은 여러 user 로부터 Like 받을 수 있다.
의사와 환자
모델링은 현실 세계를 최대한 유사하게 반영하기 위해서 해야 한다.
환자와 의사의 예약 시스템을 구축하라는 프로젝트
의사 1 : 환자 N
-
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
-
중개모델 생성
-
중개모델을 직접 거치지 않고 바로 가져올 수는 없을까?
Through option
MTOM
필드는 실제 물리적인 필드가 db에 생기는 것이 아니다.
-
Doctor도 patients로 참조할 수 없을까??
related_name
- 참조되는 대상이 참조하는 대상을 찾을 때(역참조), 어떻게 불러올지에 대해 정의 한다.
- 필수적으로 사용하는 건 아니지만, 사용해야할(필수적인) 상황이 발생할 수 있다.
중개 모델을 쓸 필요 없는가? 아니다.
- 예약한 시간 정보를 담는가더나 하는 경우( 추가적인 필드가 필요한 경우)에는 반드시 중개모델을 만들어서 진행을 해야하되는 상황도 있다. 다만, 그럴 필요가 없는경우 위와 같이 해결할 수 있다.
Like
- user는 여러 article에 좋아요를 누를 수 있고,
- article은 여러 user로부터 좋아요를 받을 수 있다.
article.user
: 게시글을 작성한 유저 - 1:Nairticle.like_users
: 게시글을 좋아요한 유저 - M:Muser.like_articles
: 유저가 좋아요를 누른 게시글 (역참조, related_name) - M:Nuser.article_set
: 유저가 작성한 게시글(역참조) - 1:N