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

Django로 홈페이지 만들기 - #7 mypage, userpage, profile update

integerJI 2020. 5. 4. 15:15


참고 사이트

보고 배운 곳

https://code1018.tistory.com/246?category=987693

 

오늘 사용한 App

myMember

 

생성한 파일 & 폴더

myMember/tamplates/mypage.html - 파일 생성

myMember/tamplates/profile_update.html - 파일 생성

myMember/tamplates/userpage.html - 파일 생성

 

포인트

user모델에서 확장한 profile를 가져오는 것

myApp에서도 profile를 가져와 프로필 사진을 보여주는 방법

ProfileUpdateView의 사용

 

완성된 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


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


myMember

<!--myProject/myMember/templates/mypage.html-->

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

<div class="cantrion">
    <div class="row justify-content-center">
        <div class="col-md-4 order-md-1">
            <img class="img-fluid rounded-circle" width="250" height="250"
                src="{% if profile_pic %} {{profile_pic}} {% else %} /static/default.jpg {% endif %}"
                preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail">
        </div>
        <div class="col-md-2 order-md-2 mb-4">
            <br>
            <h3 class="mb-0">{{ id }}</h3>
            {% if intro %}
            <p class="card-text mb-auto">{{ intro | linebreaksbr}}</p>
            {% else %}
            {% endif %}
            <br>
            <a href="{% url 'profile_update' %}">Profile Update</a>
        </div>
    </div>

    <div class="album py-5">
        <div class="container">
            <div class="row">
                {% for post in posts.all %}
                <div class="col-md-4">
                    <div class="card mb-4 shadow-sm">
                        <img src="{{post.create_img.url}}" class="rounded" alt="..." width="100%" height="300">
                    </div>
                </div>
                {% endfor %}
            </div>
        </div>
    </div>

</div>
{% endblock %}
<!--myProject/myMember/templates/profile_update.html-->

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

<div class="cantrion">
    <div class="row justify-content-center">
        <div class="col-md-4 order-md-1 d-flex align-items-center">
            <img class="img-fluid rounded-circle" width="250" height="250" src="{{profile.profile_image.url}}"
                preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail">
        </div>

        <div class="col-md-2 order-md-2 mb-4">
            <br>
            <h3 class="mb-0">{{user.username}}</h3>
            <form method="POST" class="post-form" enctype="multipart/form-data" action="">
                {%csrf_token%}
                <br>

                {{ profile_form.intro }}
                <br>
                {{ profile_form.profile_image }}
                <br>
                <br>

                <input type="submit" value="Update">
                <a href="{% url 'index' %}">
                    <button type="button">Cancel</button>
                </a>
            </form>

        </div>
    </div>

</div>
{% endblock %}
<!--myProject/myMember/templates/userpage.html-->

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

<div class="cantrion">
    <div class="row justify-content-center">
        <div class="col-md-4 order-md-1">
            <img class="img-fluid rounded-circle" width="250" height="250"
                src="{% if profile_pic %} {{profile_pic}} {% else %} /static/default.jpg {% endif %}"
                preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail">
        </div>
        <div class="col-md-2 order-md-2 mb-4">
            <br>
            <h3 class="mb-0">{{ id }}</h3>
            {% if intro %}
            <p class="card-text mb-auto">{{ intro | linebreaksbr}}</p>
            {% else %}
            {% endif %}
            <br>
            <a href="{% url 'index' %}">Home</a>
        </div>
    </div>

    <div class="album py-5">
        <div class="container">
            <div class="row">
                {% for post in posts.all %}
                <div class="col-md-4">
                    <div class="card mb-4 shadow-sm">
                        <img src="{{post.create_img.url}}" class="rounded" alt="..." width="100%" height="300">
                    </div>
                </div>
                {% endfor %}
            </div>
        </div>
    </div>

</div>
{% endblock %}
# myProject/myMember/forms.py

class ProfileUpdateForm(forms.ModelForm):
    profile_image = forms.ImageField(required=False)

    class Meta:
        model = Profile
        fields = ['intro','profile_image']

        widgets = {
            'intro': forms.TextInput(attrs={'class': 'form-control'}),
            'profile_image' : forms.ClearableFileInput(attrs={'class': 'form-control-file', 'onchange': 'readURL(this);'}),
        }

        labels = {
            'profile_image': '프로필 사진',
            'intro': '인사말',
        }
# myProject/myMember/urls.py

path('mypage/', views.userinfo, name='mypage'),
path('userpage/<str:writer>', views.user_select_info, name='userpage'),
path('profile_update', views.ProfileUpdateView.as_view(), name='profile_update'),
# myProject/myMember/views.py

from .forms import UserCreationMultiForm, ProfileForm, ProfileUpdateForm
from myApp.models import Post

@login_required
def userinfo(request):
    conn_user = request.user
    posts = Post.objects.all().filter(create_user=conn_user).order_by('-id')
    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,
    }

    return render(request, 'mypage.html', context=context)

@login_required
def user_select_info(request, writer):
    select_profile = Profile.objects.get(nick=writer)
    select_user = select_profile.user
    posts = Post.objects.all().filter(create_user=select_user).order_by('-id')

    if not select_profile.profile_image:
        pic_url = ""
    else:
        pic_url = select_profile.profile_image.url
            
    context = {
        'id' : select_user.username,
        'nick' : select_profile.nick,
        'profile_pic' : pic_url,
        'intro' : select_profile.intro,
        'posts' : posts,
    }

    return render(request, 'userpage.html', context=context)


