Django 910掲示板CRUD
45854 ワード
> End Point
-会員入力:POST/user/signup
-ログイン:POST/users/signin
-投稿リスト:GET/bullet-board/post
-投稿の作成:POST/bullet-board/post
-投稿の変更:PATCH/bulletin-board/post/int:post id
-投稿の削除:DELETE/bulletin-board/post/int:post id
-投稿詳細:GET/bullet-board/post-detail/int:post id
🥕 github:
https://github.com/chrisYang256/wnated-wecode-FreeOnboarding
> users App
▶特別事項
会員登録とログインのユーザーのみが投稿の作成、変更、削除を許可します.
登録およびログオンレコーダによる認証機能が追加されました.
▶︎ code
- models.py
- SignUp API
pythonの
異常処理を行いました.
- utils.py
login decorator関数をデザイナとして貼り付けたAPIは、タグチェック後にタグを復号します.
user idを要求します.認証とHTTP無状態をuserにダンプする
解決しました.
> bulletin_board App
▶特別事項
RESTful APIに準拠.
投稿を表示するほか、「すべて承認」に対して例外処理を行いました.
▶︎ code
- models.py
- models.pyのBulletinBoarテーブル
作成したメンバーを削除しても、記事は削除されないように設計されています.
-POST APIでのget
BDで削除したメンバーに対して、3番目の演算子を使用して投稿情報を返す場合
「消えた会員」名前のテキストが表示されます.
-POST APIのpost
pythonの
これは非常に簡単な概念で、DDos攻撃を阻止することができます.
-POST APIのpatch
PUTメソッドではなくPATCHメソッドを使用して、投稿の一部のデータを変更します.
🌈 小さな回顧🤔
久しぶりに書いた小さな回顧です
少し前、私は文章を平語から敬語に変えました.
字数を減らすほうが効率的に見えると思うので、平語の概念を決めました.
傲慢に見えるのでちょっと気分が悪いので気分を変えて穏やかになりました
Pythonと張高を学び、初めて完全なCRUDを一つのプロジェクトに統合した.
実施されたようです.
正確には初めてコードを学びました
RESTful APIも正しく適用されるのは初めてです.
URIはPOST/post-writeにそれぞれ設定され、すべてのAPIが分離される.
これは本当にRESTの黒い歴史を破壊して、同時に忘れられない学習です.
全体的に未熟ですが、コード転送を守るために何度かチェックしました.
少し時間をかけて、簡潔なコードを見て、幸せだったのを覚えています.
小さいながらも大きな一歩を踏み出した喜びをもう一度感じてほしい…!❤️🔥
-会員入力:POST/user/signup
-ログイン:POST/users/signin
-投稿リスト:GET/bullet-board/post
-投稿の作成:POST/bullet-board/post
-投稿の変更:PATCH/bulletin-board/post/int:post id
-投稿の削除:DELETE/bulletin-board/post/int:post id
-投稿詳細:GET/bullet-board/post-detail/int:post id
🥕 github:
https://github.com/chrisYang256/wnated-wecode-FreeOnboarding
> users App
▶特別事項
会員登録とログインのユーザーのみが投稿の作成、変更、削除を許可します.
登録およびログオンレコーダによる認証機能が追加されました.
▶︎ code
- models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length = 20)
password = models.CharField(max_length = 200)
email = models.EmailField(max_length = 50, unique = True)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
class Meta:
db_table = 'users'
- views.pyimport json
import re
import bcrypt
import jwt
from django.http import JsonResponse
from django.views import View
from my_settings import SECRET_KEY, ALGORITHMS
from users.models import User
class SignUp(View):
def post(self, request):
data = json.loads(request.body)
REGX_EMAIL = '^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
REGX_PASSWORD = '^(?=.*\d)(?=.*[a-zA-Z])[0-9a-zA-Z!@#$%^&*]{8,20}$'
try:
if User.objects.filter(email=data['email']).exists():
return JsonResponse({'message': 'EXIST_EMAIL'}, status=400)
if not re.match(REGX_EMAIL, data['email']):
return JsonResponse({'message': 'INVALID_EMAIL_FORM'}, status=400)
if not re.match(REGX_PASSWORD, data['password']):
return JsonResponse({'message': 'INVALID_PASSWORD_FORM'}, status=400)
password = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
User.objects.create(
name = data['name'],
email = data['email'],
password = password,
)
return JsonResponse({'message': 'SUCCESS'}, status=201)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
class SignIn(View):
def post(self, request):
try:
data = json.loads(request.body)
user = User.objects.get(email = data['email'])
if not (user and bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8'))):
return JsonResponse({"message" : "INVALID_USER"}, status=401)
except KeyError:
return JsonResponse({"message" : "KEY_ERROR"}, status=400)
access_token = jwt.encode({'user_id' : user.id}, SECRET_KEY, ALGORITHMS)
return JsonResponse({'access_token' : access_token}, status=201)
- utils.pyimport jwt
from django.http import JsonResponse
from my_settings import SECRET_KEY, ALGORITHMS
from users.models import User
def login_decorator(func):
def wrapper(self, request, *args, **kwargs):
if 'Authorization' not in request.headers:
return JsonResponse ({'message' : 'UNAUTHORIZED'}, status=401)
access_token = request.headers.get('Authorization')
try:
payload = jwt.decode(access_token, SECRET_KEY, algorithms=ALGORITHMS)
user = User.objects.get(id=payload['user_id'])
request.user = user
except jwt.exceptions.DecodeError:
return JsonResponse({'MESSAGE': 'INVALID_TOKEN'}, status=401)
except User.DoesNotExist:
return JsonResponse({'MESSAGE': 'INVALID_USER'}, status=401)
return func(self, request, *args, **kwargs)
return wrapper
- urls.pyfrom django.urls import path
from users.views import SignIn, SignUp
urlpatterns = [
path('/signup', SignUp.as_view()),
path('/signin', SignIn.as_view()),
]
▶︎ Divide & Conquer- SignUp API
pythonの
re.match()
を使用して、正規表現と入力値を照合します.異常処理を行いました.
- utils.py
login decorator関数をデザイナとして貼り付けたAPIは、タグチェック後にタグを復号します.
user idを要求します.認証とHTTP無状態をuserにダンプする
解決しました.
> bulletin_board App
▶特別事項
RESTful APIに準拠.
投稿を表示するほか、「すべて承認」に対して例外処理を行いました.
▶︎ code
- models.py
from django.db import models
class BulletinBoard(models.Model):
author = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, related_name='bulletin_board')
title = models.CharField(max_length=100)
description = models.CharField(max_length=5000)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'bulletin_boards'
- views.pyimport json
import time
import datetime
from django.http import JsonResponse
from django.views import View
from users.utils import login_decorator
from .models import BulletinBoard
from users.models import User
class Post(View):
def get(self, request):
limit = int(request.GET.get('limit', 5))
offset = int(request.GET.get('offset', 0))
limit = limit + offset
post_list = BulletinBoard.objects.all()[offset:limit]
results = [
{
'author' : post.author.name if post.author else "사라진 회원입니다.",
'title' : post.title,
'created_at' : post.created_at
} for post in post_list]
return JsonResponse({'results' : results}, status=200)
@login_decorator
def post(self, request):
try:
data = json.loads(request.body)
if not User.objects.filter(id=request.user.id):
return JsonResponse({'message' : 'INVALID_USER'}, status=404)
BulletinBoard.objects.create(
author_id = request.user.id,
title = data['title'],
description = data['description'],
created_at = data['created_at']
)
time.sleep(1)
return JsonResponse({'message' : 'SUCCESS'}, status=201)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
@login_decorator
def patch(self, request, post_id):
try:
data = json.loads(request.body)
post = BulletinBoard.objects.get(id=post_id)
if not post.author_id == request.user.id:
return JsonResponse({'message' : 'INVALID_USER'}, status=404)
post.title = data['title']
post.description = data['description']
post.updated_at = datetime.datetime.now()
post.save()
return JsonResponse({'message' : 'SUCCESS'}, status=200)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
except BulletinBoard.DoesNotExist:
return JsonResponse({'message' : 'INVALID_POST'}, status=404)
@login_decorator
def delete(self, request, post_id):
try:
post = BulletinBoard.objects.get(id = post_id)
if not post.author_id == request.user.id:
return JsonResponse({'message' : 'INVALID_USER'}, status=404)
BulletinBoard.objects.get(id=post_id).delete()
return JsonResponse({'message' : 'SUCCESS'}, status=200)
except BulletinBoard.DoesNotExist:
return JsonResponse({'message' : 'INVALID_POST'}, status=404)
class PostDetail(View):
def get(self, request, post_id):
try:
post = BulletinBoard.objects.get(id=post_id)
results = {
'author' : post.author.name if post.author else "사라진 회원입니다.",
'title' : post.title,
'description' : post.description,
'created_at' : post.created_at,
'updated_at' : post.updated_at
}
return JsonResponse({'results' : results}, status=200)
except BulletinBoard.DoesNotExist:
return JsonResponse({'message' : 'INVALID_POST'}, status=404)
- urls.pyfrom django.urls import path
from .views import Post, PostDetail
urlpatterns = [
path('/post', Post.as_view()),
path('/post/<int:post_id>', Post.as_view()),
path('/post-detail/<int:post_id>', PostDetail.as_view()),
]
▶︎ Divide & Conquer- models.pyのBulletinBoarテーブル
on_delete=models.SET_NULL
をauthor columのオプションに設定することで、作成したメンバーを削除しても、記事は削除されないように設計されています.
-POST APIでのget
BDで削除したメンバーに対して、3番目の演算子を使用して投稿情報を返す場合
「消えた会員」名前のテキストが表示されます.
-POST APIのpost
pythonの
time.sleep()
を使用して、投稿の登録時間をランダムに遅延します.これは非常に簡単な概念で、DDos攻撃を阻止することができます.
-POST APIのpatch
PUTメソッドではなくPATCHメソッドを使用して、投稿の一部のデータを変更します.
🌈 小さな回顧🤔
久しぶりに書いた小さな回顧です
少し前、私は文章を平語から敬語に変えました.
字数を減らすほうが効率的に見えると思うので、平語の概念を決めました.
傲慢に見えるのでちょっと気分が悪いので気分を変えて穏やかになりました
Pythonと張高を学び、初めて完全なCRUDを一つのプロジェクトに統合した.
実施されたようです.
正確には初めてコードを学びました
RESTful APIも正しく適用されるのは初めてです.
URIはPOST/post-writeにそれぞれ設定され、すべてのAPIが分離される.
これは本当にRESTの黒い歴史を破壊して、同時に忘れられない学習です.
全体的に未熟ですが、コード転送を守るために何度かチェックしました.
少し時間をかけて、簡潔なコードを見て、幸せだったのを覚えています.
小さいながらも大きな一歩を踏み出した喜びをもう一度感じてほしい…!❤️🔥
Reference
この問題について(Django 910掲示板CRUD), 我々は、より多くの情報をここで見つけました https://velog.io/@max-sum/Django-게시판-CRUDテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol