코딩공부/홈페이지 만들기

Django로 홈페이지 만들기 - #4 글 목록, 글 쓰기

integerJI 2020. 5. 4. 00:47


참고 사이트

views에 데이터 가져오기

https://integer-ji.tistory.com/90

 

detail page 만들기

https://integer-ji.tistory.com/91

 

글쓰기 기능 만들기

https://integer-ji.tistory.com/99

 

오늘 사용한 App

myApp

 

사용한 명령어

python manage.py makemigrations

python manage.py migrate

 

생성한 파일 & 폴더

myApp/tamplates/post.html - 파일 생성

myApp/tamplates/detail.html - 파일 생성

 

포인트

admin으로 접속 시 오류가 남

 - admin페이지로 직접 들어가 admin의 프로필 사진을 설정해주어야 한다.

첫 접속 시 프로필 사진이 안 보이는 이유는 media 경로를 설정 안 해줘서 그런 것이다.

 - 마찬가지로 admin 페이지에서 프로필 사진을 다시 등록해준다.

 

완성된 git ( 2020.06.18 키 노출로 인한 git 비공개 )

https://github.com/integerJI/int_1

 

aws key 노출되다.

https://integer-ji.tistory.com/200

 

aws key 생성시 주의 할점

https://integer-ji.tistory.com/208


사용한 디렉터리 계층구조 및 파일


myApp

<!-- myProject/myApp/templates/index.html -->

{% extends 'base.html' %}
{% block content %}

<head>
    <style>
        .hidden {
            display: none
        }
    </style>
</head>

<body>
    <main role="main" class="container">
        <div class="row justify-content-center">
            <div class="col-md-7 blog-main">
                <div class="container">
                    {% for post in posts.all %}
                    <div class="card-deck mb-3">
                        <div class="card mb-4 shadow-sm">
                            <div class="card-header">

                                <!-- 접속자와 글쓴이가 같으면 -->
                                <div class="btn-group" style="float: left;">
                                    <a class="my-0 font-weight-normal" href="#"><span
                                            class="writer_name">{{ post.create_user }}</span></a>
                                </div>

                                <!-- 점속자와 글쓴이가 같지 않으면 사라짐 -->
                                <div class="btn-group" style="float: right;">
                                    <span class="hidden" id="control_id">
                                        <a href="#"><img src="/static/update.png" alt="update"
                                                style="width: 1.5rem; height:1.5rem;">&nbsp;</a>
                                        <a href="#"><img src="/static/delete.png" alt="delete"
                                                style="width: 1.5rem; height:1.5rem;"></a>
                                    </span>
                                </div>

                            </div>
                            {% if post.create_img %}
                            <div class="text-center">
                                <img src="{{post.create_img.url}}" class="rounded" alt="..." width="585.5dp"
                                    height="585.5dp">
                            </div>
                            {% else %}
                            <a>no</a>
                            {% endif %}
                            <div class="card-body">

                                <a href="{% url 'detail' post.id %}"><img src="/static/detail.png" alt="detail 이동"
                                        style="width: 2rem; height:2rem;"></a>
                                <div class="group">
                                    <a class="my-0 font-weight-normal" href="#">{{ post.create_user }}</a>
                                    <a class="card-title pricing-card-title">{{ post|safe|linebreaksbr }}</a>
                                    <br>
                                    <small class="text-muted">{{ post.create_date }}</small>
                                </div>
                            </div>
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </div>

            <aside class="col-md-3 blog-sidebar">
                <div class="card mb-3 bg-light rounded" style="max-width: 540px;" bg-light rounded>
                    <div class="row no-gutters">
                        <a></a>
                        <div class="col-md-5 d-flex align-items-center d-flex justify-content-center">
                            <img src="{{ profile_pic }}" alt="..." class="rounded-circle" width="60" height="60">
                        </div>
                        <div class="col-md-6">
                            <div class="card-body">
                                <a><span id="user_name">{{user.username}}</span></a>
                                <br>
                                <a href="#">My Profile</a>
                                <br>
                                <a href="{% url 'post' %}">New Post</a>
                            </div>
                        </div>
                    </div>
                </div>
                {% if messages %}
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
                    {% for message in messages %}
                    <strong>{{ message.message }}</strong>
                    {% endfor %}
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                {% endif %}
                <div class="p-3">
                    <h4 class="font-italic">Producer</h4>
                    <ol class="list-unstyled">
                        <li><a href="https://github.com/integerJI">GitHub</a></li>
                        <li><a href="https://www.instagram.com/integer_ji/">Instagram</a></li>
                    </ol>
                    <footer class="my-2 pt-2 text-muted text-center text-small">
                        <p class="mb-1">&copy; 2019-2020 Integer Ji</p>
                    </footer>
                </div>
            </aside>

        </div>
    </main>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script type="text/javascript">

        $("#user_name").text()
        $(".writer_name").text()

        $(".writer_name")
        $(".writer_name")[0].innerHTML

        for (i = 0; i < $(".writer_name").length; i++) {
            if ($("#user_name").text() == $(".writer_name")[i].innerHTML) {
                $("#control_id").removeClass("hidden");
            }
        }
    </script>

</body>
{% endblock %}
<!-- myProject/myApp/templates/post.html -->

{% extends 'base.html' %}
{% block content %}

