Django

[Django] #10 다중앱과 URL

kinggoddino 2024. 8. 15.

나는 각 유저를 위한 페이지 url 을 구성하고싶은 상황이다

 

users/spino/  ▷ 스피노 페이지

users/tyranno/   티라노 페이지

하면 되는데

 

만약 유저가 백명이면?!

일일이 만들고 있을 생각하면 벌써 귀찮다

 

그럴때는 바뀌는 부분만 변수로 처리할 수 있다

users/변수/  ▷ 변수 페이지

 

이걸  Variable Routing 이라고 한다

URL 일부를 변수로 지정해서, 해당 부분에 들어온 값을 view로 넘겨줌

→  view에서 변수를 받아서 그 해당 부분에 맞게 처리

→ 하나의 URL에서 여러 페이지 연결 가능

 

▶ 직접 해보자 코드

view에서 username 매개변수 받아준 다음에 context 에 저장해서 넘겨주기

def profile(request, username):
    context = {
        "username": username,
    }
    return render(request, 'profile.html', context)

입력된 URL이 users/ 로 땡이면 views.users 로 넘겨서 처리하고,

users/ 뒤에 변수가 더 붙는다면 그걸 username 이라는 변수에 담아서 views.profile 로 넘기라는 뜻

users 템플릿은 기본페이지

profile 템플릿에서는 username 변수 받아서 보여주기

 

▶ 서버 실행 결과

기본 페이지

주소창에서 users 뒷부분을 수정했을때. 스피노 유저

이건 티라노 유저


▶  변수타입

아 근데 urls.py 에서 변수를 쓸때

    path('users/<username>/', views.profile),

이렇게 지정을 안해줄 경우 기본적으로 str 이 적용됨.

/ 빼고 나머지 문자열을 변수로 처리하겠다는 의미.

    path('users/<str:username>/', views.profile),

그래도 헷갈리지 않게 str 명시해주기

    path('users/<int:username>/', views.profile), # 숫자일때 

숫자일경우. 즉 0또는 양의 정수를 변수로 처리하겠다는 의미

 

slug, uuid, path 등이 있는데 지금은 알기 귀찮다

str, int 만 써도 대부분 가능할거라고 하셧다.


▶  하이퍼링크

<a> 앵커 태그와 href 속성으로 링크할 URL을 지정할 수 있다

# profile.html

{% extends 'base.html' %}

{% block content %}
    <h1> {{ username }}의 프로필 페이지 </h1>
    <h3> username : {{ username }} </h3>
    <a href="/index/">Index 페이지로 돌아가기</a>
{% endblock content %}

하이퍼링크 누르면

인덱스 페이지로 넘어가진다 성공


multiple apps

하나의 프로젝트는 여러개의 앱으로 구성됨

근데 현재 하나의 url 안에 기능이 다들어잇다.

 

users 앱과 articles 앱을 분리해서 만들어보자.

 

 

[0] users 앱 생성 & 등록

python manage.py startapp users  # 앱생성. 외워라

아 컴마 안찍었넹 다음부턴 까먹지말자

 

installed_apps 는 리스트 형태다

파이썬에서 리스트는 순서가 존재하는 자료형임

그래서 위에서부터 읽어들이기 때문에

장고가 만든 앱보다 사용자가 만든 앱을 위로 올려주는 게 더 권장되긴함

 

 

[1] 각 앱에 urls.py 만들기

urls.py 는 앱을 생성해도 장고에서 만들어주지 않는다. 왜지

따라서 내가 직접 articles 와 users 앱에 각각 urls.py 를 만들어준다.

 

urls.py 파일의 기본구조는 urlpatterns 임

 

 

[2]  url 분리하기

my_first_pjt 에 우르르 몰려있는 url 경로들을 각 앱의 기능에 맞게 분리해준다.

users 앱의 urls 와 articles 앱의 urls 에게 각각 해당 경로를 옮겨주기

이렇게 분리를 해주고 나면 노랑밑줄이 남발하는것을 볼 수 있는데

장고가 말을 못알아먹고 있기 때문이다

path가 뭔데

views가 어디있는데

라고 하는중

 

path와 views 를 정의해준다.

path 정의는 장고한테서 가져오고 views 는 . 에서 가져와줌

. 이 뭔의미냐면 이 urls 파일이 있는 위치에서 views 를 찾으라는 뜻이다

 

지금 users/urls.py 를 보면 views.users 랑 views.profile 이 흰색인데

해당 urls 파일이 있는 위치(==users 폴더) 에서 views.users 랑 views.profile 를 찾을 수가 없기 때문.

 

왜냐면 내가 지금까지 articles 폴더에서 작업했으니까 articles 폴더의 views 에 다 들어있음

따라서 users/urls.py 에서는 from articles import views 라고 불러와주는 게 맞다.

근데 그렇게 하면 앱을 분리하는 의미가 없겠지?

그래서 articles 폴더의 views 에 있는 기능들 중에

users 에 해당하는 기능들을 users/views로 옮겨와 준다

 

 

[3] views 분리하기

views.py 는 앱을 생성할 때 장고가 자동으로 만들어준다. 물론 비어있다

현재상태. articles 폴더의 views 에  기능이 전부 들어있음.

users 에 해당하는 기능(함수)은 users 폴더의 views 로 옮겨주자

users 함수랑 profile 함수만 옮겨줬음

 

근데 사실 장고로 request 가 들어오면 project 의 urls 로 req가 들어온다.

그래서 users/urls랑 articles/urls 를 project/urls 로 포함시켜 주는 작업이 필요하다

 

 

[4] urls 포함시키기

처음 request 가 들어올 프로젝트 폴더의 urls.py 파일

include 함수는 장고.urls 안에 있다. 불러와줌

그리고 path 경로 설정 해줌

 

ex) users/dino/ 가 들어왔을때

line22~ line24 : 일치하는 게 없으니 지나감

line25 : users/ 일치하니까 그 뒷부분은 users.urls 로 넘어감

 

그럼 dino/ 만 넘어가겠지?

어디로 넘어가냐면 앞부분이 users였으니 users 앱의 urls 로 넘어간다

넘어온 dino/는 users/urls.py 에서 경로를 비교하게 되는데,

현재 path에 users/dino/를 원하고있기 때문에 dino/랑 일치하는게 없다. 에러

 

수정코드

urlpatterns =[
    path('', views.users),
    path('<str:username>/', views.profile),
    # 앞부분(users/)는 프로젝트 폴더에서 처리하니까 없애줌
]

따라서 프로젝트폴더에서 미리 처리된 앞부분(users/)은 없애버리기

 

근데 만약에 users/profile/dino 가 들어온다면?!

users/dino/payment 가 들어온다면?

일치하는 패턴이 없으니 또 Page not found (404) 화면을 보게 될 것임.

 

따라서

urlpatterns =[
    path('', views.users),
    path('profile/<str:username>/', views.profile),
]

앞으로는 이런식으로 해당 패턴에 맞게 경로를 구체화 시켜줘야된다

 

 

여기까지 views 와 urls를 모두 분리해줬음

이런식으로 앱기능 분리하기 끝!!!

 

 

아직 끝 아니엇음..

 

완벽한 분리를 위해 templates(html파일들)도 분리해보자

 

 

[5] templates 분리하기

 

users 앱에 templates 폴더를 생성해주고

articles 앱의 templates 에서 user 기능에 해당하는 html 파일을 드래그앤드롭으로 옮겨와준다

사진은 없다 귀찬기 때문

profile.html 이랑 users.html 파일을 옮겨와 줬다

 

 

[6] 진짜 끝! 실행해보기

python manage.py runserver   # 서버실행. 좀외워라

 

