4주차 배운점

2023년 04월 09일 by barryjung

    4주차 배운점 목차

한주간 장고 배운점

 

[이번주 배운점]

 

<vscode에서 장고 시작하기>

- 폴더를 하나 생성한다.

- 가상환경을 만들고 활성화한다. python -m venv venv.

- 장고를 설치한다. pip install django

- 장고 프로젝트를 만든다. django-admin startproject <프로젝트명> .

 

프로젝트를 만들때 프로젝트명 뒤에 한칸 띄고 .(점)을 붙여준다.

점을 안붙인다면 폴더를 하나 만들며 그안에 프로젝트를 만들고,

점을 붙이면 현재 폴더에다가 프로젝트를 만든다.

 

점을 안붙일경우 이렇게 현재폴더 안에 프로젝트 폴더를 하나 더 생성한다.

venv가 있는 현재폴더에 프로젝트가 생성되는게 적합하다.

다만 조금 번거롭다는 것만 빼면 폴더위치는 문제점은 아니다.

 

나는 과제를 다 끝내고서야 이 방법을 알았다.

나처럼 디렉토리를 하나 더 만들었을 경우,

서버를 실행시키기 위해서나 manage.py 명령어를 써야할땐,

해당 디렉토리로 들어가서 명령어를 입력하면 된다.

 

django-admin명령어도 원하는 위치로 이동해서 입력하면 된다.

venv활성화나 깃 명령어는 다시 상위 디렉토리로 오면 된다.

(※ 가상환경은 하위 디렉토리까지 통째로 적용되는 것 같다.

즉, venv폴더와 프로젝트 폴더가 같은 위치가 아니여도 된다.)

 

결론, 디렉토리 위치를 알맞게 만들어야 겠다.

 


<기본 세팅하기>

장고 기본 프로젝트 폴더를 보면.

- setting.py에서는 설치된 앱, 템플릿 폴더위치, DB위치 등을 정할수 있다.

- 새 app을 만들면 꼭 setting에 추가해주자.

- 어플리케이션 리스트는 로컵앱, 서드파티, 장고 기본앱 순으로 보통 적는다.

- asgi, wsgi는 배포할때 작성된다.

- 랭귀지 코드와 타임존을 한국어와 한국으로 바꿀수 있다.

 

LANGUAGE_CODE = 'ko-kr'

TIME_ZONE = 'Asia/Seoul'

ko-kr과 Asia/Seoul이렇게 입력하면 된다.

 

- db는 sqlite가 기본설정이지만 flask처럼 mongodb를 쓸수도 있고 다른 db를 쓸수도 있다.

- 각 app에 위치하는 test.py는 테스트코드를 쓸때 작성된다.


<urls관련>

- 메인 urls.py와 앱 urls.py를 각각 만든다음,

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('accounts.urls')),
    path('', include('erp.urls')),
]

이렇게 include를 사용해서 앱 urls.py도 포함 시킬수 있다.

이때 ' ' 작은따옴표 부분을 비운다면 앱url들을 바로 하위 url들처럼 쓰는 것이고,

작은 따옴표 부분에 'url명/' 이렇게 적는다면 앱url들이 일괄적으로 해당url명의 하위 url이 된다.

 

url을 작성할때, 특정 변수가 url에 위치하게 하는 변수 url의 생성도 가능하다.

flask와는 조금 다른 점이 있다면,

'url명/<int:변수명>' 혹은 'url명/<str:변수명>'으로 변수이름의 타입을 지정해줄 수 있다.

 


<기본 회원가입/로그인 기능>

회원가입, 로그인은 장고에서 제공하는 기본 기능이 있다.

- 기본 모델이 있다. 처음부터 존재하는데 db에 보이지 않는다면 migrate를 한번 실행해준다.

기본 기능을 그대로 쓰겠다면 모델을 만들어 줄 필요 없다.

- 기본 form도 존재한다.

 

기본 기능을 그대로 쓰겠다면,

그냥 forms.py를 이렇게 작성해도 무방하다.

from django.contrib.auth.forms import UserCreationForm, AuthenticationForm

class SignupForm(UserCreationForm):
    pass

class LoginForm(AuthenticationForm):
    pass

 

forms를 쓰기로 했다면 활용해준다.

