Skip to content

Commit

Permalink
upgrade python3.9 django4
Browse files Browse the repository at this point in the history
  • Loading branch information
twtrubiks committed Jun 29, 2022
1 parent 75092d6 commit 412796c
Show file tree
Hide file tree
Showing 34 changed files with 202 additions and 2,338 deletions.
19 changes: 14 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ lib64/
parts/
sdist/
var/
migrations/
wheels/
*.egg-info/
.installed.cfg
*.egg
Expand All @@ -43,7 +43,7 @@ htmlcov/
.cache
nosetests.xml
coverage.xml
*,cover
*.cover
.hypothesis/

# Translations
Expand All @@ -67,7 +67,7 @@ docs/_build/
# PyBuilder
target/

# IPython Notebook
# Jupyter Notebook
.ipynb_checkpoints

# pyenv
Expand All @@ -76,17 +76,26 @@ target/
# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# dotenv
.env

# virtualenv
.venv
venv/
ENV/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject
.idea/
settings_db_string.py

# mkdocs documentation
/site

# mypy
.mypy_cache/
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: gunicorn ptt_beauty_images.wsgi
web: gunicorn ptt_beauty_images.wsgi --preload
109 changes: 48 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Deploying a Django App To Heroku Tutorial

* [線上 Demo 網站](https://ptt-beauty-images.herokuapp.com/)
* [線上 Demo 網站](https://deploy-django-twtrubiks.herokuapp.com/api/images/)

後端有一個自動爬蟲的程式去抓圖片,可參考 [auto_crawler_ptt_beauty_image](https://github.com/twtrubiks/auto_crawler_ptt_beauty_image)

Expand Down Expand Up @@ -36,68 +36,63 @@ web: gunicorn ptt_beauty_images.wsgi

[https://devcenter.heroku.com/articles/django-app-configuration#the-basics](https://devcenter.heroku.com/articles/django-app-configuration#the-basics)

***設定 ALLOWED_HOSTS***
## 建議使用 WhiteNoise 佈署

[settings.py](https://github.com/twtrubiks/Deploying_Django_To_Heroku_Tutorial/blob/master/ptt_beauty_images/settings.py)
***設定 Collectstatic***

```python
ALLOWED_HOSTS = ['*']
```
Disabling Collectstatic
> heroku config:set DISABLE_COLLECTSTATIC=1
***設定 Static assets and file serving***
可參考 [https://devcenter.heroku.com/articles/django-assets#collectstatic-during-builds](https://devcenter.heroku.com/articles/django-assets#collectstatic-during-builds)

[settings.py](https://github.com/twtrubiks/Deploying_Django_To_Heroku_Tutorial/blob/master/ptt_beauty_images/settings.py)
```cmd
pip3 install whitenoise
```

```python
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
這樣靜態檔案才會正常顯示.

STATIC_URL = '/static/'
詳細說明可參考 [Using WhiteNoise with Django](https://whitenoise.evans.io/en/stable/django.html)

STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
[settings.py](https://github.com/twtrubiks/Deploying_Django_To_Heroku_Tutorial/blob/master/ptt_beauty_images/settings.py) 中加入以下東西,

***設定 ALLOWED_HOSTS***

```python
ALLOWED_HOSTS = ['*']
```

更多說明請參考
[https://devcenter.heroku.com/articles/django-app-configuration#static-assets-and-file-serving](https://devcenter.heroku.com/articles/django-app-configuration#static-assets-and-file-serving)

***設定 Whitenoise***

[settings.py](https://github.com/twtrubiks/Deploying_Django_To_Heroku_Tutorial/blob/master/ptt_beauty_images/settings.py)
記得把 DEBUG 修改為 `False`

```python
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

DEBUG = False
```

[wsgi.py](https://github.com/twtrubiks/Deploying_Django_To_Heroku_Tutorial/blob/master/ptt_beauty_images/wsgi.py)
設定 STATIC_ROOT

```python
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
STATIC_ROOT = BASE_DIR / "staticfiles"
```

application = get_wsgi_application()
application = DjangoWhiteNoise(application)
設定 WhiteNoise 到 MIDDLEWARE

```python
MIDDLEWARE = [
# ...
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
# ...
]
```

更多說明請參考 [https://devcenter.heroku.com/articles/django-app-configuration#whitenoise](https://devcenter.heroku.com/articles/django-app-configuration#whitenoise)

***設定 Collectstatic***
Add compression

Disabling Collectstatic
> heroku config:set DISABLE_COLLECTSTATIC=1
```python
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
```

更多說明請參考
最後執行 `python3 manage.py collectstatic`

[https://devcenter.heroku.com/articles/django-assets#collectstatic-during-builds](https://devcenter.heroku.com/articles/django-assets#collectstatic-during-builds)
如果沒有任何錯誤, 再將產生出來的東西一起 push 到 Heroku 上.

***設定 DATABASE***

Expand Down Expand Up @@ -140,7 +135,7 @@ DATABASES = {
'HOST': os.environ.get('DATABASE_HOST'),
'PORT': os.environ.get('DATABASE_PORT'),
},
'': {
'db2': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': os.environ.get('DATABASE_NAME_2'),
'USER': os.environ.get('DATABASE_USER_2'),
Expand Down Expand Up @@ -171,35 +166,19 @@ Image.objects.using('db2').all()

更多資料可參考 [Django manually-selecting-a-database](https://docs.djangoproject.com/en/1.11/topics/db/multi-db/#manually-selecting-a-database)

## 特色

* 使用 [lazyload](https://github.com/verlok/lazyload) 載入大量圖片。
## 更新 heroku stack 指令

* 圖片來源為爬蟲,可參考 [auto_crawler_ptt_beauty_image](https://github.com/twtrubiks/auto_crawler_ptt_beauty_image)

## 安裝套件

確定電腦有安裝 [Python](https://www.python.org/) 之後

請在 cmd ( 命令提示字元 ) 輸入以下指令
指令如下

```cmd
pip install -r requirements.txt
heroku stack:set heroku-22 -a <app name>
```

## 執行畫面

首頁

![](http://i.imgur.com/Ul9qrkN.png)

滑鼠游標移到圖片上,可刪除圖片

![](http://i.imgur.com/nSuslHP.png)
之後再 commit push 一次就會自動 migrate 到新的 stack.

## 執行環境

* Python 3.6.0
* Python 3.9

## Reference

Expand All @@ -208,6 +187,14 @@ pip install -r requirements.txt
* [lazyload](https://github.com/verlok/lazyload)
* [bootstrap-sweetalert](https://github.com/lipis/bootstrap-sweetalert)

## Donation

文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡:laughing:

![alt tag](https://i.imgur.com/LRct9xa.png)

[贊助者付款](https://payment.opay.tw/Broadcaster/Donate/9E47FDEF85ABE383A0F5FC6A218606F8)

## License

MIT license
1 change: 1 addition & 0 deletions images/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@


class ImagesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'images'
4 changes: 2 additions & 2 deletions images/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@


# Create your models here.
class Image(models.Model):
class Images(models.Model):
Url = models.TextField()
CreateDate = models.DateTimeField()

class Meta:
managed = False
# managed = False
db_table = 'Images'
4 changes: 2 additions & 2 deletions images/serializers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from rest_framework import serializers

from images.models import Image
from images.models import Images


class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
model = Images
# fields = '__all__'
fields = ('id', 'Url', 'CreateDate')
3 changes: 3 additions & 0 deletions images/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
70 changes: 37 additions & 33 deletions images/views.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
from django.shortcuts import render
from rest_framework import viewsets, status

from images.models import Image
from images.models import Images
from images.serializers import ImageSerializer
from ptt_beauty_images import settings

# from ptt_beauty_images import settings
from rest_framework.response import Response
from rest_framework.decorators import list_route


# single-databases
def index_old(request):
return render(request, 'index.html', {
'images': Image.objects.values('id', 'Url').order_by('-CreateDate')
})


# multiple-databases
def index(request):
images_seq = []
for db_name in settings.DATABASES:
query = Image.objects.using(db_name).all()
for data in query:
dict_image = {
'id': data.id,
'Url': data.Url,
'CreateDate': data.CreateDate
}
images_seq.append(dict_image)
images_seq = sorted(images_seq, key=lambda x: x['CreateDate'], reverse=True)
return render(request, 'index.html', {
'images': images_seq
})
from rest_framework.decorators import action
from django.db.models.aggregates import Count
from random import randint


# # single-databases
# def index_old(request):
# return render(request, 'index.html', {
# 'images': Image.objects.values('id', 'Url').order_by('-CreateDate')
# })


# # multiple-databases
# def index(request):
# images_seq = []
# for db_name in settings.DATABASES:
# query = Image.objects.using(db_name).all()
# for data in query:
# dict_image = {
# 'id': data.id,
# 'Url': data.Url,
# 'CreateDate': data.CreateDate
# }
# images_seq.append(dict_image)
# images_seq = sorted(images_seq, key=lambda x: x['CreateDate'], reverse=True)
# return render(request, 'index.html', {
# 'images': images_seq
# })


# Create your views here.
Expand All @@ -42,12 +43,15 @@ class ImageViewSet(viewsets.ModelViewSet):
Additionally we also provide an extra `highlight` action.
"""
queryset = Image.objects.all()

queryset = Images.objects.all()
serializer_class = ImageSerializer

# [ GET ] /api/image/random/
@list_route(methods=['get'], url_path='random')
@action(detail=False, methods=["get"], url_path="random")
def get_random_image(self, request):
image = Image.objects.all().order_by('?')[1]
result = ImageSerializer(image)
count = Images.objects.aggregate(count=Count("id"))["count"]
random_index = randint(0, count - 1)
obj = Images.objects.all()[random_index]
result = ImageSerializer(obj)
return Response(result.data, status=status.HTTP_200_OK)
30 changes: 15 additions & 15 deletions manage.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ptt_beauty_images.settings")

def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ptt_beauty_images.settings')
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
Loading

0 comments on commit 412796c

Please sign in to comment.