주소창에 직접 입력 바꿔보면서 확인완료 좋아 잘 되는군

 

근데 여기서 데이터를 전송해보면

또 page not found...

 

이유는

data-throw 페이지에서 data-catch/ 로 데이터를 전송하고 있는데

앱의 기능을 분리하면서 articles/data-catch/ 로 보내는걸로 바꼇기 때문

따라서 경로를 바꿔준다

 

수정코드

    <form action="/articles/data-catch/" method="GET">
    # 경로에 articles/ 추가

 

이제 catch 페이지 정상 동작함!

 

근데 여기서 저 하이퍼링크를 누르면

후...

그렇다 data-throw 도 articles 를 추가해줘야된다

 

수정코드

    <a href="/articles/data-throw/">데이터 또 입력하러 가기!!!</a>

 

그럼 하이퍼링크도 정상작동함!

 

 

근데 지금은 예시라서 페이지가 2개지만

만약 실제 프젝을 한다고 가정햇을때는

어떤 url 경로를 바꿀 때 엄청 많은 경로를 하나씩 찾아가면서 다 바꿔야됨

그와중에 오타라도 잇으면 오류가 나게됨 

나는야 상습오타범으로서 하드코딩은 피하고싶다

 

그래서 장고가 제공하는 게 있음!

바로 각각의 url 들에게 '별명'을 붙여주는거다

먼소리야

 

 

[7] 경로에 별명 붙이기

이렇게 name 을 붙여주면

나중에 view에서사용하건 template 에서 사용하든

어디의 어떤 경로인지 대신에 name 만 가져다가 쓸 수 있게 된다.

 

이제 이 name 을 templates 에서 사용하면된다

 

사용하는 방법 !

url 템플릿 태그를 사용한다.

{% url 'url_name' %}  # 템플릿 태그

 

이렇게 햇을때 좋은점?

만약 나중에 내가 경로 이름을 수정하고 싶을때

예를들면 urls.py 파일에서 경로를 data-throw → throw 로 변경해도 name 은 data-throw 로 유지되니깐

템플릿에서 data-throw 가 사용된 부분을 수정하지 않아도 된다.

일일이 찾아서 throw로 바꿔주고 싶다면 사용안해도 된다

 

 

[7-2] data-throw 에서 홈(index)으로 바로 가는 링크 만들기

 

위의 data-throw.html 파일에다가 링크추가

    # articles/templates/data_throw.html
    
    <a href="/index/">INDEX로 가기!!!!!</a> # 앵커태그 추가

이렇게 /index/ 를 명시해주면 되는데

하드코딩 하지 말고 방금 배운 name 을 사용해보면

프로젝트 폴더의 urls.py 파일에서 index 경로에 name 을 지정해주면

    # articles/templates/data_throw.html
    
    <a href="{% url 'index' %}">INDEX로 가기!!!!!</a> # url 템플릿태그로 대체가능

이렇게 url 태그를 사용할 수 있다

하이퍼링크 누르면

헤헤 정상작동 확인

 

 

[7-3] index 페이지에 각각으로 이동하는 링크 만들기

users 앱의 urls 에도 각각 name 지정해주고

index 템플릿에서 링크 걸어주기

<br> 은 줄바꿈 해주는거다. break 약자인듯

야호

 

 

이런식으로 여기저기로 이동하는 링크를 만들 때 name 지정과 url 템플릿 태그를 사용해서

하드코딩하지 않고 특정 경로에 대한 의존성을 제거할 수 있다

 

 

 

 


 

'Django' 카테고리의 다른 글

[Django] 시험 오답노트  (1) 2024.09.02
[Django] #11 장고 Model  (0) 2024.08.16
[Django] #9 HTTP Form  (0) 2024.08.15
[Django] #8 장고 Template System  (0) 2024.08.14
[Django] #7 장고 Template 시작하기  (0) 2024.08.13