render(request, template_name, context=None, ...)
request와 template_name(html 파일명) 은 필수작성 사항화면에 html 파일을 띄우는 것이라 생각하면 됨!context : 화면에 원하는 인자를 띄워줌.딕셔너리 형태로 사용하며 {html에서 사용할 이름 : views.py에서의 변수명} 과 같이 작성redirect(url 주소, permanent=False, **args, ***kwargs)
주어진 url로 이동하는 것이므로(상대 / 절대 모두 가능) render와 같이 원하는 값들은 넘기지 못한다.render는 html 파일로 이동하고, redirect는 url을 통해 이동하는 것이다.urls.py에 url이 등록되어 있어야 한다는 점이와 맞물린 함수가 있다는 점해당 함수는 views.py에서 선언이 되어 있어야 한다는 점해당 함수 안에서 render를 할 것인지 redirect를 할 것인지 결정할 수 있다는 점한 명의 글쓴이가 여러 개의 글을 보유하고 있을 수는 있지만, 하나의 글이 여러 명의 글쓴이를 보유할 수 없는 것이다.mySpartaSns에서는 모델을 생성할 때 사용한 ForeignKey가 이에 해당한다. 아래의 코드를 한 번 보도록 하겠다. class UserModel(AbstractUser):
class Meta:
db_table = "my_user"
bio = models.TextField(max_length=500, blank=True)
class TweetModel(models.Model):
class Meta:
db_table = "tweet"
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
content = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class TweetComment(models.Model):
class Meta:
db_table = "comment"
tweet = models.ForeignKey(TweetModel, on_delete=models.CASCADE)
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
comment = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
my_user 모델은 사용자를 정의하는 모델인데, 지금 보면 tweet과 comment 모델에서 모두 author라는 변수명으로 my_user의 모든 내용을 가져다 쓰고 있다. 한 명의 사용자가 다수의 게시글과 댓글을 보유하게 된다. one-to-many 관계가 성립된다. tweet이랑 comment 모델도 one-to-many 관계가 성립된다!중복되지 않는 값을 발생시키는 것이다.프로필 기능인것 같다. 물론 요즘에는 멀티 프로필이 가능하지만, 결국 하나의 아이디에 하나의 프로필인 것은 똑같으니 적당한 예시라고 생각한다. OneToOneField를 사용해 작성하게 된다. class UserModel(AbstractUser):
class Meta:
db_table = "my_user"
bio = models.TextField(max_length=500, blank=True)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_pk = models.IntegerField(blank=True)
nickname = models.CharField(max_length=200, blank=True)
point = models.IntegerField(default=0)
phone = models.CharField(max_length=200, blank=True)
서로 n개씩의 관계를 가질 수 있다.ManyToManyField를 사용한다. 서로 n개씩이라면서 왜 한 쪽에만 ManyToManyField을 쓰냐고 생각할 수 있다. django에서는 한 쪽에만 입력해주면 알아서 다 해주니 걱정할 필요 없다.class MyTopping(models.Model):
topping_name = models.CharField(max_length=100)
class MyPizza(models.Model):
pizza_name = models.CharField(max_length=100)
pizza_topping = models.ManyToManyField(MyTopping)
restaurant app을 생성하였다. $ django-admin startapp restaurant
mySpartaSns/settings.py로 가서 내가 설치한 app이 무엇인지 django에게 알려주도록 하겠다. #### mySpartaSns/settings.py ####
# 상단 생략
INSTALLED_APPS = [
# 우리가 생성한 app 추가
'user',
'tweet',
'restaurant',
# django의 기본 app
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# 하단 생략
restaurant/models.py에 실습에 사용할 모델들을 만들도록 하겠다. # restaurant/models.py
from django.db import models
class MyTopping(models.Model):
class Meta:
db_table = "my_topping"
def __str__(self):
return self.topping_name
topping_name = models.CharField(max_length=100)
class MyPizza(models.Model):
class Meta:
db_table = "my_pizza"
def __str__(self):
return self.pizza_name
pizza_name = models.CharField(max_length=100)
pizza_topping = models.ManyToManyField(MyTopping)
$ python manage.py makemigrations
$ python manage.py migrate


resaturant/admin.py에 등록하도록 하겠다. #### resaturant/admin.py ####
from django.contrib import admin
from .models import MyPizza, MyTopping
admin.site.register(MyPizza)
admin.site.register(MyTopping)
$ python manage.py createsuperuser
http://127.0.0.1:8000/admin

db.sqlite3 삭제migrations 폴더에서 __init__.py 파일을 제외한 다른 2 개의 파일을 전부 삭제데이터베이스 창에 나와있는 데이터베이스도 모두 다 삭제auth_user를 끌어다 쓰면서 관리자에 대한 제대로된 세팅이 이루어지지 않았기 때문이며, 그래서 지우고 다시 세팅을 진행다시 db를 생성하면 된다. $ python manage.py makemigrations
$ python manage.py migrate


db.sqlite3가 다시 생기게 되고, 이거를 오른쪽의 데이터베이스 창에 드래그해주면 다시 생성이 된다.
$ python manage.py createsuperuser


My pizza로 가서 피자를 만들어 보도록 하겠다.

django를 실행하지 않고도 기능들을 사용할 수 있도록 도와주는 도구$ python manage.py shell

피자의 입장에서 자신에게 들어가 있는 모든 토핑 불러오기restaurant app에 있는 모델 중 MyTopping, MyPizza 사용MyPizza 안에 있는 모든 object를 불러옴MyPizza 중 이름이 domino인 것을 불러옴papajones인 피자에 추가되어 있는 topping들을 전부 불러옴1 >>> from restaurant.models import MyTopping, MyPizza
2 >>> MyPizza.objects.all()
<QuerySet [<MyPizza: domino>, <MyPizza: pizzahut>, <MyPizza: papajones>]>
3 >>> MyPizza.objects.get(pizza_name='domino')
<MyPizza: domino>
4 >>> MyPizza.objects.get(pizza_name='papajones').pizza_topping.all()
<QuerySet [<MyTopping: cheese>, <MyTopping: pepparoni>, <MyTopping: onion>]>
토핑의 입장에서 본인이 들어간 모든 피자 불러오기restaurant app에 있는 모델 중 MyTopping, MyPizza 사용MyTopping 안에 있는 모든 object를 불러옴MyTopping 중 이름이 cheese인 것을 불러옴MyTopping 중 cheese가 포함된 모든 피자 불러옴MyTopping 중 pepparoni가 포함된 모든 피자 불러옴1 >>> from restaurant.models import MyTopping, MyPizza
2 >>> MyTopping.objects.all()
<QuerySet [<MyTopping: cheese>, <MyTopping: pepparoni>, <MyTopping: onion>, <MyTopping: cow>, <MyTopping: chicken>, <MyTopping: shirimp>, <MyTopping: olive>]>
3 >>> MyTopping.objects.get(topping_name='cheeze')
<MyTopping: cheese>
4 >>> MyTopping.objects.get(topping_name='cheese').mypizza_set.all()
<QuerySet [<MyPizza: domino>, <MyPizza: pizzahut>, <MyPizza: papajones>]>
5 >>> MyTopping.objects.get(topping_name='pepparoni').mypizza_set.all()
<QuerySet [<MyPizza: pizzahut>, <MyPizza: papajones>]>
many-to-many 관계를 사용해서 작성해보자.#### user/models.py ####
from django.db import models
# django에서 기본적으로 제공하는 auth_user와 연동되는 클래스인 AbstractUser 사용
from django.contrib.auth.models import AbstractUser
# django가 관리하는 곳(메인 app)에 있는 settings를 불러옴
from django.conf import settings
# 내가 생성한 user model
class UserModel(AbstractUser):
# 데이터베이스에 반영되는 model의 이름 작성
class Meta:
db_table = "my_user"
# auth_user에 있는 내용들을 다 지워줌
# 상태 메세지
bio = models.CharField(max_length=256, default='')
# follow 모델
# 내가 팔로우하는 사람은 다른 모델이 아닌 사용자 모델에 있는 사용자이기 때문에 AUTH_USER_MODEL을 가져다 씀
# AUTH_USER_MODEL : 우리가 튜닝한 유저 모델이고 djangoProject/settings.py의 가장 아래부분에 우리가 추가했엄
# 내가 팔로우하는 사람들의 명단이 follow 안에 들어가는 것이고, 그 사람들 입장에서는 내가 followee가 된다.
# UserModel.followee : UserModel을 팔로우하는 사람들을 불러줌
# UserModel.follow : 내가 팔로우하는 사람들을 불러줌
follow = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='followee')
$ python manage.py makemigrations
$ python manage.py migrate

