├── .deployment
├── .gitignore
├── Azure WebApp Slides
├── 001.jpeg
├── 002.jpeg
├── 003.jpeg
├── 004.jpeg
├── 005.jpeg
├── 006.jpeg
├── 007.jpeg
├── 008.jpeg
├── 009.jpeg
├── 010.jpeg
├── 011.jpeg
├── 012.jpeg
├── 013.jpeg
├── 014.jpeg
├── 015.jpeg
├── 016.jpeg
├── 017.jpeg
├── 018.jpeg
├── 019.jpeg
├── 020.jpeg
├── 021.jpeg
├── 022.jpeg
├── 023.jpeg
├── 024.jpeg
├── 025.jpeg
├── 026.jpeg
├── 027.jpeg
└── 028.jpeg
├── README.md
├── azure_webapp_setup.py
├── deploy.py
├── deploy_settings.py
├── download.py
├── images
├── 1 - deployment_source.png
├── 2 - deployment_source - choose source.png
├── 3 - deployment_source - choose source - github.png
├── 4 - deployment_source - choose source - github - choose project.png
├── 5 - deployment_source - choose source - github - choose project after.png
└── 6 - deployment_source - completed.png
├── ptvs_virtualenv_proxy.py
├── web.2.7.config
└── web.3.4.config
/.deployment:
--------------------------------------------------------------------------------
1 | [config]
2 | command = python deploy.py
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | db.sqlite3
3 |
--------------------------------------------------------------------------------
/Azure WebApp Slides/001.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/001.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/002.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/002.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/003.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/003.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/004.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/004.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/005.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/005.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/006.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/006.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/007.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/007.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/008.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/008.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/009.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/009.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/010.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/010.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/011.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/011.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/012.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/012.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/013.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/013.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/014.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/014.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/015.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/015.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/016.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/016.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/017.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/017.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/018.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/018.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/019.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/019.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/020.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/020.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/021.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/021.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/022.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/022.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/023.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/023.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/024.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/024.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/025.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/025.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/026.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/026.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/027.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/027.jpeg
--------------------------------------------------------------------------------
/Azure WebApp Slides/028.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/Azure WebApp Slides/028.jpeg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # azure-webapp-django-setup
3 |
4 | [Azure 공식문서 - Azure에서 Django를 활용하여 웹앱 만들기](https://azure.microsoft.com/documentation/articles/web-sites-python-create-deploy-django-app/) 문서에도 배포방법을 설명하고 있습니다. 하지만 불필요한 설명이 많고 배포스크립트가 ***bat 스크립트***로 되어있어서 (암호같아요 ;;; ), 불필요한 파일들을 정리하고 코드 가독성이 좋도록 ***Azure WebApp Django Setup*** 프로젝트를 만들었습니다.
5 |
6 |
7 | ## 튜토리얼 실습 영상
8 |
9 | 본 스크립트를 통해, Azure WebApp 배포를 실습하는 영상을 찍어봤습니다.
10 |
11 | * [장고걸스 튜토리얼, Azure WebApp 배포 동영상 (한글버전)](https://www.facebook.com/askdjango/videos/634463410050050/)
12 |
13 |
14 | ## Azure WebApp
15 |
16 | [Azure](https://azure.microsoft.com/)는 Microsoft에서 서비스하고 있는 클라우드 서비스입니다. 클라우드 서비스는 크게 IaaS, PaaS, SaaS로 구분됩니다. Azure PaaS서비스로서 [Azure WebApp](https://azure.microsoft.com/services/app-service/web/)가 서비스되고 있습니다.
17 |
18 | Azure WebApp의 주요 특징
19 |
20 | * 인프라 운영부담이 없습니다. (PaaS의 일반적인 특징)
21 | * Github 등을 활용한 지속적인 배포지원 : Github 에 올리는 것만으로 배포를 수행할 수 있습니다.
22 | * 지원언어 : .NET, Java, PHP, Node.js 및 ***Python***
23 | * 배포된 프로그램은 윈도우, IIS 웹서버 상에서 구동됩니다.
24 |
25 |
26 | ## Azure WebApp Django Setup
27 |
28 | Azure WebApp 상에서 Django 애플리케이션을 돌리기 위해서는, 다음 파일들이 필요합니다.
29 |
30 | * .deployment : 배포 스크립트 지정
31 | * deploy.py : 실질적인 배포작업을 수행하는 파이썬 스크립트
32 | * deploy\_settings.py : 배포 환경설정
33 | * web.3.4.config : 파이썬 3.4용 웹서비스 설정
34 | * web.2.7.config : 파이썬 2.7용 웹서비스 설정
35 | * ptvs\_virtualenv\_proxy.py : Python Tools for Visual Studio 용 가상환경 프록시
36 |
37 | 명령 한 줄 만으로 Azure Webapp Django 배포에 필요한 위 파일들이 모두 생성이 됩니다.
38 |
39 | 파이썬 `3.4` 와 `2.7` 을 지원합니다. 디폴트로 `3.4` 로 설정되어있습니다. `2.7` 로 설정하실려면, `deploy_settings.py` 에서 `PYTHON_VERSION` 을 `2.7`로 수정하시면 됩니다.
40 |
41 |
42 | ## 소스코드 선행작업
43 |
44 | * 스크립트 실행을 위해 `requests` 라이브러리가 필요합니다. 아래 명령으로 설치해주세요.
45 | ```
46 | 쉘> pip install requests
47 | ```
48 | * 디렉토리 ROOT는 직접적으로 Django 프로젝트로 시작해야 합니다.
49 | * 지원되는 구조
50 | * manage.py
51 | * myproject 디렉토리
52 | * 하위 디렉토리에 django 프로젝트를 두고자할 경우, `web.3.4.config` 수정이 필요합니다. (파이썬 2.7을 쓰시고자 하실 경우에는 `web.2.7.config` 파일을 수정해주세요.)
53 |
54 | * 프로젝트 ROOT 에 `requirements.txt` 파일이 꼭 필요하며, 현 Django 프로젝트 구동에 필요한 파이썬 팩키지들을 모두 명시해주세요. Azure WebApp 배포 시에 본 `requirements.txt` 에 명시한 파이썬 팩키지가 자동설치됩니다. 아래는 예시입니다.
55 | ```
56 | django
57 | pillow
58 | ```
59 | * `프로젝트/settings.py` 에 STATIC/MEDIA 설정을 꼭 넣어주세요. `web.3.4.config` (혹은 `web.2.7.config`) 에서 아래 설정값으로 STATIC/MEDIA 파일 서빙을 하도록 설정되어있습니다.
60 | ```python
61 | STATIC_URL = '/static/'
62 | STATIC_ROOT = os.path.join(BASE_DIR, 'static')
63 | MEDIA_URL = '/media/'
64 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
65 | ```
66 |
67 |
68 | ### 주의사항
69 |
70 | * `env` 이름으로 virtualenv를 만들어서 업로드하지 마세요. virtualenv는 Azure WebApp상에서 배포과정 중에 `env` 이름으로 자동으로 생성이 됩니다.
71 |
72 |
73 | ## Azure WebApp 설정파일 다운로드
74 |
75 | 다음 명령을 `manage.py` 가 있는 경로에서 명령프롬프트 혹은 터미널을 통해 실행시켜주세요.
76 |
77 | ```
78 | 쉘> python -c "import requests; exec(requests.get('https://festi.kr/azure/d.py').content)"
79 | ```
80 |
81 |
82 | `web.3.4.config` (혹은 `web.2.7.config`) 파일 내 `DJANGO_SETTINGS_MODULE` 값을 Azure WebApp 에서 쓸 settings 로 설정해주세요. 다음은 설정 예입니다.
83 |
84 | ```xml
85 |
86 | ```
87 |
88 |
89 | ## Azure WebApp 에 배포하기
90 |
91 | 
92 |
93 | 
94 |
95 | 
96 |
97 | 
98 |
99 | 
100 |
101 | 
102 |
103 | 
104 |
105 | 
106 |
107 | 
108 |
109 | 
110 |
111 | 
112 |
113 | 
114 |
115 | 
116 |
117 | 
118 |
119 | 
120 |
121 | 
122 |
123 | 
124 |
125 | 
126 |
127 | 
128 |
129 | 
130 |
131 | 
132 |
133 | 
134 |
135 | 
136 |
137 | 
138 |
139 | 
140 |
141 |
142 | ## 참고
143 |
144 | Azure WebApp 에 배포한 Django 프로젝트 샘플은 [이곳](http://msdjangoisbest.azurewebsites.net/)에서 확인하실 수 있으며, 소스코드는 [github 저장소](https://github.com/askdjango/djangoisbest)에서 확인하실 수 있습니다.
145 |
146 |
147 | ## 관련 문의
148 |
149 | * [ask@festi.kr](mailto:ask@festi.kr)
150 | * [AskDjango 페이스북 페이지](http://facebook.com/askdjango)
151 | * [AskDjango 페이스북 그룹](http://facebook.com/groups/askdjango)
152 | * [AskDjango 공식 사이트](http://festi.kr)
153 |
154 |
--------------------------------------------------------------------------------
/azure_webapp_setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import print_function
3 | from __future__ import unicode_literals
4 | import os
5 | import sys
6 | try:
7 | import requests
8 | except ImportError:
9 | print('Error) Missing python package : requests', file=sys.stderr)
10 | sys.exit(1)
11 |
12 | try:
13 | from django.conf import settings
14 | except ImportError:
15 | print('Error) Missing python pakcage : django', file=sys.stderr)
16 | sys.exit(1)
17 |
18 | settings.configure(
19 | DEBUG=True,
20 | TEMPLATES=[{
21 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
22 | }])
23 |
24 | import django
25 | django.setup()
26 |
27 | from django.template import engines
28 |
29 |
30 | def main(settings_module):
31 | if not os.path.exists('requirements.txt'):
32 | print('Error) Missing file : requirements.txt', file=sys.stderr)
33 | sys.exit(1)
34 |
35 | base_url = 'https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/master/'
36 | filenames = ['ptvs_virtualenv_proxy.py', '.deployment', 'deploy.py', 'deploy_settings.py', 'web.3.4.config']
37 |
38 | for filename in filenames:
39 | print(filename + ' ...', end=' ')
40 | url = os.path.join(base_url, filename)
41 | content = requests.get(url).text
42 | if os.path.exists(filename):
43 | print('overwrite.')
44 | else:
45 | print('created.')
46 |
47 | template = engines['django'].from_string(content)
48 | content = template.render({'settings_module': settings_module})
49 | open(filename, 'wb').write(content.encode('utf8'))
50 |
51 |
52 | if __name__ == '__main__':
53 | try:
54 | settings_module = sys.argv[1]
55 | main(settings_module)
56 | except IndexError:
57 | print('Error) Missing settings_module', file=sys.stderr)
58 | sys.exit(1)
59 |
60 | print()
61 | print('Powered by AskDjango : http://festi.kr')
62 |
63 |
--------------------------------------------------------------------------------
/deploy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import print_function
3 | from __future__ import unicode_literals
4 | import datetime
5 | import os
6 | import shutil
7 | import sys
8 | import xml.etree.ElementTree as ET
9 | import deploy_settings
10 |
11 |
12 | def log(s, is_error=False):
13 | file = sys.stderr if is_error else sys.stdout
14 | prefix = datetime.datetime.now().strftime('[%Y-%m-%d %H:%M:%S] ')
15 | print(prefix + s, file=file)
16 |
17 |
18 | class AskDjango(object):
19 | def run(self):
20 | self.check_nodejs()
21 | self.check_variables()
22 | self.do_deployment()
23 | self.copy_web_config()
24 | self.do_extra_for_django()
25 | self.post_python_deployment()
26 |
27 | def check_nodejs(self):
28 | if int(os.system('where node')) != 0:
29 | self.goto_error('Missing node.js executable, plaease install node.js, if already installed make sure it can be reached from current environment.')
30 |
31 | def check_variables(self):
32 | log('check variables ...')
33 |
34 | self.deploy_src_path = self.get_deploy_src_path()
35 | self.deploy_path = self.get_deploy_path()
36 |
37 | self.python_version = deploy_settings.PYTHON_VERSION
38 | self.python_runtime = 'python-%s' % self.python_version
39 |
40 | if self.python_version.startswith('2.'):
41 | self.python_env_module = 'virtualenv'
42 | self.python_path = os.path.join(os.environ['SYSTEMDRIVE'] + os.path.sep, 'python27', 'python.exe')
43 | else:
44 | self.python_env_module = 'venv'
45 | self.python_path = os.path.join(os.environ['SYSTEMDRIVE'] + os.path.sep, 'python34', 'python.exe')
46 |
47 | self.is_skip_python_deployment = deploy_settings.IS_SKIP_PYTHON_DEPLOYMENT
48 | self.is_skip_django_extra = deploy_settings.IS_SKIP_DJANGO_EXTRA
49 |
50 | self.virtualenv_path = self.get_deploy_path('env')
51 | self.python_runtime_mark_path = os.path.join(self.virtualenv_path, self._('azure.env.{python_runtime}.txt'))
52 |
53 | self.requirements_path = self.get_deploy_path('requirements.txt')
54 | self.requirements_name = os.path.basename(self.requirements_path)
55 |
56 | self.config_src_path = self.get_deploy_src_path(self._('web.{python_version}.config'))
57 | self.config_dst_path = self.get_deploy_path('web.config')
58 |
59 | self.next_manifest_path = os.environ.get('NEXT_MANIFEST_PATH', None)
60 | self.prev_manifest_path = os.environ.get('PREVIOUS_MANIFEST_PATH', None)
61 | if self.next_manifest_path is None:
62 | self.next_manifest_path = self.current('..', 'artifacts', 'manifest')
63 | if self.prev_manifest_path is None:
64 | self.prev_manifest_path = self.current('..', 'artifacts', 'manifest')
65 |
66 | # https://github.com/projectkudu/kudu/wiki/Post-Deployment-Action-Hooks
67 | self.post_deployment_action = os.environ.get('POST_DEPLOYMENT_ACTION', None)
68 |
69 | self.is_inplace_deployment = (os.environ.get('IN_PLACE_DEPLOYMENT', None) == '1')
70 |
71 | def do_deployment(self):
72 | log('Handling python deployment.')
73 | if not self.is_inplace_deployment:
74 | kudu_sync_cmd = os.environ.get('KUDU_SYNC_CMD', None)
75 | if kudu_sync_cmd is None:
76 | log('Installing Kudu Sync')
77 | self.run_cmd('npm install kudusync -g --silent')
78 | # Locally just running "kuduSync" would also work
79 | kudu_sync_cmd = os.path.join(os.environ['appdata'], 'npm', 'kuduSync.cmd')
80 |
81 | self.run_cmd(
82 | '{kudu_sync_cmd} --verbose=300 '
83 | '--from="{deploy_src_path}" --to="{deploy_path}" '
84 | '--nextManifest="{next_manifest_path}" --previousManifest="{prev_manifest_path}" '
85 | '--ignore=".git;.hg;.deployment;deploy.cmd;deploy.py"', kudu_sync_cmd=kudu_sync_cmd)
86 |
87 | if not os.path.exists(self.requirements_path):
88 | log('Missing %s' % os.path.basename(self.requirements_path))
89 | self.post_python_deployment()
90 |
91 | elif self.is_skip_python_deployment:
92 | log('skip python deployment.')
93 | self.post_python_deployment()
94 |
95 | else:
96 | log('create virtual environment ...')
97 |
98 | if os.path.exists(self.python_runtime_mark_path):
99 | log('Found compatible virtual environment.')
100 | else:
101 | if os.path.exists(self.virtualenv_path):
102 | log('Deleting incompatible virtual environment.')
103 | shutil.rmtree(self.virtualenv_path)
104 |
105 | log(self._('Creating {python_runtime} virtual environment.'))
106 |
107 | self.run_cmd('{python_path} -m {python_env_module} env')
108 |
109 | open(self.python_runtime_mark_path, 'wb').truncate()
110 |
111 | log('Pip install requirements.')
112 | self.run_cmd('env\scripts\pip install --verbose -r "{requirements_path}"')
113 |
114 | def copy_web_config(self):
115 | log('copy web.config ...')
116 | if os.path.exists(self.config_src_path):
117 | log(self._('Overwriting web.config with web.{python_version}.config'))
118 | shutil.copyfile(self.config_src_path, self.config_dst_path)
119 |
120 | def do_extra_for_django(self):
121 | log('do_extra_for_django ...')
122 | os.chdir(self.deploy_path)
123 | if os.path.exists(self.get_deploy_path('manage.py')):
124 | if os.path.exists(self.get_deploy_path('env', 'lib', 'site-packages', 'django')):
125 | root = ET.parse(self.config_dst_path).getroot()
126 | django_settings_module = root.find(".//*[@key='DJANGO_SETTINGS_MODULE']").get('value')
127 |
128 | if not self.is_skip_django_extra:
129 | log('Collecting Django static files.')
130 | if not os.path.exists(self.get_deploy_path('static')):
131 | os.makedirs(self.get_deploy_path('static'))
132 |
133 | self.run_cmd('env\scripts\python manage.py collectstatic --settings={django_settings_module} --noinput --clear',
134 | django_settings_module=django_settings_module)
135 |
136 | def post_python_deployment(self):
137 | if self.post_deployment_action:
138 | self.run_cmd(self.post_deployment_action)
139 | sys.exit(0)
140 |
141 | def run_cmd(self, cmd, fail_message=None, **kwargs):
142 | os.chdir(self.deploy_path)
143 | cmd = self._(cmd, **kwargs)
144 | log(cmd)
145 | if int(os.system(cmd)) != 0:
146 | if fail_message:
147 | log(fail_message, is_error=True)
148 | self.goto_error()
149 |
150 | def goto_error(self, message=None):
151 | if message:
152 | log(message, is_error=True)
153 | sys.exit(1)
154 |
155 | def _(self, s, **kwargs):
156 | kwargs.update(self.__dict__)
157 | return s.format(**kwargs)
158 |
159 | def current(self, *args):
160 | current_dir_path = os.path.abspath(os.path.dirname(__file__))
161 | return os.path.join(current_dir_path, *args)
162 |
163 | def get_deploy_src_path(self, *args):
164 | deployment_source = os.environ.get('DEPLOYMENT_SOURCE', self.current())
165 | return os.path.join(deployment_source, *args)
166 |
167 | def get_deploy_path(self, *args):
168 | deployment_target = os.environ.get('DEPLOYMENT_TARGET', self.current('..', 'artifacts', 'wwwroot'))
169 | return os.path.join(deployment_target, *args)
170 |
171 |
172 | if __name__ == '__main__':
173 | AskDjango().run()
174 |
175 |
--------------------------------------------------------------------------------
/deploy_settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import os
3 |
4 | PYTHON_VERSION = '3.4'
5 |
6 | assert(PYTHON_VERSION in ('3.4', '2.7'))
7 |
8 |
9 | # 가상환경을 env 디렉토리에 이미 생성하셨다면, True로 설정해주세요.
10 | IS_SKIP_PYTHON_DEPLOYMENT = False
11 |
12 | # Azure WebApp 상에서 collectstatic 명령을 수행하지 않으실려면, True로 설정해주세요.
13 | IS_SKIP_DJANGO_EXTRA = False
14 |
15 |
--------------------------------------------------------------------------------
/download.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 | import requests
4 |
5 |
6 | def main():
7 | base = 'https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/master/'
8 | names = ['.deployment', 'deploy.py', 'deploy_settings.py', 'web.2.7.config', 'web.3.4.config', 'ptvs_virtualenv_proxy.py']
9 |
10 | for name in names:
11 | url = base + name
12 | print('downloading {} ...'.format(name))
13 | open(name, 'wb').write(requests.get(url).content)
14 |
15 |
16 | if __name__ == '__main__':
17 | main()
18 |
19 |
--------------------------------------------------------------------------------
/images/1 - deployment_source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/1 - deployment_source.png
--------------------------------------------------------------------------------
/images/2 - deployment_source - choose source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/2 - deployment_source - choose source.png
--------------------------------------------------------------------------------
/images/3 - deployment_source - choose source - github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/3 - deployment_source - choose source - github.png
--------------------------------------------------------------------------------
/images/4 - deployment_source - choose source - github - choose project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/4 - deployment_source - choose source - github - choose project.png
--------------------------------------------------------------------------------
/images/5 - deployment_source - choose source - github - choose project after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/5 - deployment_source - choose source - github - choose project after.png
--------------------------------------------------------------------------------
/images/6 - deployment_source - completed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/askdjango/azure-webapp-django-setup/ccfedb591f7277cdb199172e3a35f14b4f69ae7b/images/6 - deployment_source - completed.png
--------------------------------------------------------------------------------
/ptvs_virtualenv_proxy.py:
--------------------------------------------------------------------------------
1 | # ############################################################################
2 | #
3 | # Copyright (c) Microsoft Corporation.
4 | #
5 | # This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 | # copy of the license can be found in the License.html file at the root of this distribution. If
7 | # you cannot locate the Apache License, Version 2.0, please send an email to
8 | # vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 | # by the terms of the Apache License, Version 2.0.
10 | #
11 | # You must not remove this notice, or any other, from this software.
12 | #
13 | # ###########################################################################
14 |
15 | import datetime
16 | import os
17 | import sys
18 |
19 | if sys.version_info[0] == 3:
20 | def to_str(value):
21 | return value.decode(sys.getfilesystemencoding())
22 |
23 | def execfile(path, global_dict):
24 | """Execute a file"""
25 | with open(path, 'r') as f:
26 | code = f.read()
27 | code = code.replace('\r\n', '\n') + '\n'
28 | exec(code, global_dict)
29 | else:
30 | def to_str(value):
31 | return value.encode(sys.getfilesystemencoding())
32 |
33 | def log(txt):
34 | """Logs fatal errors to a log file if WSGI_LOG env var is defined"""
35 | log_file = os.environ.get('WSGI_LOG')
36 | if log_file:
37 | f = open(log_file, 'a+')
38 | try:
39 | f.write('%s: %s' % (datetime.datetime.now(), txt))
40 | finally:
41 | f.close()
42 |
43 | ptvsd_secret = os.getenv('WSGI_PTVSD_SECRET')
44 | if ptvsd_secret:
45 | log('Enabling ptvsd ...\n')
46 | try:
47 | import ptvsd
48 | try:
49 | ptvsd.enable_attach(ptvsd_secret)
50 | log('ptvsd enabled.\n')
51 | except:
52 | log('ptvsd.enable_attach failed\n')
53 | except ImportError:
54 | log('error importing ptvsd.\n');
55 |
56 | def get_wsgi_handler(handler_name):
57 | if not handler_name:
58 | raise Exception('WSGI_HANDLER env var must be set')
59 |
60 | if not isinstance(handler_name, str):
61 | handler_name = to_str(handler_name)
62 |
63 | module_name, _, callable_name = handler_name.rpartition('.')
64 | should_call = callable_name.endswith('()')
65 | callable_name = callable_name[:-2] if should_call else callable_name
66 | name_list = [(callable_name, should_call)]
67 | handler = None
68 |
69 | while module_name:
70 | try:
71 | handler = __import__(module_name, fromlist=[name_list[0][0]])
72 | for name, should_call in name_list:
73 | handler = getattr(handler, name)
74 | if should_call:
75 | handler = handler()
76 | break
77 | except ImportError:
78 | module_name, _, callable_name = module_name.rpartition('.')
79 | should_call = callable_name.endswith('()')
80 | callable_name = callable_name[:-2] if should_call else callable_name
81 | name_list.insert(0, (callable_name, should_call))
82 | handler = None
83 |
84 | if handler is None:
85 | raise ValueError('"%s" could not be imported' % handler_name)
86 |
87 | return handler
88 |
89 | activate_this = os.getenv('WSGI_ALT_VIRTUALENV_ACTIVATE_THIS')
90 | if not activate_this:
91 | raise Exception('WSGI_ALT_VIRTUALENV_ACTIVATE_THIS is not set')
92 |
93 | def get_virtualenv_handler():
94 | log('Activating virtualenv with %s\n' % activate_this)
95 | execfile(activate_this, dict(__file__=activate_this))
96 |
97 | log('Getting handler %s\n' % os.getenv('WSGI_ALT_VIRTUALENV_HANDLER'))
98 | handler = get_wsgi_handler(os.getenv('WSGI_ALT_VIRTUALENV_HANDLER'))
99 | log('Got handler: %r\n' % handler)
100 | return handler
101 |
102 | def get_venv_handler():
103 | log('Activating venv with executable at %s\n' % activate_this)
104 | import site
105 | sys.executable = activate_this
106 | old_sys_path, sys.path = sys.path, []
107 |
108 | site.main()
109 |
110 | sys.path.insert(0, '')
111 | for item in old_sys_path:
112 | if item not in sys.path:
113 | sys.path.append(item)
114 |
115 | log('Getting handler %s\n' % os.getenv('WSGI_ALT_VIRTUALENV_HANDLER'))
116 | handler = get_wsgi_handler(os.getenv('WSGI_ALT_VIRTUALENV_HANDLER'))
117 | log('Got handler: %r\n' % handler)
118 | return handler
119 |
--------------------------------------------------------------------------------
/web.2.7.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 |
50 |
51 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/web.3.4.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 |
50 |
51 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------