static files
JavaScrpit,CSS,Image 제공
static 설정
settings.py
STATIC_URL = "static/"
STATICFILES_DIRS = [
BASE_DIR / "static",
"/var/www/static/",
]
---------------------------------------------
app urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
---------------------------------------------
html 설정
{% load static %}
<img src="{% static 'my_app/example.jpg' %}" alt="My image">
Pillow 라이브러리 요구
장고 각 필드에대한 가이드 공식문서
STATIC/MEDIA URL 설정
settings.py
STATIC_ROOT = BASE_DIR / "static"
STATIC_URL = '/static/'
MEDIA_ROOT = BASE_DIR/ "media"
MEDIA_URL = '/media/'
app.urls.py 설정
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
....
]
urlpatterns+= static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns+= static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
이미지필드 속성 설정
image = models.ImageField(blank=True, upload_to='%Y/%m/')
등록될 이미지의 날짜별 관리 가능
class ArticleView(APIView):
def get(self,request):
articles = Article.objects.all()
# serializer = ArticleSerializer(articles,many=True)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
serializer = ArticleCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data,status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
class ArticleDetailView(APIView):
def get(self, request,article_id):
article = get_object_or_404(Article,id=article_id)
serializer = ArticleSerializer(article)
return Response(serializer.data,status=status.HTTP_201_CREATED)
def put(self, request,article_id):
article = get_object_or_404(Article, id=article_id)
if request.user == article.user:
serializer = ArticleCreateSerializer(article,data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
else:
return Response("권한이 없습니다!",status=status.HTTP_403_FORBIDDEN)
def delete(self, request,article_id):
article = get_object_or_404(Article, id=article_id)
if request.user == article.user:
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response("권한이 없습니다!",status=status.HTTP_403_FORBIDDEN)
class ArticleSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
def get_user(self, obj):
return obj.user.email
class Meta:
model = Article
fields = "__all__"
class ArticleCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("title","image","content")
class ArticleListSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
def get_user(self,obj):
return obj.user.email
# 약속된 형태, 메소드 필드를 받고, get_user를 사용하여 user의 email 값을 반환받는다.
class Meta:
model = Article
fields = ("pk","title","image","updated_at","user")
article = models.ForeignKey(Article, on_delete=models.CASCADE,related_name="comment_set")
related_name="comment_set"을 등록하지 않아도, 기본적으로 사용할 수 있다.
주의사항 : Many To Many 필드에는 항상 related_name을 설정해줘야 한다.
serializer 구축
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ("content",)
주의사항 : fields의 튜플에 항상 ,를 붙여줘야 한다.
모델 설계
class Article(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
...
likes = models.ManyToManyField(User,related_name="like_articles")
user의 역참조
user.article_set : 유저가 작성한 게시글 역참조
user.like_articles : 유저가 좋아요한 게시글 역참조
역참조 이해
class School(models.Model):
....
class Student(models.Model):
school = models.ForeignKey(School,on_delete_True)
....
related_name, 역참조 이름을 설정하지 않으면
School에서 Student를 역참조 하기 위해서는
school(오브젝트).school_set.all()
이러한 방법으로 역참조한 데이터를 모두 가져올 수 있으며
class Student(models.Model):
school = models.ForeignKey(School,on_delete_True,related_name="sparta")
....
위와 같이 related_name을 sparta로 지정시 역참조하기 위해
school(오브젝트).sparta.all()
이러한 방법으로 역참조 데이터를 가져올 수 있다.
class LikeView(APIView):
def post(self,request,article_id):
article = get_object_or_404(Article,id=article_id)
if request.user in article.likes.all():
article.likes.remove(request.user)
return Response("좋아요", status=status.HTTP_200_OK)
else:
article.likes.add(request.user)
return Response("좋아요 취소", status=status.HTTP_200_OK)
좋아요 기능은 팔로우 기능과 굉장히 흡사하다.
class FollowView(APIView):
def post(self,request,user_id):
click_user = get_object_or_404(User,id=user_id)
if request.user in click_user.followers.all():
click_user.followers.remove(request.user)
return Response("unfollow", status=status.HTTP_200_OK)
else:
click_user.followers.add(request.user)
return Response("follow", status=status.HTTP_200_OK)
Many - to - Many 설계
followings = models.ManyToManyField('self',symmetrical=False,related_name='followers')
symmetrical=False : 상호 관계성에 일방적으로 등록이 가능
many-to-many field는 항시 related_name을 설정해야한다.
serializers.py
class ArticleSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
comment_set = CommentSerializer(many=True)
def get_user(self, obj):
return obj.user.email
class Meta:
model = Article
fields = "__all__"
상세페이지 Serializer 모델에 댓글 내역을
역참조를 통해 추가
댓글 내역은 성공적으로 가져왔으며 likes에는
like를 누른 유저의 id값이 출력되고 있다.
프론트에서는 이 id값으로 출력되는것이 데이터를 가공 하는데 있어 조금더 편하겠지만
이 정보를 이메일로 바꿔보자.
class ArticleSerializer(serializers.ModelSerializer):
...
likes = serializers.StringRelatedField(many=True)
...
StringRelatedField추가
User Model의 pk값을 str값으로 변환하여 반환한다.
class ArticleListSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
likes_count = serializers.SerializerMethodField()
comments_count = serializers.SerializerMethodField()
def get_user(self,obj):
return obj.user.email
# 약속된 형태, 메소드 필드를 받고, get_user를 사용하여 user의 email 값을 반환받는다.
def get_likes_count(self,obj):
return obj.likes.count()
def get_comments_count(self,obj):
return obj.comment_set.count()
class Meta:
model = Article
fields = ("pk","title","image","updated_at","user","likes_count","comments_count")
MethodField : 직렬변환(JSON변환)데이터 추가
obj.object.count() (총 개수 반환)
comment_set의경우, comment모델을 역참조하여 데이터를 가져온다.
views.py
class ProfileView(APIView):
def get(self,request,user_id):
user = get_object_or_404(User,id=user_id)
serializer = UserProfileSerializer(user)
return Response(serializer.data)
serializers.py
class UserProfileSerializer(serializers.ModelSerializer):
followers = serializers.StringRelatedField(many=True)
followings = serializers.StringRelatedField(many=True)
article_set = ArticleListSerializer(many=True)
like_articles = ArticleListSerializer(many=True)
class Meta:
model = User
fields = ("id","email","followings","followers","article_set","like_articles")
class FeedView(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self,request):
q = Q()
for user in request.user.followings.all():
q.add(Q(user=user),q.OR)
feeds = Article.objects.filter(q)
serializer = ArticleSerializer(feeds,many=True)
return Response(serializer.data)