웹개발
웹개발플러스- 스위터 5
RAN318
2021. 6. 21. 01:43
728x90
반응형
12. 프로필 페이지 모습 만들기 - 전체
- 틀 만들기
- 프로필 페이지의 모습은 메인 페이지와 아주 비슷하기 때문에 우선 복사해오겠습니다.
<body class="has-navbar-fixed-top"> <nav class="navbar is-fixed-top is-white" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <img src="{{ url_for('static', filename='logo.png') }}"> <strong class="is-sparta" style="font-family: 'Stylish', sans-serif;font-size: larger;">SWEETER</strong> </a> </div> </nav> <section class="section"> <article class="media"> <figure class="media-left" style="align-self: center"> <a class="image is-32x32" href="/user/{{ user_info.username }}"> <img class="is-rounded" src="{{ url_for('static', filename=user_info.profile_pic_real) }}"> </a> </figure> <div class="media-content"> <div class="field"> <p class="control"> <input id="input-post" class="input is-rounded" placeholder="무슨 생각을 하고 계신가요?" onclick='$("#modal-post").addClass("is-active")'> </p> </div> </div> </article> <div class="modal" id="modal-post"> <div class="modal-background" onclick='$("#modal-post").removeClass("is-active")'></div> <div class="modal-content"> <div class="box"> <article class="media"> <div class="media-content"> <div class="field"> <p class="control"> <textarea id="textarea-post" class="textarea" placeholder="무슨 생각을 하고 계신가요?"></textarea> </p> </div> <nav class="level is-mobile"> <div class="level-left"> </div> <div class="level-right"> <div class="level-item"> <a class="button is-sparta" onclick="post()">포스팅하기</a> </div> <div class="level-item"> <a class="button is-sparta is-outlined" onclick='$("#modal-post").removeClass("is-active")'>취소</a> </div> </div> </nav> </div> </article> </div> </div> <button class="modal-close is-large" aria-label="close" onclick='$("#modal-post").removeClass("is-active")'></button> </div> </section> <section class="section"> <div id="post-box" class="container"> <div class="box"> <article class="media"> <div class="media-left"> <a class="image is-64x64" href="#"> <img class="is-rounded" src={{ url_for("static", filename="profile_pics/profile_placeholder.png") }} alt="Image"> </a> </div> <div class="media-content"> <div class="content"> <p> <strong>홍길동</strong> <small>@username</small> <small>10분 전</small> <br> 글을 적는 칸 </p> </div> <nav class="level is-mobile"> <div class="level-left"> <a class="level-item is-sparta" aria-label="heart" onclick="toggle_like('', 'heart')"> <span class="icon is-small"><i class="fa fa-heart" aria-hidden="true"></i></span> <span class="like-num">2.7k</span> </a> </div> </nav> </div> </article> </div> </div> </section> </body>
mystyle.css와 myjs.js 파일 임포트하는 것을 잊지 마세요! - 페이지가 로딩되고 나면 포스팅 카드들을 띄워줍니다.
- 프로필 페이지의 모습은 메인 페이지와 아주 비슷하기 때문에 우선 복사해오겠습니다.
- 프로필 영역 만들기
- 프로필 페이지에서는 각 사용자의 프로필이 보여야겠죠!
hero 클래스와 media 클래스를 이용해 만들어보겠습니다.
<section class="hero is-white"> <div class="hero-body" style="padding-bottom:1rem;margin:auto;min-width: 400px"> <article class="media"> <figure class="media-left" style="align-self: center"> <a class="image is-96x96" href="#"> <img class="is-rounded" src="{{ url_for('static', filename=user_info.profile_pic_real) }}"> </a> </figure> <div class="media-content"> <div class="content"> <p> <strong>{{ user_info.profile_name }}</strong> <small>@{{ user_info.username }}</small> <br> {{ user_info.profile_info }} </p> </div> </div> </article> </div> </section>
- 프로필 페이지에서는 각 사용자의 프로필이 보여야겠죠!
13. 프로필 페이지 모습 만들기 - 프로필 수정
- 프로필 수정 & 로그아웃 버튼 만들기
- 내 프로필 페이지에 들어갔을 때에는 프로필 수정과 로그아웃 버튼이 보여야합니다.
<nav id="btns-me" class="level is-mobile" style="margin-top:2rem"> <a class="button level-item has-text-centered is-sparta" aria-label="edit" onclick='$("#modal-edit").addClass("is-active")'> 프로필 수정 <span class="icon is-small"><i class="fa fa-pencil" aria-hidden="true"></i></span> </a> <a class="button level-item has-text-centered is-sparta is-outlined" aria-label="logout" onclick="sign_out()"> 로그아웃 <span class="icon is-small"><i class="fa fa-sign-out" aria-hidden="true"></i></span> </a> </nav>
- 로그아웃 기능은 이미 프로필 시작 코드에 다 들어있었죠? 로그아웃 버튼을 클릭하면 토큰을 삭제하고 로그인 페이지로 이동하면 끝!
function sign_out() { $.removeCookie('mytoken', {path: '/'}); alert('로그아웃!') window.location.href = "/login" }
- 내 프로필 페이지에 들어갔을 때에는 프로필 수정과 로그아웃 버튼이 보여야합니다.
- 프로필 수정 모달 만들기
프로필 수정 버튼을 누르면 나오는 모달입니다.
<div class="modal" id="modal-edit">
<div class="modal-background" onclick='$("#modal-edit").removeClass("is-active")'></div>
<div class="modal-content">
<div class="box">
<article class="media">
<div class="media-content">
<div class="field">
<label class="label" for="input-name">이름</label>
<p class="control">
<input id="input-name" class="input"
placeholder="홍길동" value="{{ user_info.profile_name }}">
</p>
</div>
<div class="field">
<label class="label" for="input-pic">프로필 사진</label>
<div class="control is-expanded">
<div class="file has-name">
<label class="file-label" style="width:100%">
<input id="input-pic" class="file-input" type="file"
name="resume">
<span class="file-cta"><span class="file-icon"><i
class="fa fa-upload"></i></span>
<span class="file-label">파일 선택</span>
</span>
<span id="file-name" class="file-name"
style="width:100%;max-width:100%">{{ user_info.profile_pic }}</span>
</label>
</div>
</div>
</div>
<div class="field">
<label class="label" for="textarea-about">나는 누구?</label>
<p class="control">
<textarea id="textarea-about" class="textarea"
placeholder="자기소개하기">{{ user_info.profile_info }}</textarea>
</p>
</div>
<nav class="level is-mobile">
<div class="level-left">
</div>
<div class="level-right">
<div class="level-item">
<a class="button is-sparta" onclick="update_profile()">업데이트</a>
</div>
<div class="level-item">
<a class="button is-sparta is-outlined"
onclick='$("#modal-edit").removeClass("is-active")'>취소</a>
</div>
</div>
</nav>
</div>
</article>
</div>
</div>
<button class="modal-close is-large" aria-label="close"
onclick='$("#modal-edit").removeClass("is-active")'></button>
</div>
14. 프로필 페이지 기능 만들기
- 내 프로필에서만 프로필 수정기능 보이게 하기
- 프로필 수정 & 로그아웃 버튼은 내 프로필에 들어갔을 때만 보여야겠죠? 서버에서 보내준 status 파라미터를 이용해 내 프로필일 때만 해당 부분을 그리도록 jinja2 문법을 씁니다.
{% if status %} <nav id="btns-me" class="level is-mobile" ...> <div class="modal" id="modal-edit" ...> {% endif %}
- 글을 적는 포스팅 칸과 모달도 내 프로필에서만 보이게 해줍니다.
{% if status %} <section id="section-post" class="section" ...> {% endif %}
이렇게 타인의 프로필가면 수정 버튼 없어진당
- 프로필 수정 & 로그아웃 버튼은 내 프로필에 들어갔을 때만 보여야겠죠? 서버에서 보내준 status 파라미터를 이용해 내 프로필일 때만 해당 부분을 그리도록 jinja2 문법을 씁니다.
- 프로필 수정 기능 만들기
- 프로필 수정 모달에서 이름을 바꾸거나 새 프로필 사진을 업로드하는 경우 파일을 받아 저장해주어야합니다. 프로필 업데이트 후에는 페이지를 새로고침하여 다시 정보를 받아옵니다
// 프로필 수정 클라이언트 function update_profile() { let name = $('#input-name').val() let file = $('#input-pic')[0].files[0] let about = $("#textarea-about").val() let form_data = new FormData() form_data.append("file_give", file) form_data.append("name_give", name) form_data.append("about_give", about) console.log(name, file, about, form_data) $.ajax({ type: "POST", url: "/update_profile", data: form_data, cache: false, contentType: false, processData: false, success: function (response) { if (response["result"] == "success") { alert(response["msg"]) window.location.reload() } } }); }
//프로필 수정 서버 @app.route('/update_profile', methods=['POST']) def save_img(): token_receive = request.cookies.get('mytoken') try: payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256']) username = payload["id"] name_receive = request.form["name_give"] about_receive = request.form["about_give"] new_doc = { "profile_name": name_receive, "profile_info": about_receive } if 'file_give' in request.files: file = request.files["file_give"] filename = secure_filename(file.filename) extension = filename.split(".")[-1] file_path = f"profile_pics/{username}.{extension}" file.save("./static/"+file_path) new_doc["profile_pic"] = filename new_doc["profile_pic_real"] = file_path db.users.update_one({'username': payload['id']}, {'$set':new_doc}) return jsonify({"result": "success", 'msg': '프로필을 업데이트했습니다.'}) except (jwt.ExpiredSignatureError, jwt.exceptions.DecodeError): return redirect(url_for("home"))
선생님이 업데이트 해보셨다 선생님 프로필이 수정이되었다. 포스팅해도 변경된 프로필로 포스팅이 되어요 *왜 제 화면이 아니냐구요? 코드오류가 났는데 아직 못 찾았어요^^,,,,
- 프로필 수정 모달에서 이름을 바꾸거나 새 프로필 사진을 업로드하는 경우 파일을 받아 저장해주어야합니다. 프로필 업데이트 후에는 페이지를 새로고침하여 다시 정보를 받아옵니다
- 해당 사용자 글만 보이게 하기
- 포스팅 카드들 중에 해당 사용자 글만 보여주게 해보겠습니다.
- 아까 만든 get_posts() 함수에 username을 변수로 받도록 바꿔볼까요?
function get_posts(username) { if (username==undefined) { username="" } $("#post-box").empty() $.ajax({ type: "GET", url: `/get_posts?username_give=${username}`, data: {}, success: function (response) { if (response["result"] == "success") { ... } } }) }
- 이제 서버 쪽에서 username을 받아 해당 사용자의 글만 가져오도록 바꿔봅시다.
@app.route("/get_posts", methods=['GET']) def get_posts(): token_receive = request.cookies.get('mytoken') try: payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256']) username_receive = request.args.get("username_give") if username_receive=="": posts = list(db.posts.find({}).sort("date", -1).limit(20)) else: posts = list(db.posts.find({"username":username_receive}).sort("date", -1).limit(20)) for post in posts: post["_id"] = str(post["_id"]) post["count_heart"] = db.likes.count_documents({"post_id": post["_id"], "type": "heart"}) post["heart_by_me"] = bool(db.likes.find_one({"post_id": post["_id"], "type": "heart", "username": my_username})) return jsonify({"result": "success", "msg": "포스팅을 가져왔습니다.", "posts": posts}) except (jwt.ExpiredSignatureError, jwt.exceptions.DecodeError): return redirect(url_for("home"))
위 html파일에 get post 불러와주는 script를 각 추가해주고 웹페이지로 가보면?
- og태그, favicon 넣기
- 마지막 웹서비스도 Open Graph 태그와 favicon을 넣어서 완성해줍시다. ogimg는 로그인화면 배너를 스크린샷을 찍고 favicon은 아래 파일을 다운 받아 static 폴더에 넣어줄게요.
- HTML 파일들의 head에 링크를 첨부합니다. 내용은 각 페이지에 맞게 바꿔주어야겠죠?
```html <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon"> <meta property="og:title" content="스위터 - 세상을 달달하게"/> <meta property="og:description" content="mini project for Web Plus"/> <meta property="og:image" content="{{ url_for('static', filename='ogimg.png') }}"/> ```
728x90
반응형