Skip to content

Latest commit

ย 

History

History
200 lines (167 loc) ยท 8.5 KB

File metadata and controls

200 lines (167 loc) ยท 8.5 KB

๋ชจ๋ธ ๊ด€๊ณ„ ๊ฐœ๋…

์ผ๋Œ€๋‹ค ๊ด€๊ณ„

์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋Š” ๊ฒŒ์‹œ๊ธ€-๋Œ“๊ธ€ ๊ด€๊ณ„๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ์‰ฝ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€์— ์—ฌ๋Ÿฌ ๋Œ“๊ธ€์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์—ˆ๋˜ Blog๋ชจ๋ธ๊ณผ ๊ฐ™์€ Post๋ชจ๋ธ์„ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด, ๋Œ“๊ธ€์— ํ•ด๋‹นํ•˜๋Š” Comment๋ชจ๋ธ์„ ์—ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

class Post(models.Model):
...
class Comment(models.Model):
	post = models.Foreignkey(Post, on_delete = models.CASCADE)

ORM์„ ์ด์šฉํ•ด ์ƒ๋Œ€ ๋ชจ๋ธ์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•

  • N->1: comment.post
  • 1->N: post.comment_set, post.comment_set.all(), post.comment_set.count()

N์—์„œ๋Š” ๊ด€๊ณ„๋˜์–ด ์žˆ๋Š” ๋ชจ๋ธ์ด ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, 1์ธ ์ชฝ์€ ์—ฌ๋Ÿฌ ๊ฐ์ฒด์™€ ์—ฐ๊ด€๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— set์„ ํ†ตํ•ด ์ ‘๊ทผํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ์‹œ๊ธ€์ด ์‚ญ์ œ๋œ๋‹ค๋ฉด ๊ทธ ๊ฒŒ์‹œ๊ธ€์— ์žˆ๋˜ ๋Œ“๊ธ€์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ง€์— ๋Œ€ํ•œ ์„ค์ •์„ ํ•˜๊ธฐ ์œ„ํ•ด on_delete ์ธ์ž๋ฅผ ์ž‘์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

on_delete์„ค์ •: 1์ชฝ์˜ ๋ฐ์ด์ฒ˜ ์‚ญ์ œ์‹œ N์ชฝ์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

  • CASCADE: ๋ชจ๋“  N์ชฝ์˜ ๋ฐ์ดํ„ฐ ์‚ญ์ œ
  • PROTECT: 1์ชฝ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ญ์ œ๋˜์ง€ ์•Š๋„๋ก ๋ณดํ˜ธ.
  • SET_NULL: null๊ฐ’์„ ๋Œ€์ฒด, ํ•„๋“œ์— default=True์˜ต์„ ์„ ์ถ”๊ฐ€ํ•ด์•ผํ•จ.
  • SET: ๋Œ€์ฒดํ•  ๊ฐ’์ด๋‚˜ ํ•จ์ˆ˜๋ฅผ ์ง€์ •
  • DO_NOTHING: ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Œ, ๋‹ค๋งŒ DB์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋ฆ„

์ผ๋Œ€์ผ ๊ด€๊ณ„

์ผ๋Œ€์ผ ๊ด€๊ณ„๋Š” ์œ ์ €-ํ”„๋กœํ•„ ๊ด€๊ณ„๋กœ ์ดํ•ดํ•˜๋ฉด ์‰ฝ์Šต๋‹ˆ๋‹ค. ์„œ๋กœ ๋Œ€์‘๋˜๋Š” ๊ฒƒ์ด ์œ ์ผํ•œ ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ Django์— ๊ธฐ๋ณธ์ ์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ๋Š” User ๋ชจ๋ธ๊ณผ ์ด๋ฅผ ์ปค์Šคํ…€ํ•ด ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” Profile๋ชจ๋ธ์„ ์—ฐ๊ฒฐํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

class User(AbstractBasaeUser):
...
class Profile(models.Model):
	user = models.OneTooneField(User, on_delete=models.CASCADE)

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋Œ€์ƒ ํด๋ž˜์Šค๊ฐ€ ์‚ญ์ œ๋  ๊ฒฝ์šฐ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ on_delete์„ค์ •์„ ํ•ด์ค๋‹ˆ๋‹ค.

์ƒ๋Œ€ ๋ชจ๋ธ์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์€ user.profile, profile.user ์ž…๋‹ˆ๋‹ค. ์„œ๋กœ ๋Œ€์‘๋˜๋Š” ๋ชจ๋ธ์ด ์œ ์ผํ•˜๋ฏ€๋กœ ๋ฐ”๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„

๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋Š” ํฌ์ŠคํŠธ-ํƒœ๊ทธ ๊ด€๊ณ„๋กœ ์ดํ•ดํ•˜๋ฉด ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํƒ€๊ทธ๋žจ ๊ฒŒ์‹œ๊ธ€์„ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๊ฒŒ์‹œ๊ธ€์€ ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ•ด์‹œํƒœ๊ทธ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , ํ•˜๋‚˜์˜ ํ•ด์‹œํƒœ๊ทธ์— ํ•ด๋‹น๋˜๋Š” ๊ฒŒ์‹œ๊ธ€์ด ์—ฌ๋Ÿฌ๊ฐœ ์ผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋Š” ์–ด๋Š ๋ชจ๋ธ์„ ์„ ํƒํ•ด ์ž‘์„ฑํ•ด์ฃผ์–ด๋„ ๋ฌด๋ฐฉํ•˜์ง€๋งŒ ์ถ”๊ฐ€ ๋˜๋Š” ๋ชจ๋ธ์— ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ๋จผ์ € ์„ ์–ธ๋œ ๋ชจ๋ธ์—์„œ ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•ด์ฃผ๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ž์—ด('Tag')๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

class Post(models.Model):
	tag = models.ManyToManyField('Tag', blank=True)

class Tag(models.Model):
...
class Post(models.Model):
...
class Tag(models.Model):
	post = models.MnyToManyField(Post, blank=True)

Django-allauth

์ง์ ‘ ์œ ์ €๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜์—ฌ ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ django-allauth๋ฅผ ์ด์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. allauth ์„ค์น˜

$ pip install django-allauth

2. basic/settings.py

๋จผ์ € settings.py์— ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

