댓글과 유저를 Foregin Key로 연결하기
- Comment 모델에 User 모델을 참조하는 외래키 작성
# articles/models.py
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
- CommentForm 출력을 확인해보면 불필요한 필드인 user가 드롭다운으로 출력됨
- user 필드에 작성해야하는 user 객체는 view 함수의 request 객체를 활용해야함
- CommentForm의 출력필드 수정
class CommentForm(forms.ModelForm):
...
...
exclude = ('article', 'user')
- 댓글 작성 시 작성자 정보가 함께 저장될 수 있도록 save의 commit 옵션을 활용
def comments_create(request, pk):
...
...
if comment_form.is_valid():
...
comment.user = request.user
comment.save()
- 작성자를 출력하기 위해서는 detail 템플릿에서 코드 추가
{{comment.user}}
{% if request.user == comment.user %}
- view의 comments_delete 함수에서 if 문 추가
def comments_delete(request, pk, comment_pk):
...
if request.user == comment.user:
comment.delete()
인증된 사용자인 경우만 댓글 작성 및 삭제
- comments_create
@require_POST
def comments_create(request, pk):
if request.user.is_authenticated:
article = Article.objects.get(pk=pk)
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
comment = comment_form.save(commit=False)
comment.article = article
comment.user = request.user
comment.save()
return redirect('articles:detail', article.pk)
return redirect('accounts:login')
- comments_delete
@require_POST
def comments_delete(request, article_pk, comment_pk):
if request.user.is_authenticated:
comment = Comment.objects.get(pk=comment_pk)
if request.user == comment.user:
comment.delete()
return redirect('articles:detail', article_pk)
- CommentForm 가리기
{% if request.user.is_authenticated %}
<form action = "{% url ... %}" ...>
...
</form>
{% else %}
...
{% endif %}
Many to many relationship
예시로, 의사와 환자간 예약 시스템을 구현
1) 중개 테이블 직접 구성
doctor, patient, reservation 테이블을 foreign key로 이음
2) ManyToManyField로 중개 테이블 자동 생성
class Patient(models.Model):
doctors = models.ManyToManyField(Doctor)
name = models.TextField()
def __str__(self):
return f'{self.pk}번 환자 {self.name}'
- 테스트
doctor1 = Doctor.objects.create(name='alice')
patient1 = Patient.objects.create(name='carol')
patient2 = Patient.objects.create(name='dane')
# patient1이 doctor1에게 예약
patient1.doctors.add(doctor1)
# patient1이 예약한 의사 목록 확인
patient1.doctors.all()
# doctor1에게 예약된 환자 목록 확인
doctor1.patient_set.all()
# doctor1이 patient2를 예약
doctor1.patient_set.add(patient2)
# doctor1이 patient1 진료 예약 취소
doctor1.patient_set.remove(patient1)
# patient2가 doctor1 진료 예약 취소
patient2.doctors.remove(doctor1)
- ‘related_name’ argument
- target model이 source model을 참조할 때 사용할 manager name
- ForeignKey()의 related_name과 동일
class Patient(models.Model):
doctor = models.ManyToManyField(Doctor, related_name='patients')
# 기존에는 patient_set으로 접근 가능했음
3)ManyToManyField를 사용하고 중개모델은 직접 구성
- through 설정 몇 Reservation Class 수정
- 보통 추가데이터필드를 넣기 위해 사용
class Patient(models.Model):
doctors = models.ManyToManyField(Doctor, through='Reservation')
name = models.TextField()
...
class Reservation(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CAASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
symptom = models.TextField()
reserved_at = models.DateTimeField(auto_now_add=True)
# 1. Reservation class를 통한 예약 생성
reservation1 = Reservation(doctor=doctor1, patient=patient1, symptom='headache')
reservation1.save()
# 2. Patient 객체를 통한 예약 생성
patient2.doctors.add(doctor1, through_defaults={'symptom':'flu'})
# 3. 예약 삭제
doctor1.patient_set.remove(patient1)
patient2.doctors.remove(doctor1)
'Programming Language > SQLite' 카테고리의 다른 글
SQLite_06)Fixtures (0) | 2023.04.12 |
---|---|
SQLite_05)Foreign Key_3 (0) | 2023.04.12 |
SQLite_03)Foreign Key_1 (0) | 2023.04.12 |
SQLite_02)CRUD (0) | 2023.04.12 |
SQLite_01)Set up & Basics (0) | 2023.04.12 |