* hospital/models.py
class Doctor(models.Model):
name =models.TextField()
def __str__(self):
return f'{self.pk}번 의사 {self.name}'
class Patient(models.Model):
name = models.TextField()
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
def __str__(self):
return f'{self.pk}번 환자 {self.name}
* python manage.py shell_plus
In [1]: doctor1 = Doctor.objects.create(name='jstin')
In [2]: doctor2 = Doctor.objects.create(name='eric')
In [3]: patient1 = Patient.objects.create(name='tony',doctor=doctor1)
In [4]: patient2 = Patient.objects.create(name='harry',doctor=doctor2)
In [5]: doctor1 // Out[5]: <Doctor: 1번 의사 jstin>
In [7]: patient1 // Out[7]: <Patient: 1번 환자 tony>
→ 새로 만들었어야 했다.
In [9]: patient3 = Patient.objects.create(name='tony',doctor=doctor2)
* hospital/models.py
class Doctor(models.Model):
name = models.TextField()
def __str__(self):
return f'{self.pk}번 의사 {self.name}'
class Patient(models.Model):
name = models.TextField()
def __str__(self):
return f'{self.pk}번 환자 {self.name}'
# 중개모델 작성
class Reservation(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
def __str__(self):
return f'{self.doctor_id}번 의사의 {self.patient_id}번 환자'
* python manage.py shell_plus
In [1]: doctor1 = Doctor.objects.create(name='justin')
In [2]: patient1 = Patient.objects.create(name='tony')
In [3]: **Reservation.objects.create(**doctor=doctor1,patient=patient1**)**
Out[3]: <Reservation: 1번 의사의 1번 환자>
* **의사가 환자 기록 확인하기**
In [4]**: doctor1.reservation_set.all()**
Out[4]: <QuerySet [<Reservation: 1번 의사의 1번 환자>]>
* **환자가 의사 기록 확인하기**
In [5]: **patient1.reservation_set.all()**
Out[5]: ****<QuerySet [<Reservation: 1번 의사의 1번 환자>]>
****
* hospital/models.py
from django.db import models
class Doctor(models.Model):
name = models.TextField()
def __str__(self):
return f'{self.pk}번 의사 {self.name}'
class Patient(models.Model):
name = models.TextField()
# ManyToManyField 작성
**doctors = models.ManyToManyField(Doctor)**
ㄴ> 복수인 이유는 단수인 foreign키와 차별을 주기위해서
def __str__(self):
return f'{self.pk}번 환자 {self.name}'
* python manage.py shell_plus
In [1]: doctor1 = Doctor.objects.create(name='justin')
In [2]: patient1 = Patient.objects.create(name='tony')
In [3]: patient2 = Patient.objects.create(name='harry')
- 환자가 의사 예약하기
In [4]: **patient1.doctors.add(doctor1)
-** 의사가 환자 목록보기
In [6]: doctor1.**patient_set**.all() // Out[6]: <QuerySet [<Patient: 1번 환자 tony>]>
**-** 의사가 환자 예약하기
In [7]: doctor1.**patient_set**.add(patient2)
- 의사가 환자 예약 취소하기
In [8]: doctor1.patient_set.**remove**(patient2)
- 환자가 의사 예약 취소하기
In [9]: patient1.doctors.remove(doctor1)
patient_set 쓰기 귀찮다 ->
doctors = models.ManyToManyField(Doctor,**related_name='patient'**)
In [3]: doctor1.patient.all() // Out[3]: <QuerySet []>
class Doctor(models.Model):
name = models.TextField()
def __str__(self):
return f'{self.pk}번 의사 {self.name}'
class Patient(models.Model):
doctors = models.ManyToManyField(Doctor, **through='Reservation'**)
name = models.TextField()
def __str__(self):
return f'{self.pk}번 환자 {self.name}'
class Reservation(models.Model):
**doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE) 다대다 에서의
patient = models.ForeignKey(Patient, on_delete=models.CASCADE) 중개 테이블**
**symptom =** models.TextField()
**reserved_at =** models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.doctor.pk}번 의사의 {self.patient.pk}번 환자'
* python manage.py shell_plus
In [1]: doctor1 = Doctor.objects.create(name='justin')
In [2]: patient1 = Patient.objects.create(name='tony')
In [4]: patient2 = Patient.objects.create(name='harry')
In [5]: reservation1 = **Reservation**(doctor=doctor1,patient=patient1,**symptom='headache'**)
In [8]: reservation1**.save()** 저장을 해줘야한다.
In [12]: patient2.doctors.add(doctor1,through_defaults={'symptom':'flu'})
In [14]: Reservation.objects.all()
Out[14]: <QuerySet [<Reservation: 1번 의사의 1번 환자>, <Reservation: 1번 의사의 2번 환자>]>
In [19]: patient2.doctors.remove(doctor1)
MtoM 사용시 1:N에서의 manager 이름 → ex) article.user_set 이 중복되기 때문에
related_name='' 으로 바꿔주는게 필수
class Article(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
like_users = models.ManyToManyField(settings.AUTH_USER_MODEL, **related_name='like_articles'**)
title = models.CharField(max_length=10)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
content = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.content
path('<int:article_pk>/likes/',views.likes,name='likes'),
def likes(request,article_pk):
article = get_object_or_404(Article,pk=article_pk)
현재 좋아요를 요청하는 회원(request.user)이
해당 게시물의 좋아요를 누른 회원 목록에 있다면,
**if article.like_users.filter(pk=request.user.pk).exists():**
# == if request.user in article.like_users.all() : 좋아요 취소
article.like_users.remove(request.user)
else: # 좋아요 하기
article.like_users.add(request.user)
return redirect()
if request.user in article.like_users.all() 이렇게 써도 되지만
if article.like_users.filter(pk=request.user.pk).exists(): 가 더 권장된다.
왜 ? → 규모가 큰 QuerySet의 특정 개체 존재 여부확인에 더 적합
@require_POST **추가코드 작성**
def likes(request,article_pk):
# if request.user.is_authenticated():
article = get_object_or_404(Article,pk=article_pk)
# 현재 좋아요를 요청하는 회원(request.user)이
# 해당 게시물의 좋아요를 누른 회원 목록에 있다면,
if article.like_users.filter(pk=request.user.pk).exists():
# if request.user in article.like_users.all() : # 좋아요 취소
article.like_users.remove(request.user)
else: # 좋아요 하기
article.like_users.add(request.user)
return redirect('articles:index')
# return redirect('accounts:login')
<div>
<form action="{% url 'articles:likes' article.pk %}" method='POST'>
{% csrf_token %}
{% if user in article.like_users.all %}
<input type="submit" value='좋아요 취소'>
{% else %}
<input type="submit" value='좋아요'>
{% endif %}
</form>
</div>
* accounts/urls.py
path('<username>/',views.profile,name='profile'),
* accounts/views.py
def profile(request,username):
person = get_object_or_404(get_user_model(),username=username)
context ={
'person':person
}
return render(request,'accounts/profile.html',context)
* base.html
<p>작성자 : <a href="{% url 'accounts:profile' article.user.username %}">{{ article.user }}</a></p>
* accounts/models.py
class User(AbstractUser):
followings = models.ManyToManyField('self',symmetrical=False,related_name='followers')
symmetrical =True(기본값) 으로 되어 있을 때는 a>b 일경우 b>a 까지 같이된다.
그래서 False로 바꿔줘야 한다.
* accounts/views
def follow(request,user_pk): me you 로 만들면 재밌음
me = requets.user
person (you)= get_object_or_404(get_user_model(),pk=user_pk)
# 내가 상대방의 팔로워 목록에 잇다면
if person.followers.filter(pk=request.user.pk).exists():
# if request.user in person.followers.all():
person.followers.remove(request.user)
else:
person.followers.add(request.user)
return redirect('accounts:profile', person.username)
@require_POST
def follow(request,user_pk):
if request.is_authenticated():
person = get_object_or_404(get_user_model(),pk=user_pk)
if request.user != person:
# 내가 상대방의 팔로워 목록에 잇다면
if person.followers.filter(pk=request.user.pk).exists():
# if request.user in person.followers.all():
person.followers.remove(request.user)
else:
person.followers.add(request.user)
return redirect('accounts:profile', person.username)
# 언팔로우
# 없다면 팔로우
else:
return redirect('accounts:login')
**{% with followings=person.followings.all followers=person.followers.all %}**
<h1>{{person.username}} 의 프로필 페이지</h1>
<div>
<div> 팔로잉 수 : {{followings|length}} / 팔로워 수 : {{followers|length}} </div>
</div>
{% if user != person %}
<div>
<form action="{% url 'accounts:follow' person.pk %}" method='POST'>
{% csrf_token %}
{% if user in followers %}
<input type="submit" value='언팔로우'>
{% else %}
<input type="submit" value='팔로우'>
{% endif %}
</form>
</div>
{% endif %}
{% endwith %}
<hr>