* articles/models
class Comment(models.Model):
**article = models.ForeignKey(Article, 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
article이라는 이름으로 만들면 DB에는 article_id 라는 번호가 저장된다
* python manage.py shell_plus
In [1]: comment = Comment()
In [2]: comment.content ='first comment'
In [3]: comment.save() ----> error (NOT NULL)
-------------------------------------------------------------
In [4]: article = Article.objects.create(title='title',content='content')
In [7]: comment.article = article
In [8]: comment.save()
In [9]: comment
Out[9]: <Comment: first comment>
In [10]: comment = Comment(content='second comment',article=article)
In [11]: comment.save()
In [12]: comment.pk
Out[12]: 2
* articles/admin.py
admin.site.register(Comment)
article.comment 형태로 사용이 불가
article.comment_set manager가 생성됨
In [1]: article = Article.objects.get(pk=1)
In [2]: article
Out[2]: <Article: title>
In [4]: article.**comment_set**.all()
Out[4]: <QuerySet [<Comment: first comment>, <Comment: second comment>]>
→ 귀찮다 이름을 바꾸자
* articles/models
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE**,related_name='comments'**)
* articles/forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = '__all__'
* articles/views.py
from .forms import CommentForm
def detail(request, pk):
article = get_object_or_404(Article, pk=pk)
comment_form = CommentForm()
context = {
'article': article,
'comment_form':comment_form
}
return render(request, 'articles/detail.html', context)
* articles/forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
# fields = '__all__'
exclude =('article',)
* articles/views
@require_POST
def comments_create(request,pk):
if request.is_authenticated:
article =get_object_or_404(Article,pk=pk)
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
**comment = comment_form.save(commit=False)
comment.article = article
comment.save()**
return redirect('articles:detail',article.pk)
return redirect('accounts:login')
commit =False
→ 아직 데이터베이스에 저장되지 않은 인스턴스를 반환
→ 저장하기 전에 객체에 대한 사용자 지정 처리를 수행할 때 유용
* articles/views
@require_safe
def detail(request, pk):
article = get_object_or_404(Article, pk=pk)
comment_form = CommentForm()
comments = article.comment_set.all()
context = {
'article': article,
'comment_form':comment_form,
'comments':comments,
}
return render(request, 'articles/detail.html', context)
* articles/urls.py
path('<int:article_pk>/comments/<int:comment_pk>/delete',views.comments_delete,name='comments_delete'),
* articles/views.py
@require_POST
def comments_delete(request,article_pk,comment_pk):
if request.is_authenticated:
comment = get_object_or_404(Comment,pk=comment_pk)
comment.delete()
return redirect('articles:detail',**article_pk**)
article의 pk로 돌아가고 싶은데 comment에서 그것을 가져오기는 어렵다
→ url에서 pk값을 comment pk 와 article pk 두개를 들고오게 한다.
* articles/detail.html
<h4>**댓글 목록**</h4>
<ul>
{% for comment in comments %}
<li>
{{comment.content}}
**댓글 삭제**
<form action="{% url 'articles:comments_delete' article.pk comment.pk %}"method='POST' class='d-inline'>
{% csrf_token %}
<input type="submit" value='DELETE'>
</form>
</li>
{% endfor %}
</ul>
<h4>**댓글 작성**</h4>
<form action="{% url 'articles:comments_create' article.pk %}" method ='POST'>
{% csrf_token %}
{{ comment_form}}
<input type="submit">
</form>
* detail.html
<h4>댓글 목록</h4>
{% if comments %}
<p><b>{{comments|length}}개의 댓글이 있습니다.</b></p>
{% endif %}
{% empty %} 없을때는 for 문 사이에
<p>댓글이 없어요</p>
내장 User 모델이 제공하는 인증 요구사항이 적절하지 않을 수 있다.
커스텀 유저 모델을 초기에 설정하는 것을 권장한다
* settings.py
AUTH_USER_MODEL = 'accounts.User' (맨밑)
* accounts/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
Custom을 하지 않더라도 반드시 하는 것을 권장한다.
* accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
# Register your models here.
admin.site.register(User,UserAdmin)
UserCreationForm , UserChangeForm 은
기존 내장 User 모델을 사용했기에 무조건 수정해서 사용해야한다.
* accounts/forms.py
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = ('email', 'first_name', 'last_name',)
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
fields= UserCreationForm.Meta.fields+('email',)
* accounts/view.py에서 form을 다 바꿔줘야한다
**-> form = CustomUserCreationForm()
-> form = CustomUserChangeForm()**
현재 프로젝트에서 활성화된 사용자 모델을 반환 == User?
→ get_user_model() 을 써야한다
→ 또한 유연성이 달라진다 (변경사항)