Membangung Aplikasi Blog from Zero to Deployment menggunakan Django versi 5
modified: .gitignore
modified: README.md
modified: README.md
new file: dreamblog/__init__.py
new file: dreamblog/asgi.py
new file: dreamblog/settings.py
new file: dreamblog/urls.py
new file: dreamblog/wsgi.py
new file: manage.py
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ ls
dreamblog/ manage.py* README.md
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 21, 2024 - 10:13:56
Django version 5.0.2, using settings 'dreamblog.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Django version 5.0.2, using settings 'dreamblog.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
modified: README.md
(dreamblog) λ mkdir apps
(dreamblog) λ mkdir apps\blog
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ ls
apps/ db.sqlite3 dreamblog/ manage.py* README.md
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py startapp blog apps\blog
modified: README.md
new file: apps/blog/__init__.py
new file: apps/blog/admin.py
new file: apps/blog/apps.py
new file: apps/blog/migrations/__init__.py
new file: apps/blog/models.py
new file: apps/blog/tests.py
new file: apps/blog/views.py
modified: README.md
modified: apps/blog/apps.py
modified: dreamblog/settings.py
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ ls
apps/ db.sqlite3 dreamblog/ manage.py* README.md
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py check
System check identified no issues (0 silenced).
modified: README.md
new file: apps/blog/urls.py
modified: apps/blog/views.py
modified: dreamblog/urls.py
modified: README.md
new file: apps/blog/templates/blog/index.html
modified: apps/blog/views.py
modified: README.md
new file: apps/blog/templates/blog/contact.html
modified: apps/blog/urls.py
modified: apps/blog/views.py
modified: README.md
modified: apps/blog/templates/blog/contact.html
modified: apps/blog/templates/blog/index.html
modified: README.md
modified: apps/blog/templates/blog/index.html
modified: README.md
modified: dreamblog/settings.py
modified: dreamblog/urls.py
new file: static_in_env/assets/css/custom.css
new file: static_in_env/assets/css/fontastic.css
...
new file: static_in_env/assets/vendor/popper.js/umd/popper.min.js
new file: static_in_env/assets/vendor/popper.js/umd/poppper.js.flow
modified: README.md
modified: apps/blog/templates/blog/index.html
modified: README.md
new file: apps/blog/templates/blog/blog.html
modified: apps/blog/urls.py
modified: apps/blog/views.py
modified: README.md
modified: apps/blog/templates/blog/blog.html
modified: README.md
new file: apps/blog/templates/blog/base.html
modified: README.md
modified: apps/blog/views.py
modified: README.md
modified: apps/blog/templates/blog/base.html
modified: apps/blog/templates/blog/index.html
modified: README.md
modified: apps/blog/templates/blog/index.html
modified: apps/blog/views.py
modified: README.md
modified: apps/blog/templates/blog/base.html
modified: apps/blog/templates/blog/index.html
modified: README.md
new file: apps/blog/templates/blog/partials/_footer.html
new file: apps/blog/templates/blog/partials/_head.html
new file: apps/blog/templates/blog/partials/_header.html
new file: apps/blog/templates/blog/partials/_scripts.html
modified: README.md
modified: apps/blog/templates/blog/base.html
modified: apps/blog/templates/blog/partials/_footer.html
modified: apps/blog/templates/blog/partials/_head.html
modified: apps/blog/templates/blog/partials/_header.html
modified: apps/blog/templates/blog/partials/_scripts.html
Note:
Tampilan home page saat ini tidak sempurna
karena tanpa head, header, footer, dan scripts (21_template_partials/02).
modified: README.md
modified: apps/blog/templates/blog/base.html
modified: README.md
modified: apps/blog/templates/blog/blog.html
modified: README.md
new file: apps/blog/templates/blog/post.html
modified: apps/blog/urls.py
modified: apps/blog/views.py
modified: README.md
modified: apps/blog/templates/blog/contact.html
modified: apps/blog/templates/blog/partials/_footer.html
modified: apps/blog/templates/blog/partials/_header.html
modified: README.md
new file: apps/post/__init__.py
new file: apps/post/admin.py
new file: apps/post/apps.py
new file: apps/post/migrations/__init__.py
new file: apps/post/models.py
new file: apps/post/tests.py
new file: apps/post/views.py
(dreamblog) λ python manage.py check
System check identified no issues (0 silenced).
modified: README.md
modified: apps/post/apps.py
modified: dreamblog/settings.py
modified: README.md
modified: dreamblog/settings.py
(dreamblog) λ pip install psycopg2-binary
Collecting psycopg2-binary
Using cached psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl.metadata (4.6 kB)
Using cached psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl (1.2 MB)
Installing collected packages: psycopg2-binary
Successfully installed psycopg2-binary-2.9.9
modified: README.md
modified: dreamblog/settings.py
(dreamblog) λ touch .env .env-example
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ pip install django-environ
Collecting django-environ
Using cached django_environ-0.11.2-py2.py3-none-any.whl.metadata (11 kB)
Using cached django_environ-0.11.2-py2.py3-none-any.whl (19 kB)
Installing collected packages: django-environ
Successfully installed django-environ-0.11.2
STEPS:
1. Install: pip install django-environ
2. Create .env file
3. Setup .env
DEBUG=on
SECRET_KEY=
DATABASE_NAME=
DATABASE_USER=
DATABASE_PASSWORD=
4. Setup settings.py in 6 steps:
# step: 1 of 6 import environ
import environ
env = environ.Env( # new
# set casting, default value
DEBUG=(bool, False)
)
# step: 2 of 6: Set the project base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# step: 3 of 6: Take environment variables from .env file
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
# step: 4 of 6: SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')
# step: 5 of 6: False if not in os.environ because of casting above
DEBUG = env('DEBUG') # new
# step: 6 of 6: Set the db connection
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': env('DATABASE_NAME'),
'USERNAME': env('DATABASE_USER'),
'PASSWORD': env('DATABASE_PASSWORD'),
'HOST': 'localhost',
'PORT': '5432'
}
}
5. Check:
(dreamblog) λ python manage.py check
System check identified no issues (0 silenced).
6. source: https://django-environ.readthedocs.io/en/latest/quickstart.html
new file: .env-example
modified: .gitignore
modified: README.md
modified: dreamblog/settings.py
""" ======================================
ANALISA BERDASARKAN DEMO PROYEK (TEMPLATE)
==========================================
Setiap post terdiri dari:
.category
.tag
.title
.overview
.thumbnail
.author:
.author name
.author profile_picture
.timestamp atau tanggal terbit
.jumlah komen
.jumlah berapa kali dibuka/dilihat oleh user
.jenis post:
. featured
. bukan featured
JADI, berdasarkan analisa di atas kita harus membuat 4 model:
1. Author
2. Category
3. Tag
4. Post
Hubungan / relationship antar model:
1. Author dan Post memiliki hubungan OneToMany
1.1 Di dalam tabel Author, dapat berisi 0, 1, atau banyak author.
1.2 Setiap author, memiliki nama dan photonya.
1.3 Setiap author dapat membuat 0, 1, atau banyak post.
Dengan kata lain, setiap post dibuat oleh seorang author.
1.4 Setiap post memiliki banyak atribut (lihat poin 4)
2. Category dan Post memiliki hubungan ManyToMany
2.1 Di dalam table Category, dapat berisi 0, 1, atau banyak category.
2.2 Setiap category memiliki nama dan mungkin juga memiliki slug.
2.3 Dalam hubungannya dengan post, setiap category dapat memiliki 0, 1, atau banyak post.
Dengan kata lain, setiap post dapat menjadi bagian dari satu atau lebih dari satu category.
1.4 Setiap post memiliki banyak atribut (lihat poin 4)
3. Category dan Tag memiliki hubungan OneToMany
3.1 Di dalam table Category, dapat berisi 0, 1, atau banyak category.
3.2 Setiap category memiliki nama dan mungkin juga memiliki slug.
3.3 Di dalam tabel Tag, dapat berisi 0, 1, atau banyak tag.
4.3 Setiap tag, atau beberapa tag dapat menjadi bagian dari satu category.
Dengan kata lain, sebuah category dapat memiliki 0, 1, atau banyak tag.
4. Post dan Category memiliki hubungan ManyToMany
4.1 Di dalam tabel post, dapat berisi 0, 1, atau banyak category yang didasarkan pada id dari category yang bersangkutan.
Dengan kata lain, setiap post harus menjadi bagian dari sebuah category.
Atau, setiap category dapat memiliki 0, 1, atau banyak post.
5. Post dan Tag memiliki hubungan ManyToMany
5.1 Di dalam tabel post, dapat berisi 0, 1, atau banyak tag yang didasarkan pada id dari tag yang bersangkutan.
Dengan kata lain, setiap post harus menjadi bagian dari sebuah tag.
Atau, setiap tag dapat memiliki 0, 1, atau banyak post.
NOTE:
Di dalam Django, dua model atau entitas yang memiliki hubungan ManyToMany, maka Django akan
secara otomatis membuatkan entitas baru yang menghubungkan kedua model.
"""
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
modified: README.md
modified: apps/post/models.py
(dreamblog) λ python manage.py check
SystemCheckError: System check identified some issues:
ERRORS:
post.Author.profile_picture: (fields.E210) Cannot use ImageField because Pillow is not installed.
HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "python -m pip install Pillow".
post.Post.thumbnail: (fields.E210) Cannot use ImageField because Pillow is not installed.
HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "python -m pip install Pillow".
System check identified 2 issues (0 silenced).
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ pip install pillow
Collecting pillow
Using cached pillow-10.2.0-cp312-cp312-win_amd64.whl.metadata (9.9 kB)
Using cached pillow-10.2.0-cp312-cp312-win_amd64.whl (2.6 MB)
Installing collected packages: pillow
Successfully installed pillow-10.2.0
NOTE:
Karena di dalam tabel Author ada kolom profile_picture (tempat image),
maka Django akan minta kita untuk menginstal Pillow.
modified: README.md
modified: dreamblog/settings.py
NOTE: Tentang perintah makemigrations
Saat Anda membuat perubahan pada model Anda, seperti menambahkan bidang baru, mengubah jenis bidang, atau bahkan membuat model baru, menjalankannya akan makemigrationsmenganalisis perubahan tersebut dan menghasilkan file migrasi yang menangkap perubahan dalam format yang dapat dibaca manusia. File migrasi ini disimpan di migrationsdirektori aplikasi Anda.
Makemigrations di Django pada dasarnya menghasilkan perintah SQL untuk aplikasi yang sudah diinstal sebelumnya (yang dapat dilihat di aplikasi yang diinstal di settings.py) dan model aplikasi yang baru Anda buat yang Anda tambahkan di aplikasi yang diinstal. Itu tidak menjalankan perintah-perintah itu di file database Anda. Jadi tabel tidak dibuat setelah melakukan migrasi. Setelah menerapkan makemigrations Anda dapat melihat perintah SQL tersebut dengan sqlmigrate yang menampilkan semua perintah SQL yang telah dihasilkan oleh makemigrations. Untuk mengetahui lebih lanjut tentang makemigrations, kunjungi
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py check
System check identified no issues (0 silenced).
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py makemigrations
Migrations for 'post':
apps\post\migrations\0001_initial.py
- Create model Category
- Create model Author
- Create model Tag
- Create model Post
C:\Users\ING\Desktop\2024-DEVSPACE\2024-dj5-dream-blog\root(main -> origin)
(dreamblog) λ python manage.py sqlmigrate post 0001
BEGIN;
--
-- Create model Category
--
CREATE TABLE "post_category" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"title" varchar(25) NOT NULL
);
--
-- Create model Author
--
CREATE TABLE "post_author" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"profile_picture" varchar(100) NOT NULL, "user_id" integer NOT NULL UNIQUE
);
--
-- Create model Tag
--
CREATE TABLE "post_tag" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"title" varchar(30) NOT NULL, "category_id" bigint NOT NULL
);
--
-- Create model Post
--
CREATE TABLE "post_post" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"title" varchar(100) NOT NULL,
"overview" text NOT NULL,
"timestamp" timestamp with time zone NOT NULL,
"comment_count" integer NOT NULL,
"view_count" integer NOT NULL,
"thumbnail" varchar(100) NOT NULL,
"featured" boolean NOT NULL,
"author_id" bigint NOT NULL
);
CREATE TABLE "post_post_categories" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"post_id" bigint NOT NULL,
"category_id" bigint NOT NULL
);
CREATE TABLE "post_post_tags" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"post_id" bigint NOT NULL,
"tag_id" bigint NOT NULL
);
ALTER TABLE "post_author"
ADD CONSTRAINT
"post_author_user_id_8583799e_fk_auth_user_id"
FOREIGN KEY ("user_id")
REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "post_tag"
ADD CONSTRAINT
"post_tag_category_id_885a6954_fk_post_category_id"
FOREIGN KEY ("category_id")
REFERENCES "post_category" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "post_tag_category_id_885a6954" ON "post_tag" ("category_id");
ALTER TABLE "post_post"
ADD CONSTRAINT
"post_post_author_id_99d134d5_fk_post_author_id"
FOREIGN KEY ("author_id")
REFERENCES "post_author" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "post_post_author_id_99d134d5" ON "post_post" ("author_id");
ALTER TABLE "post_post_categories"
ADD CONSTRAINT
"post_post_categories_post_id_category_id_a3046e59_uniq"
UNIQUE ("post_id", "category_id");
ALTER TABLE "post_post_categories"
ADD CONSTRAINT "post_post_categories_post_id_4e6b60a6_fk_post_post_id"
FOREIGN KEY ("post_id")
REFERENCES "post_post" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "post_post_categories"
ADD CONSTRAINT "post_post_categories_category_id_c3484c55_fk_post_category_id"
FOREIGN KEY ("category_id")
REFERENCES "post_category" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "post_post_categories_post_id_4e6b60a6" ON "post_post_categories" ("post_id");
CREATE INDEX "post_post_categories_category_id_c3484c55" ON "post_post_categories" ("category_id");
ALTER TABLE "post_post_tags"
ADD CONSTRAINT
"post_post_tags_post_id_tag_id_15c628ee_uniq"
UNIQUE ("post_id", "tag_id");
ALTER TABLE "post_post_tags"
ADD CONSTRAINT
"post_post_tags_post_id_6adf1c1b_fk_post_post_id"
FOREIGN KEY ("post_id")
REFERENCES "post_post" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "post_post_tags"
ADD CONSTRAINT
"post_post_tags_tag_id_cb551e85_fk_post_tag_id"
FOREIGN KEY ("tag_id")
REFERENCES "post_tag" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "post_post_tags_post_id_6adf1c1b" ON "post_post_tags" ("post_id");
CREATE INDEX "post_post_tags_tag_id_cb551e85" ON "post_post_tags" ("tag_id");
COMMIT;
modified: README.md
new file: apps/post/migrations/0001_initial.py
NOTE: Tentang perintah migrate
Perintah ini migratemenerapkan perubahan yang dicatat dalam file migrasi ke database. Ini mengeksekusi kueri SQL yang diperlukan untuk membuat skema database sejalan dengan definisi model Anda. Perintah ini membuat tabel, mengubah kolom, menambahkan indeks, dan melakukan operasi terkait database lainnya yang diperlukan untuk mencerminkan perubahan yang Anda buat.
Perintah ini migratemenangani urutan penerapan migrasi, memastikan bahwa ketergantungan antar migrasi terpenuhi.
Migrasi di Django pada dasarnya migrasi mengeksekusi perintah SQL dalam file database. Jadi setelah menjalankan migrasi, semua tabel aplikasi yang Anda instal dibuat di file database Anda.
Jadi selalu ingat setiap kali Anda membuat model baru atau mengubah model yang sudah ada, Anda harus selalu menerapkan makemigation terlebih dahulu dan kemudian perintah migrasi untuk melihat perubahan yang Anda buat pada model harus diterapkan ke database.
(dreamblog) λ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, post, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying post.0001_initial... OK
Applying sessions.0001_initial... OK
(dreamblog) λ python manage.py dbshell
psql (15.3, server 16.1)
WARNING: psql major version 15, server major version 16.
Some psql features might not work.
WARNING: Console code page (437) differs from Windows code page (1252)
8-bit characters might not work correctly. See psql reference
page "Notes for Windows users" for details.
Type "help" for help.
<!-- SHOW TABLES -->
2024-dj5-dream-blog=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------------------+-------+----------
public | auth_group | table | postgres
public | auth_group_permissions | table | postgres
public | auth_permission | table | postgres
public | auth_user | table | postgres
public | auth_user_groups | table | postgres
public | auth_user_user_permissions | table | postgres
public | django_admin_log | table | postgres
public | django_content_type | table | postgres
public | django_migrations | table | postgres
public | django_session | table | postgres
public | post_author | table | postgres
public | post_category | table | postgres
public | post_post | table | postgres
public | post_post_categories | table | postgres
public | post_post_tags | table | postgres
public | post_tag | table | postgres
(16 rows)
<!-- DESCRIBE TABLE post_author -->
2024-dj5-dream-blog=# \dt post_author;
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
public | post_author | table | postgres
(1 row)
<!-- SELECT * FROM post_author -->
2024-dj5-dream-blog=# SELECT * FROM post_author;
id | profile_picture | user_id
----+-----------------+---------
(0 rows)
<!-- SELECT user FROM post_author -->
2024-dj5-dream-blog=# SELECT user FROM post_author;
user
------
(0 rows)
<!-- SELECT user, profile_picture FROM post_author -->
2024-dj5-dream-blog=# SELECT user, profile_picture FROM post_author;
user | profile_picture
------+-----------------
(0 rows)
modified: README.md
(dreamblog) λ python manage.py createsuperuser
Username (leave blank to use 'ing'): superuser
Email address: superuser@mail.com
Password:superuser@mail.com
Password (again):superuser@mail.com
The password is too similar to the email address.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
modified: README.md
modified: apps/post/admin.py
modified: README.md
new file: media_root/authors/avatar-1.jpg
new file: media_root/authors/avatar-2.jpg
new file: media_root/authors/avatar-3.jpg
new file: media_root/authors/ing.jpeg
new file: media_root/featured-pic-1.jpeg
new file: media_root/featured-pic-2.jpeg
new file: media_root/featured-pic-3.jpeg
modified: README.md
modified: apps/blog/urls.py
modified: apps/blog/views.py
new file: apps/post/templates/post/base.html
new file: apps/post/templates/post/blog.html
new file: apps/post/templates/post/contact.html
new file: apps/post/templates/post/index.html
new file: apps/post/templates/post/partials/_footer.html
new file: apps/post/templates/post/partials/_head.html
new file: apps/post/templates/post/partials/_header.html
new file: apps/post/templates/post/partials/_scripts.html
new file: apps/post/templates/post/post.html
new file: apps/post/urls.py
modified: apps/post/views.py
modified: dreamblog/urls.py
NOTE:
1. Templates, views, and urls dipindahkan dari apps/blog ke apps/posts.
2. Image dalam post diplay tidak sesuai tampilan semula (tidak selang-seling)
NEXT: Mengatur tampilan thumbnail agar selang-seling.
modified: README.md
modified: apps/post/templates/post/index.html
modified: README.md
modified: apps/post/templates/post/blog.html
modified: apps/post/templates/post/index.html
modified: apps/post/views.py
new file: media_root/featured-pic-1_furvADn.jpeg
modified: README.md
modified: apps/post/templates/post/blog.html
modified: apps/post/views.py
modified: README.md
modified: apps/post/templates/post/blog.html
modified: apps/post/views.py
modified: README.md
modified: apps/post/templates/post/blog.html
modified: apps/post/views.py
modified: README.md
modified: apps/post/views.py
new file: media_root/featured-pic-3_vLUFDZI.jpeg
modified: README.md
modified: apps/post/templates/post/blog.html