models.py가 점점 커지고 있는데, 그것을 나누는 가장 좋은 방법은 무엇입니까?


91

내 상사의 지시 : "나는 로직을 models.py. 에 넣는 것을 피하고 싶다 . 이제부터는 데이터베이스 액세스를위한 클래스로만 사용하고 모델 클래스를 사용하는 외부 클래스에 모든 로직을 유지하거나 래핑합니다."

나는 이것이 잘못된 길이라고 생각합니다. 파일을 작게 유지하기 위해 모델에서 논리를 제외하는 것은 나쁜 생각이라고 생각합니다. 논리가 모델에서 가장 좋은 경우 파일 크기에 관계없이 실제로 있어야합니다.

그렇다면 include를 사용하는 간단한 방법이 있습니까? PHP-speak에서 저는 models.py다른 곳의 모델 클래스를 include () 가지고 있다고 감독자에게 제안하고 싶습니다 . 개념적으로 이것은 모델이 우리가 원하는 모든 논리를 갖도록 허용하지만 파일 수를 늘려 파일 크기를 줄 이도록합니다 (충돌 등과 같은 수정 제어 문제를 줄임).

그렇다면 models.py 파일에서 모델 클래스를 제거하는 간단한 방법이 있지만 여전히 모든 Django 도구에서 모델이 작동합니까? 아니면 "대형"models.py 파일의 일반적인 문제에 대한 완전히 다르지만 우아한 해결책이 있습니까? 모든 입력을 주시면 감사하겠습니다.


7
수입 명세서를 알고 계십니까?
balpha

7
추신. 불쾌하게 말하는 것이 아니라 당신이 어디에 있는지 알고 싶습니다.
balpha

1
예,하지만 django의 관리 도구가 모델을 가져 오기 위해 import 문을 사용하는 것만으로 작동하는지 몰랐습니다. 장고의 도구가 제대로 작동하지 않는지 확인하기 위해 일반 ole 가져 오기를 사용하는 데 많은 시간을 소비하는 것보다 여기서 묻고 싶습니다. 나는 내가 파이썬과 장고에 더
익숙하다는

답변:


64

Django는 하나의 큰 응용 프로그램 대신 많은 작은 응용 프로그램을 빌드 할 수 있도록 설계되었습니다.

모든 대형 애플리케이션 내부에는 자유를 위해 고군분투하는 많은 작은 애플리케이션이 있습니다.

귀하의 경우 models.pyFeel로 큰, 당신은 너무 많은 일을하고 있습니다. 중지. 편하게 하다. 분해.

더 작고 재사용 가능한 소형 애플리케이션 구성 요소 또는 조각을 찾으십시오. 실제로 재사용 할 필요는 없습니다 . 잠재적으로 재사용 가능하다고 생각하십시오.

업그레이드 경로를 고려하고 언젠가 교체 할 수있는 애플리케이션을 분해하십시오. 당신은 필요가 없습니다 실제로 교체,하지만 당신은 미래에 뭔가 쿨러로 대체 될 수있는 위치를 프로그래밍의 독립 실행 형 "모듈"로 그들을 고려할 수 있습니다.

우리는 약 12 ​​개의 응용 프로그램을 가지고 있으며 각각 model.py은 약 400 줄의 코드를 넘지 않습니다. 그것들은 모두 6 개 미만의 개별 클래스 정의에 꽤 집중되어 있습니다. (이것은 엄격한 한계가 아니라 우리 코드에 대한 관찰입니다.)

우리는 일찍 그리고 자주 분해됩니다.


1
바로 포인트입니다. 사소하지 않은 웹앱은 여러 개의 작은 '앱'이 될 것입니다. 들어있는 contrib 및 기타 인기있는 애플 리케이션의 힌트를 가지고, 사용자 인증 하나의 응용 프로그램이며, 태그 등,보다, 하나의 사용자 프로파일 또 다른 하나
하비에르

4
이것이 "올바른"방법이고 알아두면 도움이되지만 제가 찾던 것은 아닙니다. 제가 어떤 답변을 찾고 있었는지 알 방법이 없다면 사과드립니다. :)
Eddified

@Eddified : 이렇게하지 않으면 더 나빠질뿐입니다. 지금 분할을 시작하십시오.
S.Lott

재미있게도, 바로이 순간에 Jacob Kaplan Moss (OSCON에서)가이를 훌륭하고 강력하게 정당화 한 세부 사항으로 정확하게 설명하는 것을 듣고 있습니다 .-).
Alex Martelli