INSTALLED_APPS = [
    ...
	# ์‚ฌ์ดํŠธ ํ”„๋ ˆ์ž„์›Œํฌ, ์‚ฌ์ดํŠธ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    'django.contrib.sites',
    # allauth ๊ด€๋ จ ์•ฑ: ์ผ๋ฐ˜ ๊ณ„์ • ๊ด€๋ฆฌ, ์†Œ์…œ ๊ณ„์ • ๊ด€๋ฆฌ
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
]
...
AUTHENTICATION_BACKENDS=[
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
# admin ํŽ˜์ด์ง€ ๊ด€๋ฆฌ ๋ฒˆํ˜ธ, ๋‹จ์ผ ์„œ๋ฒ„๋Š” 1์„ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.
SITE_ID=1

# ๋กœ๊ทธ์ธ ๋˜๋ฉด ์ด๋™ํ•˜๋Š” ํŽ˜์ด์ง€, ๋งŒ์•ฝ ๊ธ€ ๋ชฉ๋ก์œผ๋กœ ์ด๋™ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด '/posts/'
# ๋ฉ”์ธํ™”๋ฉด์œผ๋กœ ์ด๋™
LOGIN_REDIRECT_URL='/'

3.basic/urls.py

urls.py์—์„œ url์—ฐ๊ฒฐ๋„ ํ•ด์ค๋‹ˆ๋‹ค.

urlpatterns = [
    ...
    path('accounts/', include('allauth.urls')),
]

๊ทธ ๋‹ค์Œ์— migrate๋ฅผ ํ•ด์ค๋‹ˆ๋‹ค. $ python manage.py migrate ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋ธ์„ ๋งŒ๋“ค์ง€๋Š” ์•Š์•˜์ง€๋งŒ, django-allauth ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ชจ๋ธ์„ ์ ์šฉ์‹œ์ผœ์ฃผ๊ธฐ ์œ„ํ•ด ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

4. ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ์ถ”๊ฐ€ํ•˜๊ธฐ

basic/templates/shared/_navbar ๋„ค๋ธŒ๋ฐ”์— ๋กœ๊ทธ์ธ๊ณผ ํšŒ์›๊ฐ€์ž…์„ ์ถ”๊ฐ€ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

<li class="nav-item dropdown">
  <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
    Account
  </a>
  <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
    {% if user.is_authenticated %} # ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋ผ๋ฉด
    <li><a class="dropdown-item" href="{%url 'account_logout' %}">Logout</a></li>
    {% else %} # ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด
    <li><a class="dropdown-item" href="{% url 'account_login' %}">Login</a></li>
    <li><a class="dropdown-item" href="{%url 'account_signup' %}">Signup</a></li>
    {% endif %}
  </ul>
</li>

๋กœ๊ทธ์ธํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” ๋กœ๊ทธ์•„์›ƒ์„ ๋ณด์—ฌ์ฃผ๋„๋ก, ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋กœ๊ทธ์ธ๊ณผ ํšŒ์›๊ฐ€์ž…์„ ๋ณด์—ฌ์ฃผ๋„๋ก if๋ฌธ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค๋‹ˆ๋‹ค.

5. ๋กœ๊ทธ์ธํ–ˆ์„ ๊ฒฝ์šฐ์— ๊ธ€์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๊ธฐ

๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์•„๋„ ๊ธ€์„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์ƒ๊ด€์—†๋‹ค๋ฉด ๊ตณ์ด ํ•˜์ง€ ์•Š์•„๋„ ๋˜์ง€๋งŒ, ๋กœ๊ทธ์ธํ•œ ํšŒ์›๋“ค๋งŒ ๊ธ€์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. main/templates/main/posts.html

{% extends 'base.html' %}
{% load static %}

{% block content %}
<div class="container">
    {% if user.is_authenticated %}
    <h1>๊ธ€ ๋ชฉ๋ก</h1>
    <div>
        {% for blog in blogs %}
        <div>
            <h3>{{blog.title}}</h3>
            {{blog.writer}}<br>
            {{blog.summary}}
            <a href="{%url 'main:detail' blog.id%}">...more</a>
            <br><hr>
        </div>
        {%endfor%}
    </div>
    {% else %}
    <h3>๋กœ๊ทธ์ธ ํ›„ ์ด์šฉ ๊ฐ€๋Šฅ</h3>
    <a href="{% url 'account_login' %}" class="btn btn-warning">๋กœ๊ทธ์ธ</a>
    <a href="{% url 'account_signup' %}"  class="btn btn-warning">ํšŒ์›๊ฐ€์ž…</a>
    {% endif %}
</div>
{% endblock %}

๐Ÿ’ก ๋กœ๊ทธ์ธ, ๋กœ๊ทธ์•„์›ƒ, ํšŒ์›๊ฐ€์ž… ๋“ฑ์˜ ํŽ˜์ด์ง€ ์ปค์Šคํ…€ ๋ฐฉ๋ฒ•

๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ํŽ˜์ด์ง€๊ฐ€ ์˜ˆ์˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์•„๋ž˜ ์‚ฌ์ดํŠธ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

6. ๊ธ€ ์ž‘์„ฑ์ž๋ฅผ User ๋ชจ๋ธ๊ณผ ์—ฐ๊ฒฐํ•˜๊ธฐ

์ด์ „์—๋Š” ๊ธ€ ์ž‘์„ฑ์ž๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์ˆ˜๊ธฐ๋กœ ์ž…๋ ฅํ•˜๋„๋ก ์„ค์ •ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์„ user ๋ชจ๋ธ์˜ ์ •๋ณด์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋ฅผใ„น ์ž‘์„ฑ์ž๋กœ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์„ ์ˆ˜์ •ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์— ์ž‘์„ฑํ–ˆ๋˜ ๊ธ€์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ db๋ฅผ ์ง€์›Œ์ฃผ๊ณ  ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

DB ์‚ญ์ œ

db.sqlite3 ํŒŒ์ผ์„ ์‚ญ์ œํ•ด์ฃผ์„ธ์š”.

์ž‘์„ฑ์ž input ํƒœ๊ทธ ์‚ญ์ œ

main/templates/main/new.html

  • <p>์ž‘์„ฑ์ž : <input type="text" name="writer"></p>

main/templates/main/edit.html

  • <p>์ž‘์„ฑ์ž : <input type="text" name="writer" value="{{blog.writer}}"></p>

์—์„œ ์ž‘์„ฑ์ž input ํƒœ๊ทธ๋ฅผ ์ง€์›Œ์ฃผ์„ธ์š”.

main/views.py

def create(request):
    ...
    new_blog.writer = request.user
    
def update(request, id):
    ...
    update_blog.writer = request.user    

create์™€ updateํ•จ์ˆ˜์—์„œ ์ž‘์„ฑ์ž ๋ถ€๋ถ„์„ ํ˜„์žฌ ์ž‘์—…์„ ์ˆ˜ํ–‰์ค‘์ธ ์œ ์ €๋ฅผ ์ €์žฅํ•˜๋„๋ก ๋ฐ”๊พธ์–ด์ค๋‹ˆ๋‹ค.

Blog๋ชจ๋ธ์˜ writer์†์„ฑ์„ ์œ ์ € ๋ชจ๋ธ๊ณผ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋กœ ์ˆ˜์ •

from django.contrib.auth.models import User

class Blog(models.Model):
    ...
    writer = models.ForeignKey(User, on_delete=models.CASCADE)

๋จผ์ € django-allauth์˜ User๋ชจ๋ธ์„ import ํ•ด์ค๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Blog๋ชจ๋ธ์˜ writer์†์„ฑ์„ ์ด User๋ชจ๋ธ๊ณผ ์—ฐ๊ฒฐํ•ด์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ฒŒ์‹œ๊ธ€์—๋Š” ํ•œ ๋ช…์˜ ์ž‘์„ฑ์ž๋งŒ ์žˆ๊ณ , ์ž‘์„ฑ์ž๋Š” ์—ฌ๋Ÿฌ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. ๋งจ ์ฒ˜์Œ์— ๋ชจ๋ธ ๊ด€๊ณ„ ๊ฐœ๋…๋•Œ ๋ดค๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋Š” '๋‹ค'์ชฝ์— ํ•ด๋‹นํ•˜๋Š” ๋ชจ๋ธ์— ForeignKey๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ฒŒ์‹œ๊ธ€์ด ์ง€์›Œ์ง€๋ฉด ๊ทธ ๊ฒŒ์‹œ๊ธ€์˜ ์ž‘์„ฑ์ž ์ •๋ณด๋ฅผ ํ•„์š”์—†์œผ๋ฏ€๋กœ ์ง€์›Œ์ง€๋„๋ก on_delete ์„ค์ •์„ ํ•ด์ค๋‹ˆ๋‹ค.

migrate

๋ชจ๋ธ์„ ์ˆ˜์ •ํ•˜์˜€์œผ๋‹ˆ migrateํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. $ python manage.py makemirgations

$ python manage.py migrate