many-to-many 관계의 경우 참조할 것이 많다보니 자동적으로 생기는 것이므로 신경쓸 필요 없다. 
@login_required
def user_view(request):
if request.method == 'GET':
# exclude : 해당하는 데이터에서 조건에 맞는 데이터를 제거해주는 함수
# 사용자를 불러오기, exclude와 request.user.username 를 사용해서 '로그인 한 사용자'를 제외하기
user_list = UserModel.objects.all().exclude(username=request.user.username)
return render(request, 'user/user_list.html', {'user_list': user_list})
@login_required
def user_follow(request, id):
# 나(로그인한 사용자)
me = request.user
# 내가 팔로우하려고 방금 누른 사람
click_user = UserModel.objects.get(id=id)
# 팔로우를 당한 사람(click_user)도 UserModel의 정보를 가져와 쓰기 때문에 아래와 같이 쓸 수 있다.
# 만약 click_user를 팔로우하는 사람의 명단에 내가 있다면
if me in click_user.followee.all():
# 나를 명단에서 제외해줘(팔로우가 된 상태에서 팔로우를 또 누르면 팔로우가 취소되니까)
click_user.followee.remove(request.user)
else:
# 내가 명단에 없다면 나를 팔로우하는 사람들의 명단에 넣어줘
click_user.followee.add(request.user)
return redirect('/user')
from django.urls import path
from . import views
urlpatterns = [
path('sign-up/', views.sign_up_view, name='sign-up'),
path('sign-in/', views.sign_in_view, name='sign-in'),
path('logout/', views.logout, name='logout'),
path('user/', views.user_view, name='user-list'),
path('user/follow/<int:id>', views.user_follow, name='user-follow'),
]
<!-- templates/user/user_list.html -->
{% extends 'base.html' %}
{% block title %}
사용자 리스트
{% endblock %}
{% block content %}
<div class="container timeline-container">
<div class="row">
<!-- 왼쪽 컬럼 -->
<div class="col-md-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ user.username }}</h5>
<p class="card-text"> {{ user.bio }}</p>
</div>
</div>
</div>
<!-- 오른 쪽 컬럼-->
<div class="col-md-7">
<div class="row">
<div class="alert alert-success" role="alert">
나를 팔로우 하는 사람 수 : {{ user.followee.count }} 명 / 내가 팔로우 하는 사람 수 : {{ user.follow.count }} 명
</div>
</div>
<div class="row">
<!-- 사용자 리스트 반복문 -->
{% for ul in user_list %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ ul.username }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{ ul.email }}</h6>
<p class="card-text">
{{ ul.bio }}
</p>
<p class="card-text">
팔로잉 {{ ul.follow.count }} 명 / 팔로워 {{ ul.followee.count }} 명
</p>
{% if ul in user.follow.all %}
<a href="/user/follow/{{ ul.id }}" class="card-link">[팔로우 취소]</a>
{% else %}
<a href="/user/follow/{{ ul.id }}" class="card-link">[팔로우]</a>
{% endif %}
</div>
</div>
<hr>
{% endfor %}
</div>
</div>
<div class="col-md-2"></div>
</div>
</div>
{% endblock %}
친구 부분에 /user url을 걸어주었다. <!-- templates/base.html -->
<!-- 상단 생략 -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="/">SpartaSNS</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/user"> 친구 <span class="sr-only"></span></a>
</li>
</ul>
</div>
<!-- 하단 생략 -->

