티스토리 뷰

 

<Complete List>

1. 데이터베이스 및 UI 설계하기

  • 인스타그램 UI 구성
  • 데이터베이스 테이블 설계 및 구현

2. 앱 만들기

  • instagram, accounts 앱 만들기
  • views.py 분리하기

3. 회원가입 페이지

  • 비밀번호 암호화 함수 구현 - 해시 함수

4. 로그인 페이지

  • 세션에 사용자 ID 저장하기

5. 로그아웃 뷰

6. 메인 페이지

7. 포스트 리스트 페이지

8. 포스트 상세 페이지

 

<To Do List>

9. 포스트 업로드 페이지

10. 회원 정보 수정 페이지

 


9. 포스트 업로드 페이지

  • pystagram에서 작업

9.1 url

urlpatterns = [
    re_path(r'^$', MainView, name='pn_main'),
    re_path(r'^(?P<user_id>[a-zA-Z0-9-_.]*)/$', PostListView, name='pn_post_list'),
    re_path(r'^p/(?P<post_id>[0-9]+)/$', PostDetailView, name='pn_post_detail'),
    re_path(r'^p/upload/$', PostUploadView, name='pn_post_upload')
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
  • pn_post_upload : 별도의 구분없이 /upload/ 이런 식으로 url이 들어온다면 위에서부터 차례로 매칭하는 django

    ​ 특성상 pn_post_list 로 인식이 되기 때문에 p를 추가하여 구분

 

  • urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

    : media 파일은 static 파일과 다르게 개발 서버에서 serving을 지원해주지 않기 때문에 static 함수를 이용해

    url pattern을 만들어 urls.py 에 직접 serving rule을 추가해야 함

 

9.2 PostUploadView

  • splitviews 디렉토리에 PostUploadView.py 생성

  • splitviews 의 __init.py__에 PostUploadView 를 import

 

  • 로직(전체코드 - github)
  1. request.method == GET
    : post_create.html rendering
  1. request.method == POST
    : post_create.html 의 form 데이터를 받아와 post 테이블에 데이터 INSERT
    2.1 post_create.html 의 form 데이터를 받아온다.
    2.2 post_img_url = fileUpload(user, postImg)

    • 사용자가 올린 사진 파일을 media 폴더에 저장한 후 저장된 경로를 return

      2.3 post 테이블에 데이터 INSERT

 

사용자가 올린 사진 파일을 media 폴더에 저장하고 저장된 경로를 return 받기 위한 함수이다.

# common.py
def fileUpload(user, postImg):
    # 파일 이름과 확장자를 분리
    fileName, extension = os.path.splitext(postImg.name)

    newFileName = str(uuid.uuid4()) + extension
    # ex) image/1111/51dc6889-448c-4dff-a685-3372acd78c9d.jpg
    filePath = os.path.join('image', user.username, newFileName)

    # 사진 파일을 지정된 경로에 저장
    default_storage.save(filePath, postImg)
    # 저장된 파일의 경로 가져오기
    post_img_url = default_storage.url(filePath)

    return post_img_url
  • uuid.uuid4() 를 사용하는 이유

    : 한글 이름의 파일이 저장되는 경우, 화면 상으로는 제대로 보일 지 몰라도 받아오는 경로에는 인코딩 문제로 이름이

    이상하게 변한다. 또한 똑같은 파일이 저장되는 경우, 파일 이름 뒤에 랜덤 문자열을 집어넣어 저장한다. 따라서,

    처음부터 uuid 를 사용하여 파일마다 고유 값을 부여하고, 이를 이름으로 사용하여 저장한다.

 

  • str(uuid.uuid4()) : uuid는 길이가 32byte인 하나의 uuid 객체이기 때문에 이를 파일 이름으로 사용하려면

    ​ 문자열로 변환해야 한다.

 

9.3 post_create.html

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
    $(document).ready(function(){
        // 사용자가 파일 선택 시, 파일 이름이 화면에 보여지도록
        $('#postImg').change(function(e){
            var fileName = e.target.files[0].name;
            $('.custom-file-label').html(fileName);
        });

        // 사용자가 파일을 선택하지 않고 업로드 하는 경우 막기
        $('.btn').click(function(e){
            if ($('#post_img').val() == '') {
                alert("사진을 선택해주세요.");
                return false;
            }
        });
    });
</script>

 

 

10. 회원 정보 수정 페이지

  • accounts 에서 작업

10.1 url

urlpatterns = [
    re_path(r'^register/$', RegisterAccountsView, name='pn_reg_accounts'),
    re_path(r'^login/$', LoginView, name='pn_login'),
    re_path(r'^logout/$', LogoutView, name='pn_logout'),
    re_path(r'^modify/$', AccountsModifyView, name='pn_accounts_modify'),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

 

10.2 AccountsModifyView

  • splitviews 디렉토리에 AccountsModifyView.py 생성

  • splitviews 의 __init.py__에 AccountsModifyView 를 import

 

  • 로직(전체코드 - github)
  1. request.method == GET
    : accounts_modify.html rendering
  2. request.method == POST
    : accounts_modify.html 의 form 데이터를 받아와 Django 인증 시스템을 사용하여 사용자 정보 UPDATE
    2.1 accounts_modify.html 의 form 데이터를 받아온다.
    2.2 사용자가 프로필 이미지 파일을 업로드 한 경우,

    ​     2.2.1 기존 프로필 이미지 파일을 삭제

    ​     2.2.2 새로운 프로필 이미지 파일을 media 폴더에 저장한 후 저장된 경로를 return
    2.3 사용자가 프로필 이미지 파일을 업로드 하지 않은 경우,

         : 기존 정보 그대로 UPDATE

 

# common.py
# 사용자가 올린 사진 파일을 media 폴더에 저장하고 저장된 경로를 return
def profileImageFileUpload(user, profileImg):
    fileName, extension = os.path.splitext(profileImg.name)

    newFileName = str(uuid.uuid4()) + extension
    filePath = os.path.join('image', user.username, 'profile', newFileName)

    default_storage.save(filePath, profileImg)
    profile_img_url = default_storage.url(filePath)

    return profile_img_url


# 기존 프로필 이미지 파일을 삭제
def profileImageFileDelete(profile_img_src):
    tmp_path = re.findall(r'image.*', profile_img_src)
    delete_path = tmp_path[0]

    default_storage.delete(delete_path)

파일을 삭제할 때는 MEDIA_ROOT 를 제외한 나머지 path 를 입력했을 때만 작동하기 때문에 아래와 처리했다.

  • tmp_path = re.findall(r'image.*', profile_img_src)

    : 지정된 path에서 image로 시작하는 정규식 패턴들을 모두 찾아 리스트로 반환

 

10.3 accounts_modify.html

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
    //업로드 프로필 이미지 미리보여주기
    function readURL(input) {
        if (input.files && input.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#profile_img').attr('src', e.target.result);
            }
            reader.readAsDataURL(input.files[0]);
        }
    }

    // 사용자가 파일 선택 시, 파일 이름이 화면에 보여지도록
    $(document).ready(function(){
        $('#postImg').change(function(e){
            var fileName = e.target.files[0].name;
            $('.custom-file-label').html(fileName);
        });
</script>
댓글