{% for topic in topics %}
<div>
<a href="{% url 'home' %}?q={{topic.name}}">{{topic.name}}</a>
</div>
{% endfor %}
자동
{% for field in form %}
<div class="form__group">
<label for="room_name">{{field.label}}</label>
<!-- <input id="room_name" name="room_name" type="text" placeholder="E.g. Mastering Python + Django" /> -->
{{field}}
</div>
{% endfor %}
<div class="form__group">
<label for="room_topic">Topic</label>
<input required type="text" name="topic" list="topic-list">
<datalist id="topic-list">
<select id="room_topic">
{% for topic in topics %}
<option value="{{topic.name}}">{{topic.name}}</option>
{% endfor %}
</select>
</datalist>
</div>
<div class="form__group">
<label for="room_name">Name</label>
{{form.name}}
</div>
<div class="form__group">
<label for="room_description">Room Description</label>
{{form.description}}
</div>
topics = Topic.objects.all()
context = {'form': form,'topics':topics}
이렇게 하면 자동 완성 및 옵션 기능 가능
@login_required(login_url='login')
def createRoom(request) :
form = RoomForm()
topics = Topic.objects.all()
if request.method == 'POST' :
topic_name = request.POST.get('topic')
topic, created = Topic.objects.get_or_create(name=topic_name)
Room.objects.create(
host=request.user,
topic = topic,
name = request.POST.get('name'),
description = request.POST.get('description'),
)
return redirect('home') # url 에 이름 있어서 redirect 가능해짐
context = {'form':form,'topics':topics}
return render(request, 'base/room_form.html', context)
@login_required(login_url='login')
def createRoom(request) :
form = RoomForm()
topics = Topic.objects.all()
if request.method == 'POST' :
topic_name = request.POST.get('topic')
topic, created = Topic.objects.get_or_create(name=topic_name)
Room.objects.create(
host=request.user,
topic = topic,
name = request.POST.get('name'),
description = request.POST.get('description'),
)
return redirect('home') # url 에 이름 있어서 redirect 가능해짐
context = {'form':form,'topics':topics}
return render(request, 'base/room_form.html', context)
@login_required(login_url='login')
def updateRoom(request,pk) :
room = Room.objects.get(id=pk)
form = RoomForm(instance=room)
topics = Topic.objects.all()
if request.user != room.host :
return HttpResponse('Your are not allowed here!!!')
if request.method == 'POST' :
topic_name = request.POST.get('topic')
topic, created = Topic.objects.get_or_create(name=topic_name)
room.topic = topic
room.name = request.POST.get('name')
room.description = request.POST.get('description')
room.save()
return redirect('home')
context = {'form': form,'topics':topics,'room':room}
return render(request, 'base/room_form.html',context)
<div class="form__group">
<label for="room_topic">Enter a topic</label>
<input required type="text" value="{{room.topic.name}}" name="topic" list="topic-list">
<datalist id="topic-list">
<select id="room_topic">
{% for topic in topics %}
<option value="{{topic.name}}">{{topic.name}}</option>
{% endfor %}
</select>
</datalist>
</div>
<div class="form__group">
<label for="room_name">Name</label>
{{form.name}}
</div>
<div class="form__group">
<label for="room_description">Room Description</label>
{{form.description}}
</div>
{% extends 'main.html' %}
{% block content %}
<main class="update-account layout">
<div class="container">
<div class="layout__box">
<div class="layout__boxHeader">
<div class="layout__boxTitle">
<a href="{% url 'home' %}">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"
viewBox="0 0 32 32">
<title>arrow-left</title>
<path
d="M13.723 2.286l-13.723 13.714 13.719 13.714 1.616-1.611-10.96-10.96h27.625v-2.286h-27.625l10.965-10.965-1.616-1.607z">
</path>
</svg>
</a>
<h3>Edit your profile</h3>
</div>
</div>
<div class="layout__body">
<form class="form" action="#" method="POST">
{% csrf_token %}
<div class="form__group">
<label for="profile_pic">Avatar</label>
<input id="profile_pic" name="profile_pic" type="file" />
</div>
<div class="form__action">
<a class="btn btn--dark" href="index.html">Cancel</a>
<button class="btn btn--main" type="submit">Update</button>
</div>
</form>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
자세히 ...
{% for field in form %}
<div class="form__group">
<label for="profile_pic">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
class UserForm(ModelForm) :
class Meta :
model = User
fields = ['username','email']
@login_required(login_url='login')
def updateUser(request) :
user = request.user
form = UserForm(instance=user)
if request.method == 'POST' :
form = UserForm(request.POST, instance=user)
if form.is_valid() :
form.save()
return redirect('user-profile', pk=user.id)
return render(request, 'base/update-user.html',{'form':form})
{% extends 'main.html' %}
{% block content %}
<main class="delete-item layout">
<div class="container">
<div class="layout__box">
<div class="layout__boxHeader">
<div class="layout__boxTitle">
<a href="{{request.META.HTTP_REFERER}}">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"
viewBox="0 0 32 32">
<title>arrow-left</title>
<path
d="M13.723 2.286l-13.723 13.714 13.719 13.714 1.616-1.611-10.96-10.96h27.625v-2.286h-27.625l10.965-10.965-1.616-1.607z">
</path>
</svg>
</a>
<h3>Back</h3>
</div>
</div>
<div class="layout__body">
<form class="form" method="POST" action="#">
{% csrf_token %}
<div class="form__group">
<p>Are you sure you want to delete "{{obj}}"?</p>
</div>
<div class="for__group">
<input class="btn btn--main" type="submit" value="Confirm" />
</div>
</form>
</div>
</div>
</div>
</main>
{% endblock content %}
{% extends 'main.html' %}
{% block content %}
<main class="auth layout">
{% if page == 'login' %}
<div class="container">
<div class="layout__box">
<div class="layout__boxHeader">
<div class="layout__boxTitle">
<h3>Login</h3>
</div>
</div>
<div class="layout__body">
<h2 class="auth__tagline">Find your study partner</h2>
<form class="form" action="#" method="POST">
{% csrf_token %}
<div class="form__group form__group">
<label for="room_name">Username</label>
<input id="username" name="username" type="text" placeholder="e.g. dennis_ivy" />
</div>
<div class="form__group">
<label for="password">Password</label>
<input
id="password"
name="password"
type="password"
placeholder="••••••••"
/>
</div>
<button class="btn btn--main" type="submit">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<title>lock</title>
<path
d="M27 12h-1v-2c0-5.514-4.486-10-10-10s-10 4.486-10 10v2h-1c-0.553 0-1 0.447-1 1v18c0 0.553 0.447 1 1 1h22c0.553 0 1-0.447 1-1v-18c0-0.553-0.447-1-1-1zM8 10c0-4.411 3.589-8 8-8s8 3.589 8 8v2h-16v-2zM26 30h-20v-16h20v16z"
></path>
<path
d="M15 21.694v4.306h2v-4.306c0.587-0.348 1-0.961 1-1.694 0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.732 0.413 1.345 1 1.694z"
></path>
</svg>
Login
</button>
</form>
<div class="auth__action">
<p>Haven't signed up yet?</p>
<a href="{% url 'register' %}" class="btn btn--link">Sign Up</a>
</div>
</div>
</div>
</div>
{% else %}
<div class="container">
<div class="layout__box">
<div class="layout__boxHeader">
<div class="layout__boxTitle">
<h3>Login</h3>
</div>
</div>
<div class="layout__body">
<h2 class="auth__tagline">Find your study partner</h2>
{% for field in form %}
<form class="form" action="#" method="POST">
{% csrf_token %}
<div class="form__group form__group">
<label for="room_name">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<button class="btn btn--main" type="submit">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<title>lock</title>
<path
d="M27 12h-1v-2c0-5.514-4.486-10-10-10s-10 4.486-10 10v2h-1c-0.553 0-1 0.447-1 1v18c0 0.553 0.447 1 1 1h22c0.553 0 1-0.447 1-1v-18c0-0.553-0.447-1-1-1zM8 10c0-4.411 3.589-8 8-8s8 3.589 8 8v2h-16v-2zM26 30h-20v-16h20v16z"
></path>
<path
d="M15 21.694v4.306h2v-4.306c0.587-0.348 1-0.961 1-1.694 0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.732 0.413 1.345 1 1.694z"
></path>
</svg>
Register
</button>
</form>
<div class="auth__action">
<p>Haven't signed up yet?</p>
<a href="{% url 'register' %}" class="btn btn--link">Sign Up</a>
</div>
</div>
</div>
</div>
</main>
{% endif %}
{% endblock content %}
<ul class="topics__list">
<li>
<a href="{% url 'topics' %}" class="active">All <span>{{topcis.count}}</span></a>
</li>
{% for topic in topics %}
<li>
<a href="/">{{ topic.name }} <span>{{topic.room_set.all.count}}</span></a>
</li>
{% endfor %}
</ul>
<li>
<a href="{% url 'topics' %}" class="active">All <span>{{topcis.count}}</span></a>
</li>
{% for topic in topics %}
<li>
<a href="{% url 'home' %}?q={{topic.name}}">{{ topic.name }} <span>{{topic.room_set.all.count}}</span></a>
</li>
{% endfor %}
def topicsPage(request) :
q = request.GET.get('q') if request.GET.get('q') != None else ''
topics = Topic.objects.filter(name__icontains=q)
return render(request, 'base/topics.html', {'topics':topics})
<form action="" method="GET" class="header__search">
<label>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>search</title>
<path
d="M32 30.586l-10.845-10.845c1.771-2.092 2.845-4.791 2.845-7.741 0-6.617-5.383-12-12-12s-12 5.383-12 12c0 6.617 5.383 12 12 12 2.949 0 5.649-1.074 7.741-2.845l10.845 10.845 1.414-1.414zM12 22c-5.514 0-10-4.486-10-10s4.486-10 10-10c5.514 0 10 4.486 10 10s-4.486 10-10 10z"
></path>
</svg>
<input name="q" placeholder="Search for topics" />
</label>
</form>
home 함수에 가서
topics = Topic.objects.all()[:5]
<a class="btn btn--main btn--pill" href="{% url 'activity' %}">Recent Activities</a>
def activityPage(request) :
room_messages = Message.objects.all()
return render(request, 'base/activity.html', {})
path('activity/', views.activityPage, name="activity"),
def activityPage(request) :
room_messages = Message.objects.all()
return render(request, 'base/activity.html', {'room_messages':room_messages})
{% extends 'main.html' %}
{% block content %}
<main class="layout">
<div class="container">
<div class="layout__box">
<div class="layout__boxHeader">
<div class="layout__boxTitle">
<a href="{% url 'home' %}">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>arrow-left</title>
<path
d="M13.723 2.286l-13.723 13.714 13.719 13.714 1.616-1.611-10.96-10.96h27.625v-2.286h-27.625l10.965-10.965-1.616-1.607z"
></path>
</svg>
</a>
<h3>Recent Activities</h3>
</div>
</div>
<div class="activities-page layout__body">
{% for message in room_messages %}
<div class="activities__box">
<div class="activities__boxHeader roomListRoom__header">
<a href="{% url 'user-profile' message.user.id %}" class="roomListRoom__author">
<div class="avatar avatar--small">
<img src="https://randomuser.me/api/portraits/women/11.jpg" />
</div>
<p>
@{{message.user}}
<span>{{message.created|timesince}} days ago</span>
</p>
</a>
{% if request.user == message.user %}
<div class="roomListRoom__actions">
<a href="{% url 'delete-message' message.id %}">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>remove</title>
<path
d="M27.314 6.019l-1.333-1.333-9.98 9.981-9.981-9.981-1.333 1.333 9.981 9.981-9.981 9.98 1.333 1.333 9.981-9.98 9.98 9.98 1.333-1.333-9.98-9.98 9.98-9.981z"
></path>
</svg>
</a>
</div>
{% endif %}
</div>
<div class="activities__boxContent">
<p>replied to post “<a href="{% url 'room' message.room.id %}">{{message.room}}</a>”</p>
<div class="activities__boxRoomContent">
{{message.body}}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</main>
{% endblock %}
from django.http import JsonResponse
def getRoutes(request) :
routes = [
'GET /api',
'GET /api/rooms',
'GET /api/rooms/:id',
]
return JsonResponse(routes, safe=False)
import django
from django.urls import path
from . import views
urlpatterns = [
path('', views.getRoutes),
]
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('base.urls')),
path('api/', include('base.api.urls'))
]
https://www.django-rest-framework.org/
가서 설치
pip install djangorestframework
# settings.py 가서
INSTALLED_APPS = [
...
'rest_framework',
]
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def getRoutes(request) :
routes = [
'GET /api',
'GET /api/rooms',
'GET /api/rooms/:id',
]
return Response(routes)
이런식으로 화면이 뜸
from base.models import Room
@api_view(['GET'])
def getRooms(request) :
rooms = Room.objects.all()
return Response(rooms)
path('api/', include('base.api.urls'))
... 그러니 리스트 형태여서 오류가 남
from rest_framework.serializers import ModelSerializer
from base.models import Room
class RoomSerializer(ModelSerializer) :
class Meta:
model = Room
fields = '__all__'
from .serializers import RoomSerializer
@api_view(['GET'])
def getRooms(request) :
rooms = Room.objects.all()
serializer = RoomSerializer(rooms,many=True) # multiple object 인지
return Response(serializer.data)
@api_view(['GET'])
def getRoom(request,pk) :
rooms = Room.objects.get(id=pk)
serializer = RoomSerializer(rooms,many=False) # multiple object 인지
return Response(serializer.data)
path('rooms/<str:pk>',views.getRoom),
python -m pip install django-cors-headers
...
https://pypi.org/project/django-cors-headers/
여기 문서 보면서 cors headers 관련 오류 찾기
INSTALLED_APPS = [
...,
"corsheaders",
...,
]
MIDDLEWARE = [
...,
"corsheaders.middleware.CorsMiddleware",
...,
]
CORS_ALLOW_ALL_ORIGINS = True
이러면 돌아감
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cool Rooms</title>
</head>
<body>
<h1>Cools Rooms</h1>
<div id="rooms-container"></div>
</body>
<script>
let getRooms = async () => {
let response = await fetch('http://127.0.0.1:8000/api/rooms/')
console.log('RESPONSE:', response)
}
getRooms()
</script>
</html>
그리고
<script>
let getRooms = async () => {
let response = await fetch('http://127.0.0.1:8000/api/rooms/')
let rooms = await response.json()
console.log('rooms:', rooms)
}
getRooms()
</script>
console 창 가면 데이터를 받아 온 것을 볼 수 있음
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cool Rooms</title>
</head>
<body>
<h1>Cools Rooms</h1>
<div id="rooms-container"></div>
</body>
<script>
let roomsContainer = document.getElementById('rooms-container')
let getRooms = async () => {
let response = await fetch('http://127.0.0.1:8000/api/rooms/')
let rooms = await response.json()
console.log('rooms:', rooms)
for(let i=0; i<rooms.length ; i++) {
let room = rooms[i]
let row = `<div><h3>${room.name}</h3></div>`
roomsContainer.innerHTML += row
}
}
getRooms()
</script>
</html>
installed_app 에
'base.app.BaseConfig',
AUTH_USER_MODEL = 'base.User'
이거 추가
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser) :
pass
makemigrations , migrate ...
createsuperuser 하고
admin.py 가서
from .models import User
admin.site.register(User)
해주기
그리고 어드민 페이지에서 체크
from django.contrib.auth.models import AbstractUser
class User(AbstractUser) :
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True)
bio = models.TextField(null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
이러면 이메일로 로그인 가능하고 여러가지 필드 관련해서 만들 수 있음
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser) :
pass
AUTH_USER_MODEL = 'base.User'
admin.site.register(User)
from django.contrib.auth.models import User
class User(AbstractUser) :
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True)
bio = models.TextField(null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
서버 끄고
python3 -m pip install pillow
그리고 다시 서버 키기
avatar = models.ImageField(null=True, default="avatar.svg")
MEDIA_URL = '/images/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
from django.conf import settings
from django.conf.urls.static import static
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
이미지 테그 찾아서
<img src="{{room.host.avatar.url}}" />
와 같이 변경
<img src="{{request.user.avatar.url}}" />
<img src="{{room.host.avatar.url}}" />
<img src="{{message.user.avatar.url}}" />
나머지는 이와 같이 계속 해서 진행 됨
from django.contrib.auth.forms import UserCreationForm
class UserForm(ModelForm) :
class Meta :
model = User
fields = ['avatar','name','username','email','bio']
같은 코드를 입력
<form class="form" action="#" method="POST" enctype="multipart/form-data">
다양한 폼 넘겨준다는 의미
@login_required(login_url='login')
def updateUser(request) :
user = request.user
form = UserForm(instance=user)
if request.method == 'POST' :
form = UserForm(request.POST, request.FILES , instance=user) # 주어진 파일
if form.is_valid() :
form.save()
return redirect('user-profile', pk=user.id)
return render(request, 'base/update-user.html',{'form':form})
class MyUserCreationForm(UserCreationForm) :
class Meta :
model = User
fields = ['name','username','email','password1','password2']
# from django.contrib.auth.forms import UserCreationForm
# 이부분 제거
from .forms import RoomForm, UserForm ,MyUserCreationForm
# 추가
UserCreationForm >> MyUserCreationForm
def registerPage(request) :
page = 'register'
form = MyUserCreationForm()
if request.method == 'POST' :
form = MyUserCreationForm(request.POST)
if form.is_valid() :
user = form.save(commit=False) # 전처리
user.username = user.username.lower() # 대문자 소문자로 처리
user.save()
login(request,user)
return redirect('home')
else :
messages.error(request, 'An error occured during registration')
return render(request, 'base/login_register.html',{'form':form})
<div class="form__group form__group">
<label for="room_name">Email</label>
<input id="username" name="email" type="text" placeholder="e.g. dennis_ivy" />
</div>
def loginPage(request) :
page ='login'
if request.user.is_authenticated :
return redirect('home')
if request.method == 'POST' :
email = request.POST.get('email').lower()
password = request.POST.get('password')
try:
user = User.objects.get(email=email)
except:
messages.error(request, 'User does not exist')
user = authenticate(request,email=email, password=password)
if user is not None :
login(request, user)
return redirect('home')
else :
messages.error(request, 'Username OR password does not exit')
username 부분을 email 로 바꾸기