Skip to content

Commit 1eea684

Browse files
committed
upgrade django3 and python3.8
1 parent cba48cd commit 1eea684

File tree

13 files changed

+95
-163
lines changed

13 files changed

+95
-163
lines changed

README.en.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ The terminal output is also fine ( though it is easy to get stuck here :sweat_sm
346346

347347
![](https://i.imgur.com/RBW8eQt.png)
348348

349-
Next, open another terminal and go into the api ( Django + uWSGI ) container.
349+
Next, open another terminal and go into the api ( Django + uWSGI ) container.
350350

351351
You can find the steps in the previous [docker-tutorial-指令介紹](https://github.com/twtrubiks/docker-tutorial#指令介紹)
352352

@@ -490,8 +490,9 @@ If you are still learning to read, read more :satisfied:
490490
## Environment
491491

492492
* Mac
493-
* Python 3.6.2
493+
* Python 3.8.2
494494
* windows 10
495+
* Liunx
495496

496497
## Reference
497498

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ django 上可以設定 CORS,透過 django-cors-headers 方法可參考 [文章
656656
## 執行環境
657657

658658
* Mac
659-
* Python 3.6.2
659+
* Python 3.8.2
660660
* windows 10
661661

662662
## Reference

api/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.6.2
1+
FROM python:3.8.2
22
LABEL maintainer twtrubiks
33
ENV PYTHONUNBUFFERED 1
44
RUN mkdir /docker_api
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
ASGI config for django_rest_framework_tutorial project.
3+
It exposes the ASGI callable as a module-level variable named ``application``.
4+
For more information on this file, see
5+
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
6+
"""
7+
8+
import os
9+
10+
from django.core.asgi import get_asgi_application
11+
12+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_rest_framework_tutorial.settings')
13+
14+
application = get_asgi_application()

api/django_rest_framework_tutorial/settings.py

+18-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
"""
22
Django settings for django_rest_framework_tutorial project.
33
4-
Generated by 'django-admin startproject' using Django 1.10.6.
4+
Generated by 'django-admin startproject' using Django 3.2.
55
66
For more information on this file, see
7-
https://docs.djangoproject.com/en/1.10/topics/settings/
7+
https://docs.djangoproject.com/en/3.2/topics/settings/
88
99
For the full list of settings and their values, see
10-
https://docs.djangoproject.com/en/1.10/ref/settings/
10+
https://docs.djangoproject.com/en/3.2/ref/settings/
1111
"""
1212

13-
import os
13+
from pathlib import Path
1414

15-
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16-
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16+
BASE_DIR = Path(__file__).resolve().parent.parent
1717

1818

1919
# Quick-start development settings - unsuitable for production
@@ -62,6 +62,7 @@
6262
# Application definition
6363

6464
INSTALLED_APPS = [
65+
'musics.apps.MusicsConfig',
6566
'django.contrib.admin',
6667
'django.contrib.auth',
6768
'django.contrib.contenttypes',
@@ -70,7 +71,6 @@
7071
'django.contrib.staticfiles',
7172
'corsheaders', # django-cors-headers
7273
'rest_framework',
73-
'musics',
7474
]
7575

7676
MIDDLEWARE = [
@@ -89,8 +89,7 @@
8989
TEMPLATES = [
9090
{
9191
'BACKEND': 'django.template.backends.django.DjangoTemplates',
92-
'DIRS': [os.path.join(BASE_DIR, 'templates')]
93-
,
92+
'DIRS': [],
9493
'APP_DIRS': True,
9594
'OPTIONS': {
9695
'context_processors': [
@@ -107,7 +106,7 @@
107106

108107

109108
# Database
110-
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
109+
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
111110

112111
# DATABASES = {
113112
# 'default': {
@@ -129,7 +128,7 @@
129128

130129

131130
# Password validation
132-
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
131+
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
133132

134133
AUTH_PASSWORD_VALIDATORS = [
135134
{
@@ -148,11 +147,11 @@
148147

149148

150149
# Internationalization
151-
# https://docs.djangoproject.com/en/1.10/topics/i18n/
150+
# https://docs.djangoproject.com/en/3.2/topics/i18n/
152151

153152
LANGUAGE_CODE = 'en-us'
154153

155-
TIME_ZONE = 'UTC'
154+
TIME_ZONE = 'Asia/Taipei'
156155

157156
USE_I18N = True
158157

@@ -162,8 +161,11 @@
162161

163162

164163
# Static files (CSS, JavaScript, Images)
165-
# https://docs.djangoproject.com/en/1.10/howto/static-files/
164+
# https://docs.djangoproject.com/en/3.2/howto/static-files/
166165

167166
STATIC_URL = '/static/'
168-
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
169-
# MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
167+
168+
# Default primary key field type
169+
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
170+
171+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+15-13
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
"""django_rest_framework_tutorial URL Configuration
2-
32
The `urlpatterns` list routes URLs to views. For more information please see:
4-
https://docs.djangoproject.com/en/1.10/topics/http/urls/
3+
https://docs.djangoproject.com/en/3.2/topics/http/urls/
54
Examples:
65
Function views
76
1. Add an import: from my_app import views
8-
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
7+
2. Add a URL to urlpatterns: path('', views.home, name='home')
98
Class-based views
109
1. Add an import: from other_app.views import Home
11-
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
10+
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
1211
Including another URLconf
13-
1. Import the include() function: from django.conf.urls import url, include
14-
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
12+
1. Import the include() function: from django.urls import include, path
13+
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1514
"""
16-
from django.conf.urls import url, include
1715
from django.contrib import admin
16+
from django.urls import include, path
1817
from rest_framework.routers import DefaultRouter
19-
from musics import views
18+
from musics.views import MusicViewSet
2019

2120
router = DefaultRouter()
22-
router.register(r'music', views.MusicViewSet, base_name='music')
21+
router.register('musics', MusicViewSet)
22+
2323

2424
urlpatterns = [
25-
url(r'^admin/', admin.site.urls),
26-
url(r'^api/', include(router.urls, namespace='api'), name='api'),
27-
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
28-
]
25+
# path('admin/', admin.site.urls),
26+
# for rest_framework
27+
path('api/', include(router.urls)),
28+
# for rest_framework auth
29+
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
30+
]
+3-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
"""
22
WSGI config for django_rest_framework_tutorial project.
3-
43
It exposes the WSGI callable as a module-level variable named ``application``.
5-
64
For more information on this file, see
7-
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
5+
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
86
"""
97

108
import os
119

1210
from django.core.wsgi import get_wsgi_application
1311

14-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_rest_framework_tutorial.settings")
12+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_rest_framework_tutorial.settings')
1513

16-
application = get_wsgi_application()
14+
application = get_wsgi_application()

api/docker-entrypoint.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
echo 'Run migration'
3+
python3 manage.py makemigrations musics
4+
python3 manage.py migrate
5+
echo 'Create Super User'
6+
python3 manage.py createsuperuser --noinput || echo "Super user already created"
7+
exec "$@"

api/manage.py

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
23
import os
34
import sys
45

5-
if __name__ == "__main__":
6-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_rest_framework_tutorial.settings")
6+
7+
def main():
8+
"""Run administrative tasks."""
9+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_rest_framework_tutorial.settings')
710
try:
811
from django.core.management import execute_from_command_line
9-
except ImportError:
10-
# The above import may fail for some other reason. Ensure that the
11-
# issue is really that Django is missing to avoid masking other
12-
# exceptions on Python 2.
13-
try:
14-
import django
15-
except ImportError:
16-
raise ImportError(
17-
"Couldn't import Django. Are you sure it's installed and "
18-
"available on your PYTHONPATH environment variable? Did you "
19-
"forget to activate a virtual environment?"
20-
)
21-
raise
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
2218
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == '__main__':
22+
main()

api/musics/apps.py

+1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33

44
class MusicsConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
56
name = 'musics'

api/musics/tests.py

+2-86
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,3 @@
1-
# Create your tests here.
2-
from django.contrib.auth.models import User
3-
from rest_framework import status
4-
from rest_framework.reverse import reverse
5-
from rest_framework.test import APITestCase, APIClient
1+
from django.test import TestCase
62

7-
from musics.models import Music
8-
9-
10-
class MusicViewTestCase(APITestCase):
11-
url_reverse = reverse('api:music-list')
12-
url = '/api/music/'
13-
url_detail = '/api/music/{}/'
14-
url_detail_route_reverse = reverse('api:music-detail', kwargs={"pk": 1})
15-
url_detail_route = '/api/music/{}/detail/'
16-
url_list_route = '/api/music/all_singer/'
17-
18-
def setUp(self):
19-
print('setUp')
20-
21-
self.client = APIClient()
22-
# create user
23-
User.objects.create_user(username='test_user', password='password123')
24-
25-
self.client.login(username='test_user', password='password123')
26-
27-
self.request_data = {
28-
'song': 'song_test',
29-
'singer': 'singer_test'
30-
}
31-
32-
self.music = Music.objects.create(song='song_test', singer='singer_test')
33-
34-
def test_api_music_create(self):
35-
print('test_api_music_create')
36-
self.response = self.client.post(
37-
self.url,
38-
self.request_data,
39-
format="json"
40-
)
41-
self.assertEqual(self.response.status_code, status.HTTP_201_CREATED)
42-
self.assertEqual(Music.objects.count(), 2)
43-
self.assertEqual(Music.objects.get(pk=self.music.id).song, 'song_test')
44-
self.assertEqual(Music.objects.get(pk=self.music.id).singer, 'singer_test')
45-
46-
def test_api_music_retrieve(self):
47-
print('test_api_music_retrieve')
48-
music = Music.objects.get(pk=self.music.id)
49-
response = self.client.get(self.url_detail.format(self.music.id))
50-
self.assertEqual(response.status_code, status.HTTP_200_OK)
51-
self.assertEqual(response.data.get('song', None), music.song)
52-
self.assertEqual(response.data.get('singer', None), music.singer)
53-
54-
def test_api_music_partial_update(self):
55-
print('test_api_music_partial_update')
56-
update_song = {'song': 'song_update'}
57-
response = self.client.patch(self.url_detail.format(self.music.id), update_song, format='json')
58-
self.assertEqual(response.status_code, status.HTTP_200_OK)
59-
self.assertEqual(response.data.get('song', None), update_song.get('song', None))
60-
61-
def test_api_music_update(self):
62-
print('test_api_music_update')
63-
update_song = {'song': 'song_update', 'singer': 'singer_update'}
64-
response = self.client.put(self.url_detail.format(self.music.id), update_song, format='json')
65-
self.assertEqual(response.status_code, status.HTTP_200_OK)
66-
self.assertEqual(response.data.get('song', None), update_song.get('song'))
67-
self.assertEqual(response.data.get('singer', None), update_song.get('singer'))
68-
69-
def test_api_music_delete(self):
70-
print('test_api_music_delete')
71-
response = self.client.delete(self.url_detail.format(self.music.id))
72-
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
73-
74-
def test_api_music_detail_route(self):
75-
print('test_api_music_detail_route')
76-
music = Music.objects.get(pk=self.music.id)
77-
response = self.client.get(self.url_detail_route.format(self.music.id))
78-
self.assertEqual(response.status_code, status.HTTP_200_OK)
79-
self.assertEqual(response.data.get('song', None), music.song)
80-
self.assertEqual(response.data.get('singer', None), music.singer)
81-
82-
def test_api_music_list_route(self):
83-
print('test_api_music_list_route')
84-
music = Music.objects.values_list('singer', flat=True).distinct()
85-
response = self.client.get(self.url_list_route)
86-
self.assertEqual(response.status_code, status.HTTP_200_OK)
87-
self.assertEqual(next(iter(response.data)), next(iter(music)))
3+
# Create your tests here.

0 commit comments

Comments
 (0)