웹 프로그래밍: 프로필, 카테고리, 댓글 추가(5부)

웹 프로그래밍 프로필 및 카테고리 및 코멘트 추가(5부)

이전 Django 기반 Python 웹 프로그래밍 포스팅에서 업로드된 포스트에 삭제 기능과 로그인 기능을 추가했습니다. 이번에는 블로그의 기본 요소인 프로필과 포스트를 구분하는 카테고리와 댓글 기능을 추가해 보겠습니다. 이제 웹 프로그래밍에 대한 포스팅을 시작해서 프로필, 카테고리, 댓글을 추가하겠습니다(5부).

1. 프로필 및 카테고리, 댓글 프로필 및 카테고리, 댓글 위에 언급한 세 가지 기능은 게시물 업로드 및 로그인 기능을 제외한 블로그 운영에 가장 기본적인 기능입니다. 이번에는 스타일 시트 영역을 건드리지 않겠습니다. 지금은 블로그라고 부르기에는 너무 기능이 부족하고 UI와 UX도 형편없지만 프런트엔드와 백엔드 영역을 구현한 후 UI/UX를 개선하여 블로그라는 단어에 맞게 어느 정도 기능할 수 있도록 할 예정이니 참고하시기 바랍니다.

2. 프로필 관리 기능 프로필을 추가하려면 다른 기능을 구현할 때와 마찬가지로 프로필 기능을 구현하는 데 필요한 모델을 만들고, 새 사용자(계정)가 생성될 때마다 자동으로 기본 프로필을 만듭니다. 그런 다음 클라이언트가 프로필을 수정할 수 있는 페이지와 최소한의 인터페이스를 보고 사용할 수 있도록 템플릿을 만들고 URL을 매핑합니다. 이러한 단계를 거친 후 프로필 관리 기능이 추가됩니다. 아래 소스 코드를 참조하세요.

blog1/models.py(클래스 Profile)에 프로필 모델을 생성합니다.