class ProfileUpdateView(View): 
    def get(self, request):
        user = get_object_or_404(User, pk=request.user.pk) 

        if hasattr(user, 'profile'):  
            profile = user.profile
            profile_form = ProfileUpdateForm(initial={
                'nick': profile.nick,
                'intro': profile.intro,
                'profile_image': profile.profile_image,
            })
        else:
            profile_form = ProfileUpdateForm()

        return render(request, 'profile_update.html', { "profile_form": profile_form, "profile": profile})

    def post(self, request):
        u = User.objects.get(id=request.user.pk)       


        if hasattr(u, 'profile'):
            profile = u.profile
            profile_form = ProfileUpdateForm(request.POST, request.FILES, instance=profile) 
        else:
            profile_form = ProfileUpdateForm(request.POST, request.FILES)

        # Profile 폼
        if profile_form.is_valid():
            profile = profile_form.save(commit=False) 
            profile.user = u
            profile.save()

            if not profile.profile_image:
                pic_url = ""
            else:
                pic_url = profile.profile_image.url
                    
            context = {
                'id' : u.username,
                'nick' : profile.nick,
                'profile_pic' : pic_url,
                'intro' : profile.intro,
            }

            return render(request, 'mypage.html', context=context)
            
        return redirect('mypage', pk=request.user.pk) 

 

myApp

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

# .. 생략

{% 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="{% url 'userpage' post.create_user %}"><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="{% url 'update' post.id %}"><img src="/static/update.png" alt="update"
              style="width: 1.5rem; height:1.5rem;">&nbsp;</a>
          <a href="{% url 'delete' post.id %}" onclick="return confirm('정말 삭제하시겠습니까?')"><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">
        <small class="text-muted">{{post.comments.count}} comment</small>
        <br>
#★        <a class="my-0 font-weight-normal" href="{% url 'userpage' post.create_user %}">{{ post.create_user }}</a>
        <a class="card-title pricing-card-title">{{ post|safe|linebreaksbr }}</a>
        <br>
        {% for comment in post.comments.all %}
#★        <a class="card-text" href="{% url 'userpage' comment.comment_user %}"><span
            class="comment_writer_name">{{comment.comment_user}}</span></a>
        <a class="card-text">{{comment.comment_text}}
          <span class="control hidden" id="control_id1{{ forloop.counter0 }}">
            <form action="{% url 'c_delete' post.pk comment.pk %}" method="POST" style="display:inline-block">
              {% csrf_token %}
              <input type="`" name="app_url" id="app_url" value="{{app_url}}" />
              <button type="submit">삭제</button>
            </form>
          </span>
          <br>
          {% endfor %}
          <small class="text-muted">{{ post.create_date }}</small>
          <br>
          <div class="group">
            <form action="{% url 'c_post' post.id %}" method="POST">
              {% csrf_token %}
              <div class="input-group input-group-sm mb-3">
                <input type="text" class="form-control" aria-label="Sizing example input"
                  aria-describedby="inputGroup-sizing-sm" name="comment_text" id="comment_text" placeholder="댓글 달기 ..."
                  style="display:inline-block">
                <input type="hidden" name="app_url" id="app_url" value="{{app_url}}" />
                <div class="input-group-prepend">
                  <button class="input-group-text" id="inputGroup-sizing-sm" type="submit">게시</button>
                </div>
              </div>
            </form>
          </div>
      </div>
    </div>
  </div>
</div>
{% endfor %}

# .. 생략

<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="{% url 'mypage' %}">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>
<!-- myProject/myApp/templates/detail.html -->

<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="{% url 'userpage' post.create_user %}"><span
                        class="writer_name">{{ post.create_user }}</span></a>
            </div>
            <div class="btn-group">
                <span class="hidden" id="control_id">
                    <a href="{% url 'update' post.id %}"><img src="/static/update.png" alt="update"
                            style="width: 1.5rem; height:1.5rem;">&nbsp;</a>
                    <a href="{% url 'delete' post.id %}" onclick="return confirm('정말 삭제하시겠습니까?')"><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>
        <small class="text-muted">{{post.comments.count}} comment</small>
        <hr>
        <a class="card-title pricing-card-title">{{ post|safe|linebreaksbr }}<small
                class="text-muted">&nbsp;&nbsp;{{ post.create_date }}</small></a>
        <hr>
        {% for comment in post.comments.all %}
#★        <a class="card-text" href="{% url 'userpage' comment.comment_user %}"><span
                class="comment_writer_name">{{comment.comment_user}}</span></a>
        <small class="text-muted">{{comment.comment_date}}</small>
        <br>
        <a class="card-text">{{comment.comment_text}}
            <span class="control hidden" id="control_id1{{ forloop.counter0 }}">
                <form action="{% url 'c_delete' post.pk comment.pk %}" method="POST" style="display:inline-block">
                    {% csrf_token %}
                    <input type="hidden" name="app_url" id="app_url" value="{{app_url}}" />
                    <button type="submit">삭제</button>
                </form>
            </span>
            <br>
            {% endfor %}
            <form action="{% url 'c_post' post.id %}" method="POST">
                {% csrf_token %}
                <div class="input-group input-group-sm mb-3">
                    <input type="text" class="form-control" aria-label="Sizing example input"
                        aria-describedby="inputGroup-sizing-sm" name="comment_text" id="comment_text"
                        placeholder="댓글 달기 ..." style="display:inline-block">
                    <input type="hidden" name="app_url" id="app_url" value="{{app_url}}" />
                    <div class="input-group-prepend">
                        <button class="input-group-text" id="inputGroup-sizing-sm" type="submit">게시</button>
                    </div>
                </div>
            </form>
    </div>
</aside>

마무리