<body>
    <form method="POST" action="{% url 'post' %}" enctype="multipart/form-data" id="form1" runat="server">
        {%csrf_token%}
        <main role="main" class="container">
            <div class="row justify-content-center">
                <div class="col-md-7 blog-main">
                    <div class="container">
                        <div class="form-group">
                            <img id="blah" src="/static/default.png" alt="your image" width="585.5dp"
                                height="585.5dp" />
                        </div>
                    </div>
                </div>
                <aside class="col-md-3 blog-sidebar">
                    <div class="form-group">
                        <input type="file" class="form-control-file" id="id_images" name="create_img" accept="image/*"
                            onchange="readURL(this);">
                        <br>
                        <textarea class="form-control" rows="7" name="main_text" cols="40" maxlength="150" required
                            id="id_text"></textarea>
                    </div>
                    <div style="float: right;">
                        <input class="btn btn-dark" type="submit" value="post">
                    </div>
                </aside>
            </div>
        </main>
    </form>
</body>
<script type="text/javascript">
    function readURL(input) {
        if (input.files && input.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#blah').attr('src', e.target.result);
            }
            reader.readAsDataURL(input.files[0]);
        }
    }
</script>
{% endblock %}
<!-- myProject/myApp/templates/detail.html -->

{% extends 'base.html' %}
{% block content %}

<head>
    {% if messages %}
    <div class="alert alert-warning alert-dismissible fade show" role="alert">
        {% for message in messages %}
        <strong>{{ message.message }}</strong>
        {% endfor %}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    {% endif %}
</head>

<body>
    <main role="main" class="container">
        <div class="row justify-content-center">

            <div class="col-md-7 blog-main">
                <div class="container">
                    <div class="card-deck mb-3">
                        <div class="card mb-4 shadow-sm">
                            {% if post.create_img %}
                            <div class="text-center">
                                <img src="{{post.create_img.url}}" class="rounded" alt="..." width="585.5dp"
                                    height="585.5dp">
                            </div>
                            {% else %}
                            <a>no</a>
                            {% endif %}
                        </div>
                    </div>
                </div>
            </div>

            <aside class="col-md-3 blog-sidebar">
                <div class="card-header">
                    <div class="d-flex justify-content-between align-items-center">
                        <div class="btn-group">
                            <a class="my-0 font-weight-normal" href="#"><span
                                    class="writer_name">{{ post.create_user }}</span></a>
                        </div>
                        <div class="btn-group">
                            <span class="hidden" id="control_id">
                                <a href="#"><img src="/static/update.png" alt="update"
                                        style="width: 1.5rem; height:1.5rem;">&nbsp;</a>
                                <a href="#"><img src="/static/delete.png" alt="delete"
                                        style="width: 1.5rem; height:1.5rem;"></a>
                            </span>
                        </div>
                    </div>
                </div>
                <div class="card-body">

                    <a href="{% url 'detail' post.id %}"><img src="/static/detail.png" alt="detail 이동"
                            style="width: 2rem; height:2rem;"></a>
                    <br>
                    <hr>
                    <a class="card-title pricing-card-title">{{ post|safe|linebreaksbr }}<small
                            class="text-muted">&nbsp;&nbsp;{{ post.create_date }}</small></a>
                    <hr>
                </div>
            </aside>

        </div>
    </main>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script type="text/javascript">

        $("#user_name").text()
        $(".writer_name").text()

        if ($("#user_name").text() == $(".writer_name").text()) {
            $("#control_id").removeClass("hidden")
        }

        $(".comment_writer_name")
        $(".comment_writer_name")[0].innerHTML

        for (i = 0; i < $(".comment_writer_name").length; i++) {
            if ($("#user_name").text() == $(".comment_writer_name")[i].innerHTML) {
                $("#control_id1" + i).removeClass("hidden");
            }
        }
    </script>

</body>
{% endblock %}
# myProject/myApp/admin.py

from django.contrib import admin
from .models import Post

admin.site.register(Post)
# myProject/myApp/models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
import re

class Post(models.Model):
    main_text = models.CharField(max_length=200)
    create_user = models.ForeignKey(User, on_delete = models.CASCADE)
    create_date = models.DateTimeField('date published', default=timezone.now)
    create_img = models.ImageField(blank=True, upload_to="post/%Y/%m/%d", null=True)

    def __str__(self):
        return self.main_text
# myProject/myApp/urls.py

# Line 8~9
path('post/', views.post, name="post"),
path('detail/<int:post_id>/', views.detail, name="detail"),
# myProject/myApp/views.py

from django.shortcuts import render, redirect, get_object_or_404, reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from .models import Post
from .forms import PostForm
from myMember.models import Profile
from django.contrib import messages

def index(request):
    posts = Post.objects.all().order_by('-id')
    app_url = request.path

    conn_user = request.user
    conn_profile = Profile.objects.get(user=conn_user)

    if not conn_profile.profile_image:
        pic_url = ""
    else:
        pic_url = conn_profile.profile_image.url
            
    context = {
        'id' : conn_user.username,
        'nick' : conn_profile.nick,
        'profile_pic' : pic_url,
        'intro' : conn_profile.intro,
        'posts' : posts,
        'app_url' : app_url,
    }
    return render(request, 'index.html', context=context)

def post(request):
    if request.method == "POST":
        form = PostForm(request.POST, request.FILES)
        
        if form.is_valid(): 
            post = form.save(commit = False)
            post.create_user = User.objects.get(username = request.user.get_username())
            post.save()
        return redirect(reverse('index'))
    else:
        form = PostForm() 
        return render(request, 'post.html', {'form' : form})

def detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    return render(request, 'detail.html', {'post': post})
from django import forms
from django.db import models

from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['main_text', 'create_img']

        widgets = {
            'main_text': forms.TextInput(attrs={'class': 'form-control', 'rows':'7', 'cols':'40', 'maxlength':'150'}),
            'create_img' : forms.ClearableFileInput(attrs={'class': 'form-control-file'}),
        }

        labels = {
            'main_text': '본문 내용',
            'create_img': '사진',
        }

마무리