- view.py에서 render로 html을 넘길때 {'form': form } 이렇게 넘겨준다.

- templates의 해당 html에서는 form 태그 안쪽에 form이 위치하게끔 작성해준다.

<form class="form-area" method="post" action="/login/">
    {% csrf_token %}
    {{form}}
    <div style="float: right">
        <button type="submit" class="btn btn-primary">로그인</button>
        <a href="/signup" class="btn btn-secondary">회원가입 페이지로</a>
    </div>
</form>

이렇게 작성할수 있다.

이렇게 할 경우 action은 안 적어도 된다.

 

(반면, 직접 form태그를 작성할 경우 method와 action이 꼭 있어야 한다.

action에는 url양쪽으로 슬래시를 붙여야 정상적으로 연결된다.)

- csrf_token은 보안기능인데 꼭 적어줘야 한다.

(안적을 경우, 에러로 적으라고 알려준다.) 

 

- forms는 모델의 데이터 타입을 인식해서,

선택지 등도 적어줬다면 참고해서 form을 작성한다.

그럼 웹에서 입력칸에 작성할때 입력했던 요소들을 보여주거나,

올바른 값을 입력하라고 팝업이 뜨는등 여러 기능이 알아서 작동된다.

 


<__str__과 save()의 수정>

내가 만든 개인과제에 erp앱에 model.py에는

Product라는 모델 클래스가 있다.

상품 종류가 담기는 주요한 모델이다.

 

    def __str__(self):
        return self.code
    
    def save(self, *args, **kwargs):
        if not self.id: 
            super().save(self, *args, **kwargs)
            add_inventory = Invetory(code=self)
            add_inventory.save()
        else:
            super().save(self, *args, **kwargs)

클래스 안쪽 작성칸에 밑부분에는 이런 함수가 정의 되어있다.

- __str__로 오브젝트가 호출될때 돌려줄 내용을 정할수 있다.

여기에선 self의 code를 돌려주게 설정했다.

 

- save 함수도 상속받아 조금 변경을 해준다.

Product를 저장할때 새로 저장하는 경우(self.id가 db에 존재하지 않음),

inventoy에 해당 Product를 코드로 가진.

데이터 칸을 하나 생성하게 했다.

 

inventory는 product와, code를 통해 OneToOne형태로 연결된 모델이기 때문에,

이렇게 하나씩 생성해놓는 것이다.

inventory기능은 inventory정보를 갱신해서 리스팅 해주는 건데,

이렇게 미리 데이터 칸을 만들어 놓으면,

inventory기능에서는 빈값에 대한 구분을 할필요가 없다.

 

(이부분을 수정하기 전에는 빈값을 구분해서,

빈값이면 새로 작성하며 리스팅을,

기존 값이면 갱신만 하며 리스팅을 하게끔 view를 만들었었다.)

 

__str__은 form의 보일 모습을 위해 변형시킨 이유가 가장 주요하다.

입고와 출고 모델에서 code는 product를 외래키로 가져온 것이다.

저렇게 작성해주지 않으면 code칸은 product-001, 002같은 인스턴스 이름을 작성하게끔 된다.

__str__을 작성하여 입고와, 출고의 form에서 code의 내용물이 보이게 해준다.

 

 views.py에서도 __str__은 똑같이 동작한다.

    products = Product.objects.all()
    for product in products:
        inbounds = Inbound.objects.filter(code=product)
(중략)
        outbounds = Outbound.objects.filter(code=product)
(중략)
        inventory = Invetory.objects.get(code=product)

이렇게 해서 object들을 불러왔다면.

각 product들은 인스턴스가 아닌 코드명이 된다.

즉, 아래처럼 code=product.code가 아니라 product로 작성할수 있는 것이다.

 

views.py에서는 참조와 가공이 쉬운 반면.

form에서 code내용물을 보이게 하려고 form으로 입력받을 데이터 형태를 변경하여,

code 내용물인 string값이 request에 실려오게 만든다면,

결국 다시 저장할때 인스턴스명이 아닌 스트링이 입력되고 있다는 에러가 나오게 된다.

 

입고 페이지에서는 코드네임이 잘 보이고, 실제 데이터에서는 프로덕트ID로 잘 저장되는 모습이다.