· 7 years ago · Feb 13, 2018, 03:32 AM
1site
2├── project
3│ ├── gallery
4│ │ ├── static
5│ │ │ ├── gallery
6│ │ │ │ ├── css
7│ │ │ │ └── images
8│ │ ├── templates
9│ │ │ └── gallery
10│ │ ├── admin.py
11│ │ ├── models.py
12│ │ ├── urls.py
13│ │ └── views.py
14│ ├── posts
15│ │ ├── static
16│ │ │ ├── posts
17│ │ │ │ ├── css
18│ │ │ │ └── images
19│ │ ├── templates
20│ │ │ └── gallery
21│ │ ├── admin.py
22│ │ ├── models.py
23│ │ ├── urls.py
24│ │ └── views.py
25│ ├── project
26│ │ ├── settings
27│ │ │ ├── base.py
28│ │ │ ├── development.py
29│ │ │ ├── local.py
30│ │ │ ├── production.py
31│ │ │ └── testing.py
32│ │ ├── urls.py
33│ │ └── wsgi.py
34│ ├── static
35│ └── templates
36
37...
38from imagekit.models import ImageSpecField
39from imagekit.processors import ResizeToFit, ResizeToFill
40...
41
42class Watermark(object):
43 def process(self, image):
44 pass
45
46class Image(models.Model):
47 original = ImageField(upload_to='images/%Y/%m/%d/')
48 large = ImageSpecField(source='original', processors=[Watermark(),
49 ResizeToFit(width=2000, height=2000, upscale=False)],
50 format='JPEG', options={'quality': 90})
51 medium=...
52 small=...
53 wide=...
54 home=...
55 upload_date = models.DateTimeField(null=True, editable=False)
56
57 def save(self):
58 if not self.id and not self.original:
59 return
60
61 if self.upload_date is None:
62 self.upload_date = timezone.now()
63
64 image = PIL.Image.open(self.original)
65 imgFormat = image.format
66 MAX_HEIGHT = 4000
67 MAX_WIDTH = 4000
68
69 # Resize image if over MAX pixels in either direction
70 (width, height) = image.size
71 if height > MAX_HEIGHT or width > MAX_WIDTH:
72 ratio = width / height
73 output = BytesIO()
74
75 if width > height:
76 width = MAX_WIDTH
77 height = int(width / ratio)
78 else:
79 height = MAX_HEIGHT
80 width = int(height * ratio)
81
82 size = (width, height)
83 image = image.resize(size, PIL.Image.ANTIALIAS)
84 image.save(output, format=imgFormat, quality=100)
85 self.original = InMemoryUploadedFile(output, 'ImageField',
86 self.original.name, 'images/', sys.getsizeof(output), None)
87 super(Image, self).save()
88
89class Post(models.Model):
90 title = models.CharField(max_length=75)
91 ...
92 image = models.ForeignKey(Image, blank=True, null=True,
93 on_delete=models.SET_NULL)
94 ...
95
96import os
97
98BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
99
100SECRET_KEY = os.environ['SECRET_KEY']
101
102DEBUG = True
103
104ALLOWED_HOSTS = []
105
106INSTALLED_APPS = [
107 'django.contrib.admin',
108 'django.contrib.auth',
109 'django.contrib.contenttypes',
110 'django.contrib.sessions',
111 'django.contrib.messages',
112 'django.contrib.staticfiles',
113 'posts',
114 'gallery',
115 'taggit',
116 'ckeditor',
117 'storages',
118 'imagekit',
119 ...
120]
121
122MIDDLEWARE = [
123 'django.middleware.security.SecurityMiddleware',
124 'django.contrib.sessions.middleware.SessionMiddleware',
125 'django.middleware.common.CommonMiddleware',
126 'django.middleware.csrf.CsrfViewMiddleware',
127 'django.contrib.auth.middleware.AuthenticationMiddleware',
128 'django.contrib.messages.middleware.MessageMiddleware',
129 'django.middleware.clickjacking.XFrameOptionsMiddleware',
130]
131
132ROOT_URLCONF = 'project.urls'
133
134TEMPLATES = [
135 {
136 'BACKEND': 'django.template.backends.django.DjangoTemplates',
137 'DIRS': [os.path.join(BASE_DIR, 'templates')],
138 'APP_DIRS': True,
139 'OPTIONS': {
140 'context_processors': [
141 'django.template.context_processors.debug',
142 'django.template.context_processors.request',
143 'django.contrib.auth.context_processors.auth',
144 'django.contrib.messages.context_processors.messages',
145 'django.template.context_processors.media',
146 ],
147 },
148 },
149]
150
151WSGI_APPLICATION = 'project.wsgi.application'
152
153AUTH_PASSWORD_VALIDATORS = [
154 {
155 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
156 },
157 {
158 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
159 },
160 {
161 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
162 },
163 {
164 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
165 },
166]
167
168LANGUAGE_CODE = 'en-us'
169
170TIME_ZONE = 'UTC'
171
172USE_I18N = True
173
174USE_L10N = True
175
176USE_TZ = True
177
178from project.settings.base import *
179
180# Override base.py settings here
181
182DEBUG = False
183
184ALLOWED_HOSTS = ['*']
185
186DATABASES = {
187 'default': {
188 'ENGINE': 'django.db.backends.postgresql_psycopg2',
189 'NAME': 'test',
190 'USER': 'user',
191 'PASSWORD': '****',
192 'HOST': 'localhost',
193 'PORT': '1234',
194 }
195}
196
197# DigitalOcean Spaces Settings
198AWS_ACCESS_KEY_ID = '*****'
199AWS_SECRET_ACCESS_KEY = '*****'
200AWS_STORAGE_BUCKET_NAME = 'production-storage'
201AWS_S3_ENDPOINT_URL = 'https://nyc3.digitaloceanspaces.com'
202AWS_S3_OBJECT_PARAMETERS = {
203 'CacheControl': 'max-age=86400'
204}
205AWS_LOCATION = 'static_test/'
206
207STATICFILES_DIRS = [
208 os.path.join(BASE_DIR, 'static', 'static'),
209]
210
211STATIC_URL = 'https://%s/%s/' % (AWS_S3_ENDPOINT_URL, AWS_LOCATION)
212STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
213DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
214IMAGEKIT_DEFAULT_IMAGE_CACHE_BACKEND = 'imagekit.imagecache.NonValidatingImageCacheBackend'
215
216# Needed for CKEditor to work
217AWS_QUERYSTRING_AUTH = False
218
219#!/bin/bash
220
221NAME="project"
222DIR=/home/user/site/project
223USER=brandon
224GROUP=brandon
225WORKERS=3
226BIND=unix:/home/user/run/gunicorn.sock
227DJANGO_SETTINGS_MODULE=project.settings.testing
228DJANGO_WSGI_MODULE=project.wsgi
229SECRET_KEY='*****'
230LOG_LEVEL=error
231
232cd $DIR
233source ../../venv/bin/activate
234
235export SECRET_KEY=$SECRET_KEY
236export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
237export PYTHONPATH=$DIR:$PYTHONPATH
238
239exec ../../venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application
240 --name $NAME
241 --workers $WORKERS
242 --user=$USER
243 --group=$GROUP
244 --bind=$BIND
245 --log-level=$LOG_LEVEL
246 --log-file=-
247
248upstream app_server {
249 server unix:/home/user/run/gunicorn.sock fail_timeout=0;
250}
251
252server {
253 listen 80;
254
255 # add here the ip address of your server
256 # or a domain pointing to that ip(like example.com or www.example.com)
257 server_name 192.168.1.179
258
259 keepalive_timeout 5;
260 client_max_body_size 4G;
261 access_log /home/user/logs/nginx-access.log;
262 error_log /home/user/logs/nginx-error.log;
263
264 location /static/ {
265 alias /home/user/site/project/static;
266 }
267
268 # checks for static file, if not found proxy to app
269 location / {
270 try_files $uri @proxy_to_app;
271 }
272
273 location @proxy_to_app {
274 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
275 proxy_set_header Host $http_host;
276 proxy_redirect off;
277 proxy_pass http://app_server;
278 }
279}