from django.db import modelsfrom django.contrib.auth.models import Userfrom django.utils import timezoneclass Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(blank=True) location = models.CharField(max_length=30, blank=True) birth_date = models.DateField(null=True, blank=True) def __str__(self):return self.user.username signals.py라는 이름의 파일을 만들고 아래 코드를 작성한 후 blog1 디렉터리에 저장합니다. 특수 문자 @가 있는 줄에 작성된 코드는 데코레이터로 간주할 수 있습니다. 작성한 데코레이터는 함수와 메서드에 추가 동작을 추가하는 코드로 생각할 수 있습니다. from django.db.models.signals import post_savefrom django.dispatch import receiverfrom django.contrib.auth.models import Userfrom .models import Profile@receiver(post_save, sender=User)def create_user_profile(sender, instance, created, **kwargs):if created: Profile.objects.create(user=instance)@receiver(post_save, sender=User)def save_user_profile(sender, instance, **kwargs): instance.profile.save() 다음과 같이 blog1/apps.py 파일에 코드를 작성합니다. 작성된 코드는 이전에 작성한 signals.py 파일을 프로젝트에 연결하기 위한 것이라고 생각할 수 있습니다. from django.apps import AppConfigclass Blog1Config(AppConfig): name = ‘blog1’ def ready(self):import blog1.signals 그런 다음 명령 프롬프트를 실행하고 프로젝트 디렉토리가 있는 경로로 이동하여 마이그레이션을 생성하고 적용합니다. blog1/forms.py와 같은 디렉토리에 있는 두 개의 파일 views.py에 프로필에 대한 코드를 추가합니다. forms.py from django import formsfrom .models import Post, Profileclass ProfileForm(forms.ModelForm):class Meta: model = Profile fields = (‘bio’, ‘location’, ‘birth_date’) views.py 아래 코드에서 볼 수 있듯이 프로필 콘텐츠 외에도 이 뷰는 이전에 사용한 데코레이터를 추가하여 이전에 생성된 페이지에는 로그인한 사용자만 액세스할 수 있도록 합니다. django.shortcuts에서 render, get_object_or_404, django.contrib.auth.models에서 리디렉션 가져오기 Userfrom .models 가져오기 Post, Profilefrom .forms 가져오기 PostForm, ProfileFormfrom django.contrib.auth.decorators에서 login_required 가져오기 def post_list(요청): posts = Post.objects.all().order_by(‘-created_at’) return render(요청, ‘blog1/post_list.html’, {‘posts’: posts}) def post_detail(요청, pk): post = get_object_or_404(게시물, pk=pk) return render(요청, ‘blog1/post_detail.html’, {‘post’: post}) def post_new(요청): if request.method == “POST”: form = PostForm(request.POST) if form.is_valid(): post = form.save(commit=False) post.save()return(‘post_detail’, pk=post.pk) else: form = PostForm()return(request, ‘blog1/post_edit.html’, {‘form’: form}) def post_edit(request, pk): post = get_object_or_404(Post, pk=pk) if request.method == “POST”: form = PostForm(request.POST, instance=post) if form.is_valid(): post = form.save(commit=False) post.save()return(‘post_detail’, pk=post.pk) else: form = PostForm(instance=post)return(request, ‘blog1/post_edit.html’, {‘form’: form}) def post_delete(request, pk): post = get_object_or_404(Post, pk=pk) if request.method == “POST”: post.delete()return react(‘post_list’)return render(request, ‘blog1/post_confirm_delete.html’, {‘post’: post})@login_requireddef edit_profile(request):if request.method == ‘POST’: form = ProfileForm(request.POST, instance=request.user.profile)if form.is_valid(): form.save()return react(‘profile’)else: form = ProfileForm(instance=request.user.profile)return render(request, ‘blog1/edit_profile.html’, {‘form’: form})@login_requireddef profile_view(request): profile = get_object_or_404(Profile, user=request.user)return render(request, ‘blog1/profile.html’, {‘profile’: profile}) 템플릿 및 URL 만들기다음 코드를 사용하여 매핑 프로필에 대한 템플릿을 만듭니다. 아래에서 blog1/templates/blog1 경로에 저장한 다음, 프로필 URL에 대한 패턴을 blog/urls.py 파일에 추가합니다. 템플릿 파일 이름은 profile과 edit_profile입니다. HTML(profile, edit_profile) 프로필 수정

프로필 수정

{% csrf_토큰 %}{{ 양식.as_p }}

