Spring Batch
Real Time 작업 - 실시간 작업바로 응답을 받아서 보는 것을 실시간 작업이라 한다. 배치 작업은작업들을 한번에 모아서 처리하는 작업 배송이나 정산은 모아서 특정 주기마다 처리하는 작업고객눈에는 보이지 않지만 서비스 뒷펀에서 대량의 작업을 처리한다.
Real Time 작업 - 실시간 작업바로 응답을 받아서 보는 것을 실시간 작업이라 한다. 배치 작업은작업들을 한번에 모아서 처리하는 작업 배송이나 정산은 모아서 특정 주기마다 처리하는 작업고객눈에는 보이지 않지만 서비스 뒷펀에서 대량의 작업을 처리한다.
장고를 이용한 rest api 만들기settings myapi/settings.py STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 정적 파일 root 추가 INSTALLED_APPS = [ ... 'rest_framework',] INSTALLED_APPS에 quiz와 rest_framework를 추가해준다. 모델 생성하기 quiz/models.py
Comment (댓글) view 구현하기테스트 코드 작성 blog/tests.py # Comment를 생성한다.comment_000 = create_post(post_000, text='a test comment', author=self.author_obama) # Comment comments_div = main_div.find('div', id='comment-list') self.assertIn(comment_000.author.username, comments_div.text) self.assertIn(comment_000.text, comments_div.text) post_detail 수정하기 blog/templates/blog/post_detail.html <!-- Comment --><div id="comment-list">{% for comment in object.comment_set.all %} <div class="media mb-4"> <img class="d-flex mr-3 rounded-circle" src="http://placehold.it/50x50" alt=""> <div class="media-body"> <h5 class="mt-0">{{ comment.author }}</h5> {{ comment.get_markdwon_content | safe }} </div> </div>{% endfor %}</div> admin 사이트에서 comment확인할 수 있게 반영하기 blog/admin.py
Comment (댓글) 작성창 구현하기forms.py 파일 생성하기 blog/ 해당 돌더에 forms.py 파일을 생성한다. from .models import Commentfrom django import formsclass CommentForm(forms.ModelForm): class Meta: model = Comment fields = {'text',} 테스트 코드 작성하기 blog/tests.py # 로그인하기login_success = self.client.login(username='smith', password='nopassword')self.assertTrue(login_success)# post를 이용하여 서버에 데이터를 보낸다.response = self.client.post( post_000.get_absolute_url() + 'new_comment/', {'text':'A test comment for the first comment'}, follow=True # redirect하는 것까지 확인을 해봐라)self.assertEqual(response.status_code, 200) views.py에 반영하기
블로그 post list와 post detail 페이지에 카테고리 추가하기테스트 코드 작성하기 blog/tests.py post_001 = create_post( title="The second post", content="Second Second Second", author=self.author_000, category=create_category(name='정치/사회'))# category card에서 category_card = body.find('div', id='category-card') self.assertIn('미분류(1)', category_card.text) #### 미분류 (1)이 있어야 한다. self.assertIn('정치/사회(1)', category_card.text) #### 정치/사회(1)이 있어야 한다. main_div = body.find('div', id='main_div') self.assertIn('정치/사회', main_div.text) ###'정치/사회' 있어야 함 self.assertIn(('미분류', main_div.text)) ### '미분류' 있어야 함 id 추가하기 blog/templates/blog/base.html <div class="card my-4" id = "category-card"> 카테고리 카드 수정해주기 blog/views.py
Comment (댓글) 모델 구현하기테스트 코드 작성하기 blog/tests.py # commnet를 생성하는 함수def create_comment(post, text='a comment', author=None): if author is None: author, is_created = User.objects.get_or_create( username='guset', password='guestpassword' ) comment = Comment.objects.create( post = post, text = text, author = author ) return comment # class test_Model에 추가 # 댓글 기능에 관한 test def test_comment(self): post_000 = create_post( title="The first post", content="Hello World. We are the world.", author=self.author_000, ) self.assertEqual(Comment.objects.count(), 0) comment_000 = create_comment( post=post_000 ) comment_001 = create_comment( post=post_000, text='second comment' ) self.assertEqual(Comment.objects.count(), 2) self.assertEqual(post_000.comment_set.count(), 2) comment 모델 추가하기 blog/models.py class Comment(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE) text = MarkdownxField() author = models.ForeignKey(User, on_delete=models.CASCADE)
로그인 사용자만 접속 가능하게 하기테스트 코드 작성 blog/tests.py # post_create를 확인하기 위한 테스트 코드def test_post_create(self): response = self.client.get('/blog/create/') # 로그인 하지 않은 상태에서는 create로 접속시에 200이 뜨면 안된다. self.assertNotEqual(response.status_code, 200) # 로그인을 했을 때만 create로 접속시 200이 뜨게 해야 한다. self.client.login(username='smith', password='nopassword') response = self.client.get('/blog/create/') self.assertEqual(response.status_code, 200) # 정상적으로 이루어진 경우 BeautifulSoup을 이용해 html.parser로 파싱한 객체를 생성한다. soup = BeautifulSoup(response.content, 'html.parser') main_div = soup.find('div', id='main-div') # self.assertIn('New Post', main_div.text) 뷰 수정하기 blog/views.py from django.contrib.auth.mixins import LoginRequiredMixinclass PostCreate(LoginRequiredMixin, CreateView): model = Post fields = [ 'title', 'content', 'head_image', 'category', # 'tags' ] def form_valid(self, form): # 작성자를 가지고 온다. current_user = self.request.user # 로그인을 한 상태인지 확인을 한다. if current_user.is_authenticated: # form의 author를 현재 작성중인 사람으로 채워 넣어 form.instance.author = current_user return super(type(self), self).form_valid(form) else : return redirect('/blog/') PostCreate에서 LoginRequiredMixin을 추가적으로 상속한다.
Post 작성 화면 / 기능 구현하기new 버튼 만들기 blog/templates/post_list.html <!--로그인 한 사용자에게만 보이게 하기-->{% if user.is_authenticated %} <!-- new post button 만들기 --> <button class="btn btn-primary btn-sm float-right" onclick="location.href='/blog/create/'">new post</button>{% endif %} post_create 만들기테스트 코드 작성 blog/tests.py # post_create를 확인하기 위한 테스트 코드def test_post_create(self): response = self.client.get('/blog/create/') self.assertEqual(response.status_code, 200) # 정상적으로 이루어진 경우 BeautifulSoup을 이용해 html.parser로 파싱한 객체를 생성한다. soup = BeautifulSoup(response.content, 'html.parser') main_div = soup.find('div', id='main-div') # self.assertIn('New Post', main_div.text) url 추가하기
Post 수정 화면 / 기능 구현하기update된 url을 반환하는 함수 만들어 주기 blog/models.py # update된 url을 반환하기 위한 함수def get_update_url(self): return self.get_absolute_url() + 'update/' update된 url로 접속하기 blog/views.py from django.views.generic import UpdateViewclass PostUpdate(UpdateView): model = Post # post의 모든 field를 가져와라 field = '__all__' blog/urls.py from django.urls import path, includefrom .import viewsurlpatterns = [ # path('', views.index), # path('<int:pk>/', views.post_detail), path('category/<str:slug>/', views.PostListByCategory.as_view()), path('<int:pk>/update/', views.PostUpdate.as_view()), path('<int:pk>/', views.PostDetail.as_view()), path('', views.PostList.as_view()),]
마크다운적용하기, tag field에 공란 허용하기 post에 그림이 나타나게 해주기 줄바꿈이 적용될 수 있게 바꿔주기 -> 마크다운 이용하기 post에 그림이 나타나게 해주기 blog/templates/blog/post_detail.html <img class="img-fluid rounded" src="{{object.head_image.url}}" alt=""> 줄바꿈이 적용될 수 있게 바꿔주기 -> 마크다운 이용하기https://neutronx.github.io/django-markdownx/ pip install django-markdownx 앱 추가하기
Post Detail 개선사항 도출하고 Test 코드 만들기 post에 카테고리 표시하기 edit 버튼 만들기 post에 그림이 나타나게 해주기 줄바꿈이 적용될 수 있게 바꿔주기 -> 마크다운 이용하기 post에 카테고리 표시하기테스트 코드 만들어주기 blog/tests.py self.assertIn(category_politics.name, main_div.text) # category가 main_div에 있다.self.assertNotIn('EDIT', main_div.text) # EDIT 버튼이 로그인 하지 않은 경우 보이지 않는다.login_success = self.client.login(username='smith', password='nopassword') # login을 한 경우에는self.assertTrue(login_success)response = self.client.get(post_000_url)self.assertEqual(response.status_code, 200)soup = BeautifulSoup(response.content, 'html.parser')main_div = soup.find('div', id='main-div')self.assertEqual(post_000.author, self.author_000) # post.author와 login한 사람이 같으면self.assertIn('EDIT', main_div.text) # EDIT button이 있다. blog/templates/blog/post_detail.html {% if p.category %}<!-- badge가 오른쪽에 붙을 수 있게 float-right옵션을 이용한다. --><span class="badge badge-primary float-right">{{ p.category }}</span>{% else %}<span class="badge badge-primary float-right">미분류</span>{% endif %} post_list.html로부터 category부분의 내용을 post_detail.html에 붙여준다.
Category 페이지 만들기 (slugField)Category에 get_absolute_url추가하기 blog/models.py # Create your models here.# 카테고리를 추가한다.class Category(models.Model): # Category의 이름이 유일할 수 있게 unique옵션을 준다. name = models.CharField(max_length=25, unique=True) description = models.TextField(blank=True) # unicode를 허용한다. # slug를 이용하여 url에 카테고리가 뜰 수 있게 해준다. slug = models.SlugField(unique=True, allow_unicode=True) def get_absoulte_url(self): return '/blog/category/{}/'.format(self.slug) # 카테고리 이름을 출력해준다. def __str__(self): return self.name class Meta: verbose_name_plural = 'categories' admin에 slug가 자동으로 생성 될 수 있게하기 blog/admin.py from django.contrib import adminfrom .models import Post, Category# Register your models here.class CategoryAdmin(admin.ModelAdmin): # 미리 만들어지는 field # slug를 자동으로 만들어준다. prepopulated_fields = {'slug': ('name', )}admin.site.register(Post)admin.site.register(Category, CategoryAdmin) url 만들어주기 blog/urls.py
사소한 문제들 해결: 불필요한 내용 삭제하기; category 복수형 수정하기 (categorys -> categories)post_detail에 카테고리 반영하기 blog/models.py def get_context_data(self, *, object_list=None, **kwargs): context = super(PostList, self).get_context_data(**kwargs) context['category_list'] = Category.objects.all() # Post들 중에서 category가 None인 것의 갯수를 가져온다. context['posts_without_category'] = Post.objects.filter(category=None).count() return context blog/tests.py def check_right_side(self, soup): category_card = soup.find('div', id='category-card') self.assertIn('미분류(1)', category_card.text) #### 미분류 (1)이 있어야 한다. self.assertIn('정치/사회(1)', category_card.text) #### 정치/사회(1)이 있어야 한다.# category가 잘 작동하는지 확인하기self.check_right_side(soup)
블로그 post list와 post detail 페이지에 카테고리 추가하기테스트 코드 작성하기 blog/tests.py post_001 = create_post( title="The second post", content="Second Second Second", author=self.author_000, category=create_category(name='정치/사회'))# category card에서 category_card = body.find('div', id='category-card') self.assertIn('미분류(1)', category_card.text) #### 미분류 (1)이 있어야 한다. self.assertIn('정치/사회(1)', category_card.text) #### 정치/사회(1)이 있어야 한다. main_div = body.find('div', id='main_div') self.assertIn('정치/사회', main_div.text) ###'정치/사회' 있어야 함 self.assertIn(('미분류', main_div.text)) ### '미분류' 있어야 함 id 추가하기 blog/templates/blog/base.html <div class="card my-4" id = "category-card"> 카테고리 카드 수정해주기 blog/views.py
블로그 post에 카테고리 추가하기테스트 코드 작성하기 blog/tests.py # 카테고리 생성을 위한 코드def create_category(name='life', description=""): category, is_created = Category.objects.get_or_create( name=name, description=description ) return category# 카테고리를 테스트 하기 위한class TestModel(TestCase): def setUp(self): # 브라우저 역할을 해준다. self.client = Client() self.author_000 = User.objects.create( username='smith', password='nopassword') def test_category(self): category = create_category() def test_post(self): category = create_category( ) post_000 = create_post( title="The first post", content="Hello World. We are the world.", author=self.author_000, category=category ) # 카테고리에서 포스트를 불러오는 코드 self.assertEqual(category.post_set.count(), 1) 카테고리 만들어 주기 blog/models.py # 카테고리를 추가한다.class Category(models.Model): name = models.CharField(max_length=25) description = models.TextField(black=True) 전체 소스 코드from django.db import modelsfrom django.contrib.auth.models import User# Create your models here.# 카테고리를 추가한다.class Category(models.Model): # Category의 이름이 유일할 수 있게 unique옵션을 준다. name = models.CharField(max_length=25, unique=True) description = models.TextField(blank=True)class Post(models.Model): # 제목 title = models.CharField(max_length=30) # 내용 content = models.TextField() # 이미지 파일 저장을 위한 객체 # upload된 이미지 파일은 blog에 저장이 된다. blank = True는 공란이여도 된다는 의미이다. head_image = models.ImageField(upload_to='blog/%Y/%m/%d/', blank=True) # 작성 일자 created = models.DateTimeField() # 저자 author = models.ForeignKey(User, on_delete=models.CASCADE) # 카테고리 객체 추가 category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL) # 해당 객체를 문자열로 바꿧을 때 어떤 식으로 보여줄 것인지를 결정한다. def __str__(self): # 작성된 페이지의 제목과 저자를 보여준다. return '{} :: {}'.format(self.title, self.author) # 포스트의 절대 경로를 얻기 위한 함 def get_absolute_url(self): return '/blog/{}/'.format(self.pk)