13
Glenn Maynard의 답변은 이것에 대해 훨씬 낫습니다. 복잡한 웹앱을 여러 앱으로 나누는 것은 확실히 좋은 방법이지만 앱 내에서 model.py 파일을 리팩토링하는 것도 좋습니다. 두 동작은 직교 할 수 있습니다.
Erik

108

모델 클래스가 모델에서 작동하는 메서드를 포함하는 것은 당연합니다. 메소드가있는 Book 모델이 있다면 book.get_noun_count()그것이 속한 곳입니다 get_noun_count(book). 메소드가 실제로 본질적으로 다른 패키지에 속하지 않는 한 " " 를 작성하고 싶지 않습니다 . (예 : " get_amazon_product_id(book)"를 사용하여 Amazon의 API에 액세스하기위한 패키지가있는 경우 )

나는 Django의 문서가 모델을 단일 파일에 넣는 것을 제안했을 때 마음에 들었고 처음부터 적절한 하위 패키지로 분할하는 방법을 알아내는 데 몇 분이 걸렸습니다.

site/models/__init__.py
site/models/book.py

__init__.py 다음과 같이 보입니다.

from .book import Book

그래도 "from site.models import Book"을 쓸 수 있습니다.


다음은 Django 1.7 이전 버전에만 필요합니다. https://code.djangoproject.com/ticket/3591 참조

유일한 트릭은 Django의 버그로 인해 각 모델의 애플리케이션을 명시 적으로 설정해야한다는 것입니다. 애플리케이션 이름이 모델 경로의 마지막에서 세 번째 항목이라고 가정합니다. "site.models.Book"은 올바른 "site"가됩니다. "site.models.book.Book"은 응용 프로그램 이름이 "models"라고 생각하게합니다. 이것은 Django의 부분에서 매우 불쾌한 해킹입니다. 아마도 설치된 응용 프로그램 목록에서 접두사 일치를 검색해야합니다.

class Book(models.Model):
    class Meta: app_label = "site"

이를 일반화하기 위해 기본 클래스 또는 메타 클래스를 사용할 수 있지만 아직 신경 쓰지 않았습니다.


2
+1 나는 이것을 성공적으로 사용했습니다. S. Lott는 여러 앱에서 옳은 것이 좋은 생각이지만 이것이 바로 지금 해결책입니다.
Alexander Ljungberg

35
모델이 밀접하고 본질적으로 관련되어있을 때 여러 앱으로 분할하는 것이 많은 이점을 보지 못합니다.
Glenn Maynard

2
관심이 있습니다. 나는 django wiki 링크 scompt가 게시 한 것을 읽었고 "이것은 현재 메인 브랜치에서 메타 클래스 app_labels없이 작동하는 것으로 확인되었습니다."라는 것을 발견했습니다. 그렇다면 메인 브랜치로 작업하는 경우 Meta : app_label 항목을 삭제할 수 있다는 의미입니까? 이 문제를 해결하기 위해 티켓에 대한 의견 뒤에 있기 때문에 혼란 스럽습니다.
Dan.StackOverflow

2
방금 trunk로 테스트했습니다 (오늘부터 r11286). app_name이 설정되지 않은 경우 모델은 "sqlall appname"에 표시되지 않고 syncdb에서 생성되지 않을 것입니다 (하지만 사용하지 않으므로 테스트 할 수 없습니다). 오류를 유발하지 않기 때문에 매우 혼란스러운 오류 사례입니다. 조용히 나타나지 않습니다.
Glenn Maynard

2
와, 거의 10 년이 지난 지금도이 솔루션이 마음에 듭니다. 코드를 작은 앱으로 분할하는 것보다 훨씬 더 나은 접근 방식이라는 데 동의했습니다. 제 생각에는 추론하기 어려운 코드베이스로 이어질 수 있습니다.
Michael Hays

5

나는 당신이 가질 수있는 많은 가능한 문제들 중 어느 것을 확실히 알 수 없습니다. 답변이있는 몇 가지 가능성은 다음과 같습니다.

  • 동일한 파일에있는 여러 모델

    별도의 파일에 넣으십시오. 종속성이있는 경우 가져 오기를 사용하여 추가 모델을 가져옵니다.

  • models.py의 관련없는 논리 / 유틸리티 함수

    추가 로직을 별도의 파일에 넣으십시오.

  • 데이터베이스에서 일부 모델 인스턴스를 선택하기위한 정적 메소드

    별도의 파일에 새 관리자 를 만듭니다 .

  • 모델과 분명히 관련된 방법

    save, __unicode__ 및 get_absolute_url이 예입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.