blog1/urls.py django.urls에서 가져오기 pathfrom django.contrib.auth 가져오기 views as auth_viewsfrom .views 가져오기 post_list, post_detail, post_new, post_edit, post_delete, edit_profile, profile_viewurlpatterns = (path(‘login/’, auth_views.LoginView.as_view(), name=’login’),path(‘logout/’, auth_views.LogoutView.as_view(), name=’logout’),path(”, post_list, name=’post_list’),path(‘post//’, 게시물_세부_정보, 이름=’게시물_세부_정보’),경로(‘게시물/새 게시물/’, 게시물_새 게시물, 이름=’게시물_새 게시물’),경로(‘게시물//편집/’, 게시물_편집, 이름=’게시물_편집’),경로(‘게시물//delete/’, post_delete, name=’post_delete’),path(‘profile/edit/’, edit_profile, name=’edit_profile’),path(‘profile/’, profile_view, name=’profile’),) 이렇게 코드를 작성하고 서버를 실행하고 로그인하여 127.0.0.1:8000/profile/edit에 접속하면 왼쪽 이미지처럼 프로필을 편집할 수 있는 창이 나오는 것을 확인할 수 있고, 프로필 내용을 작성하여 저장하면 오른쪽 이미지처럼 작성한 프로필이 노출되는 것을 확인할 수 있습니다. Bio, Location, Birth date는 각각 자기소개, 거주지, 생년월일을 입력하기 위해 만들었습니다. 필드 이름 자체가 한글일 경우 호환성 문제로 오류가 발생할 가능성이 높아서 영어로 먼저 작성하였고, 프로젝트가 완료된 후 한글로 수정될 예정이니 참고해주시기 바랍니다. 3. Category 카테고리가 없으면 모든 업로드를 보려면 아래로 스크롤해야 하므로 가독성이 크게 떨어지고, 오래전에 업로드된 게시물을 찾는 것도 어렵습니다. 이를 해결하기 위해 카테고리가 절대적으로 필요합니다. 카테고리는 게시물 모델 코드, 뷰, 템플릿의 일부만 수정하면 쉽게 구현할 수 있습니다. blog1/models 게시물 모델에 카테고리 필드를 추가한 후 마이그레이션을 생성하여 적용합니다. 하지만 이전에 테스트 목적으로 작성해둔 게시물의 카테고리 값이 설정되어 있지 않아 마이그레이션을 생성할 수는 있었지만 적용되지 않았습니다. 처음에는 전체 DB를 해체하고 수정하는 것도 생각했지만 시간이 많이 걸릴 것 같아서 마이그레이션을 롤백하고 다시 시도했습니다. 명령 프롬프트에 아래의 코드를 작성하면 롤백이 가능하다는 점을 참고하세요. (롤백하면 업로드 및 프로필 데이터가 삭제됩니다.) python manage.py migrate blog1 zero from django.db import modelsfrom django.contrib.auth.models import Userfrom django.utils import timezoneclass Category(models.Model): name = models.CharField(max_length=100) def __str__(self):return self.nameclass Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() created_at = models.DateTimeField(default=timezone.now) updated_at = models.DateTimeField(auto_now=True) category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1) def __str__(self):return self.titleclass Profile(models.Model): user = models.OneToOneField(User,on_delete=models.CASCADE) bio = models.TextField(blank=True) location = models.CharField(max_length=30, blank=True) birth_date = models.DateField(null=True, blank=True) def __str__(self):return self.user.username HTML (post_list) 기존 post_list 코드를 다음과 같이 수정하여 카테고리를 표시합니다. 블로그 게시물

블로그 게시물

모든 카테고리

{% 게시물의 게시물에 대한 %}

{{ 게시물 제목 }}

{{ 게시물.내용|잘라내기단어:20 }}

{{게시물 ​​생성 시간 }}

{% 끝 %}

views.py마지막으로 blog1/view.py 파일에 아래 코드를 추가하고 카테고리에 대한 값을 삽입합니다. from django.shortcuts import render, get_object_or_404, directfrom django.contrib.auth.models import Userfrom .models import Post, Profile, Categoryfrom .forms import PostForm, ProfileFormfrom django.contrib.auth.decorators import login_requireddef post_list(request): category_id = request.GET.get(‘category’)if category_id: posts = Post.objects.filter(category_id=category_id).order_by(‘-created_at’)else: posts = Post.objects.all().order_by(‘-created_at’) categories = Category.objects.all()return render(request, ‘blog1/post_list.html’, {‘posts’: posts, ‘categories’: categories}) 서버를 시작하고 127.0.0.1:8000/admin에 액세스합니다. 액세스하는 경우페이지로 이동하여 로그인하면 BLOG1 앱에 Category 항목이 추가된 것을 확인할 수 있습니다. 오른쪽에 있는 Add 버튼을 클릭하여 원하는 이름으로 Category를 만듭니다. Category를 만든 후 127.0.0.1:8000/post/new/에 접속하면 오른쪽 이미지와 같이 Category를 선택할 수 있는 창이 보입니다. Post를 업로드한 후 127.0.0.1:8000에 접속하면 Category를 선택할 수 있는 텍스트가 보이고, 텍스트를 클릭하면 해당 Category로 이동하는 것을 확인할 수 있습니다. 4. Comments 많은 블로그의 가장 중요한 기능 중 하나가 Comments입니다. Comments는 다른 페이지와 마찬가지로 모델, 폼, 뷰를 추가한 후 이전에 만든 post_detail 템플릿을 수정하여 수정할 수 있습니다. blog1/models.py, forms.py blog1 디렉토리에 있는 models.py 파일의 맨 아래에 아래의 comment 모델 코드를 작성하여 저장한 후 마이그레이션을 생성하여 적용합니다. class Comment(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name=’comments’) author = models.CharField(max_length=100) text = models.TextField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self):return self.text 마이그레이션 후 forms.py 파일의 맨 아래에 아래 코드를 추가합니다. from django import formsfrom .models import Post, Profile, Commentclass CommentForm(forms.ModelForm):class Meta: model = Comment fields = (‘author’, ‘text’) blog1/views.py 뷰 파일에서 post_delete 영역의 코드를 수정하고 2번째 줄의 가져오기 영역에 Comment를 추가하여 댓글 기능을 구현하기 위해 작성한 코드를 로드할 수 있도록 합니다. django.shortcuts에서 render, get_object_or_404, .models에서 가져오기 Post, Profile, Category, Commentfrom .forms에서 가져오기 PostForm, ProfileForm, CommentFormfrom django.contrib.auth.decorators에서 가져오기 login_requireddef post_detail(요청, pk): post = get_object_or_404(게시물, pk=pk) comments = post.comments.all() request.method == ‘POST’인 경우 form = CommentForm(요청.POST) form.is_valid()인 경우 comment = form.save(commit=False) comment.post = post comment.user = request.user comment.save() ‘post_detail’, pk=post.pk를 리디렉션(redirect)으로 반환합니다. 그렇지 않으면 form = CommentForm() 요청, ‘blog1/post_detail.html’, { ‘post’: post, ‘comments’: comments, ‘form’:form}) HTML을 반환합니다. (post_detail) 이전에 작성하여 템플릿 디렉토리에 저장했던 post_detail의 코드를 아래와 같이 수정해 댓글 양식과 댓글 목록을 추가합니다. {{ 게시물 제목 }}

{{ 게시물 제목 }}

{{ 게시물.내용 }}

카테고리: {{ post.category.name }}

생성됨: {{ post.created_at }}

업데이트 시간: {{ post.updated_at }}

코멘트

{% for comment in comments %}

{{ comment.text }} – {{ comment.user.username }}님이 {{ comment.created_at }}에 게시함

{% 비어 있는 %}

아직 댓글이 없습니다.

{% 끝 %}

의견을 추가하다

{%csrf_토큰 %}{{ 양식.as_p }}

게시물로 돌아가기 위와 같이 코드를 작성하고 서버를 구동한 후 업로드된 게시글을 보면 아래 이미지처럼 댓글 쓰기 상자가 나오고, 댓글 업로드도 원활하게 되는 것을 확인할 수 있습니다. 5. 결론 이번 웹 프로그래밍, 프로필, 카테고리, 댓글 추가하기(5부) 게시글에서는 제목에서 알 수 있듯이 프로필, 카테고리, 댓글 기능을 추가했습니다. 다만 첫 문단에서 썼듯이 스타일시트 부분은 전혀 신경을 쓰지 않아 시각적인 부분에서는 조금 부족해 보이지만, 조금씩 완성되어 가는 듯합니다. 다음 게시글에서는 다른 기능을 구현하거나 UI/UX 부분을 개선하겠습니다. 이전과 마찬가지로 이 게시글의 내용은 GitHub에 새로 업로드했으니 참고해주시기 바랍니다. GitHub – woong980623/Python-Django-BlogGitHub.github.com에 계정을 만들어 woong980623/Python-Django-Blog 개발에 기여하세요.