├── blog ├── __init__.py ├── migrations │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── 0001_initial.cpython-37.pyc │ │ ├── 0002_comment_parent.cpython-37.pyc │ │ ├── 0004_auto_20191015_0853.cpython-37.pyc │ │ ├── 0005_auto_20211014_1338.cpython-37.pyc │ │ └── 0003_remove_comment_parent.cpython-37.pyc │ ├── 0003_remove_comment_parent.py │ ├── 0002_comment_parent.py │ ├── 0004_auto_20191015_0853.py │ ├── 0005_auto_20211014_1338.py │ └── 0001_initial.py ├── tests.py ├── apps.py ├── __pycache__ │ ├── admin.cpython-37.pyc │ ├── apps.cpython-37.pyc │ ├── feeds.cpython-37.pyc │ ├── forms.cpython-37.pyc │ ├── urls.cpython-37.pyc │ ├── views.cpython-37.pyc │ ├── models.cpython-37.pyc │ ├── __init__.cpython-37.pyc │ └── sitemaps.cpython-37.pyc ├── forms.py ├── sitemaps.py ├── urls.py ├── admin.py ├── feeds.py ├── models.py └── views.py ├── mysite ├── __init__.py ├── __pycache__ │ ├── urls.cpython-37.pyc │ ├── wsgi.cpython-37.pyc │ ├── __init__.cpython-37.pyc │ └── settings.cpython-37.pyc ├── wsgi.py ├── urls.py └── settings.py ├── db.sqlite3 ├── requirements.txt ├── Makefile ├── static └── css │ └── base.css ├── manage.py ├── templates ├── sidebar.html ├── index.html ├── post_detail.html └── base.html └── README.md /blog/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mysite/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/db.sqlite3 -------------------------------------------------------------------------------- /blog/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | name = "blog" 6 | -------------------------------------------------------------------------------- /blog/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/apps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/apps.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/feeds.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/feeds.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/forms.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/forms.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/views.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/views.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /mysite/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/mysite/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /mysite/__pycache__/wsgi.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/mysite/__pycache__/wsgi.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /blog/__pycache__/sitemaps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/__pycache__/sitemaps.cpython-37.pyc -------------------------------------------------------------------------------- /mysite/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/mysite/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /mysite/__pycache__/settings.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/mysite/__pycache__/settings.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/0001_initial.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/0001_initial.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/0002_comment_parent.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/0002_comment_parent.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/0004_auto_20191015_0853.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/0004_auto_20191015_0853.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/0005_auto_20211014_1338.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/0005_auto_20211014_1338.cpython-37.pyc -------------------------------------------------------------------------------- /blog/migrations/__pycache__/0003_remove_comment_parent.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sroycho4/Django_Project/HEAD/blog/migrations/__pycache__/0003_remove_comment_parent.cpython-37.pyc -------------------------------------------------------------------------------- /blog/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Comment 4 | 5 | 6 | class CommentForm(forms.ModelForm): 7 | class Meta: 8 | model = Comment 9 | fields = ("name", "email", "body") 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.4.1 2 | autopep8==1.5.7 3 | Django==3.2.12 4 | django-crispy-forms==1.13.0 5 | django-debug-toolbar==3.2.2 6 | django-summernote==0.8.11.6 7 | pycodestyle==2.8.0 8 | pytz==2021.3 9 | sqlparse==0.4.2 10 | toml==0.10.2 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | pip install -r requirements.txt 3 | 4 | test: 5 | python manage.py test 6 | 7 | makemigrations: 8 | python manage.py makemigrations 9 | 10 | migrate: 11 | python manage.py migrate 12 | 13 | run: 14 | python manage.py runserver 15 | -------------------------------------------------------------------------------- /blog/sitemaps.py: -------------------------------------------------------------------------------- 1 | from django.contrib.sitemaps import Sitemap 2 | 3 | from .models import Post 4 | 5 | 6 | class PostSitemap(Sitemap): 7 | changefreq = "weekly" 8 | priority = 0.8 9 | 10 | def items(self): 11 | return Post.objects.filter(status=1) 12 | 13 | def lastmod(self, obj): 14 | return obj.updated_on 15 | 16 | # def location(self, item): 17 | # return reverse(item) 18 | -------------------------------------------------------------------------------- /blog/migrations/0003_remove_comment_parent.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.6 on 2019-10-13 14:16 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('blog', '0002_comment_parent'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='comment', 15 | name='parent', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /blog/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | from .feeds import AtomSiteNewsFeed, LatestPostsFeed 5 | 6 | urlpatterns = [ 7 | path("feed/rss", LatestPostsFeed(), name="post_feed"), 8 | path("feed/atom", AtomSiteNewsFeed()), 9 | path("", views.PostList.as_view(), name="home"), 10 | # path('/', views.PostDetail.as_view(), name='post_detail'), 11 | path("/", views.post_detail, name="post_detail"), 12 | ] -------------------------------------------------------------------------------- /mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /static/css/base.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Roboto", sans-serif; 3 | font-size: 17px; 4 | background-color: #fdfdfd; 5 | } 6 | 7 | .shadow { 8 | box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.1); 9 | } 10 | 11 | .btn-danger { 12 | color: #fff; 13 | background-color: #f00000; 14 | border-color: #dc281e; 15 | } 16 | 17 | .masthead { 18 | background: #3398E1; 19 | height: auto; 20 | padding-bottom: 15px; 21 | box-shadow: 0 16px 48px #E3E7EB; 22 | padding-top: 10px; 23 | } 24 | 25 | .card { 26 | box-shadow: 0 16px 48px #E3E7EB; 27 | } 28 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /blog/migrations/0002_comment_parent.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.6 on 2019-10-13 12:05 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('blog', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='comment', 16 | name='parent', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='blog.Comment'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /templates/sidebar.html: -------------------------------------------------------------------------------- 1 | {% block sidebar %} 2 | 3 | 4 | 5 | 6 |
7 |
8 |
About Us
9 |
10 |

This awesome blog is made with our Favourite full stack Framework Django, 11 | follow up the tutorial to learn how we made it

12 | Know more 13 |
14 |
15 |
16 | 17 | {% endblock sidebar %} 18 | -------------------------------------------------------------------------------- /blog/migrations/0004_auto_20191015_0853.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.6 on 2019-10-15 08:53 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('blog', '0003_remove_comment_parent'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='comment', 15 | name='status', 16 | ), 17 | migrations.AddField( 18 | model_name='comment', 19 | name='active', 20 | field=models.BooleanField(default=False), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /blog/migrations/0005_auto_20211014_1338.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2 on 2021-10-14 13:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('blog', '0004_auto_20191015_0853'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='comment', 15 | name='id', 16 | field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), 17 | ), 18 | migrations.AlterField( 19 | model_name='post', 20 | name='id', 21 | field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /blog/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django_summernote.admin import SummernoteModelAdmin 3 | 4 | from .models import Comment, Post 5 | 6 | 7 | class PostAdmin(SummernoteModelAdmin): 8 | list_display = ("title", "slug", "status", "created_on") 9 | list_filter = ("status", "created_on") 10 | search_fields = ["title", "content"] 11 | prepopulated_fields = {"slug": ("title",)} 12 | 13 | summernote_fields = ("content",) 14 | 15 | 16 | @admin.register(Comment) 17 | class CommentAdmin(admin.ModelAdmin): 18 | list_display = ("name", "body", "post", "created_on", "active") 19 | list_filter = ("active", "created_on") 20 | search_fields = ("name", "email", "body") 21 | actions = ["approve_comments"] 22 | 23 | def approve_comments(self, request, queryset): 24 | queryset.update(active=True) 25 | 26 | 27 | admin.site.register(Post, PostAdmin) 28 | -------------------------------------------------------------------------------- /blog/feeds.py: -------------------------------------------------------------------------------- 1 | from django.contrib.syndication.views import Feed 2 | from django.template.defaultfilters import truncatewords 3 | from django.urls import reverse 4 | 5 | from .models import Post 6 | 7 | 8 | class LatestPostsFeed(Feed): 9 | title = "My blog" 10 | link = "" 11 | description = "New posts of my blog." 12 | 13 | def items(self): 14 | return Post.objects.filter(status=1) 15 | 16 | def item_title(self, item): 17 | return item.title 18 | 19 | def item_description(self, item): 20 | return truncatewords(item.content, 30) 21 | 22 | # Only needed if the model has no get_absolute_url method 23 | # def item_link(self, item): 24 | # return reverse("post_detail", args=[item.slug]) 25 | 26 | 27 | from django.utils.feedgenerator import Atom1Feed 28 | 29 | 30 | class AtomSiteNewsFeed(LatestPostsFeed): 31 | feed_type = Atom1Feed 32 | subtitle = LatestPostsFeed.description 33 | -------------------------------------------------------------------------------- /blog/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | from django.db import models 3 | 4 | STATUS = ((0, "Draft"), (1, "Publish")) 5 | 6 | 7 | class Post(models.Model): 8 | title = models.CharField(max_length=200, unique=True) 9 | slug = models.SlugField(max_length=200, unique=True) 10 | author = models.ForeignKey( 11 | User, on_delete=models.CASCADE, related_name="blog_posts" 12 | ) 13 | updated_on = models.DateTimeField(auto_now=True) 14 | content = models.TextField() 15 | created_on = models.DateTimeField(auto_now_add=True) 16 | status = models.IntegerField(choices=STATUS, default=0) 17 | 18 | class Meta: 19 | ordering = ["-created_on"] 20 | 21 | def __str__(self): 22 | return self.title 23 | 24 | def get_absolute_url(self): 25 | from django.urls import reverse 26 | 27 | return reverse("post_detail", kwargs={"slug": str(self.slug)}) 28 | 29 | 30 | class Comment(models.Model): 31 | post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments") 32 | name = models.CharField(max_length=80) 33 | email = models.EmailField() 34 | body = models.TextField() 35 | created_on = models.DateTimeField(auto_now_add=True) 36 | active = models.BooleanField(default=False) 37 | 38 | class Meta: 39 | ordering = ["created_on"] 40 | 41 | def __str__(self): 42 | return "Comment {} by {}".format(self.body, self.name) 43 | -------------------------------------------------------------------------------- /mysite/urls.py: -------------------------------------------------------------------------------- 1 | """mysite URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.conf import settings 17 | from django.conf.urls.static import static 18 | from django.contrib import admin 19 | from django.contrib.sitemaps.views import sitemap 20 | from django.urls import include, path 21 | import debug_toolbar 22 | 23 | from blog.sitemaps import PostSitemap 24 | 25 | sitemaps = { 26 | "posts": PostSitemap, 27 | } 28 | 29 | urlpatterns = [ 30 | path("admin/", admin.site.urls), 31 | path("", include("blog.urls"), name="blog-urls"), 32 | path("summernote/", include("django_summernote.urls")), 33 | path('__debug__/', include(debug_toolbar.urls)), 34 | path("sitemap.xml", sitemap, {"sitemaps": sitemaps}, name="sitemap"), 35 | ] 36 | 37 | if settings.DEBUG: 38 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 39 | -------------------------------------------------------------------------------- /blog/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import get_object_or_404, render 2 | from django.views import generic 3 | 4 | from .forms import CommentForm 5 | from .models import Post 6 | 7 | 8 | class PostList(generic.ListView): 9 | queryset = Post.objects.filter(status=1).order_by("-created_on") 10 | template_name = "index.html" 11 | paginate_by = 3 12 | 13 | 14 | # class PostDetail(generic.DetailView): 15 | # model = Post 16 | # template_name = 'post_detail.html' 17 | 18 | 19 | def post_detail(request, slug): 20 | template_name = "post_detail.html" 21 | post = get_object_or_404(Post, slug=slug) 22 | comments = post.comments.filter(active=True).order_by("-created_on") 23 | new_comment = None 24 | # Comment posted 25 | if request.method == "POST": 26 | comment_form = CommentForm(data=request.POST) 27 | if comment_form.is_valid(): 28 | 29 | # Create Comment object but don't save to database yet 30 | new_comment = comment_form.save(commit=False) 31 | # Assign the current post to the comment 32 | new_comment.post = post 33 | # Save the comment to the database 34 | new_comment.save() 35 | else: 36 | comment_form = CommentForm() 37 | 38 | return render( 39 | request, 40 | template_name, 41 | { 42 | "post": post, 43 | "comments": comments, 44 | "new_comment": new_comment, 45 | "comment_form": comment_form, 46 | }, 47 | ) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django_blog 2 | 3 | A blog application made on Django. 4 | 5 | ![ezgif com-video-to-gif](https://user-images.githubusercontent.com/38559396/55287491-12c4de80-53c7-11e9-8c6a-3f02b79ba9ca.gif) 6 | 7 | **Release 1.0** -Blog application made with Django, To learn more read https://djangocentral.com/building-a-blog-application-with-django 8 | 9 | **Release 2.0** - Comments system added. To learn more read - https://djangocentral.com/creating-comments-system-with-django/ 10 | 11 | ![Peek 2019-10-15 11-41](https://user-images.githubusercontent.com/38559396/66840502-c9fcfd80-ef85-11e9-827c-51fa4064a231.gif) 12 | 13 | **Release 2.1** - Pagination added, To learn more read - https://djangocentral.com/adding-pagination-with-django/

14 | Static assets management added, To learn more read - https://djangocentral.com/static-assets-in-django/

15 | 16 | Wysiwyg editor added, To learn more read - https://djangocentral.com/integrating-summernote-in-django/

17 | 18 | Sitemap added, To learn more read - https://djangocentral.com/creating-sitemaps-in-django/ 19 | 20 | Feeds added, To learn more read - https://djangocentral.com/creating-feeds-with-django/ 21 | 22 | Using Environment Variables In Django, To learn more read - https://djangocentral.com/environment-variables-in-django/ 23 | 24 | # Deployment 25 | 26 | How To Deploy Django App with Nginx, Gunicorn, PostgreSQL and Let’s Encrypt SSL on Ubuntu - https://djangocentral.com/deploy-django-with-nginx-gunicorn-postgresql-and-lets-encrypt-ssl-on-ubuntu/ 27 | 28 | # Contributors 29 | Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

30 | 31 | Please star the repo and feel free to make pull requests.

32 | Buy Me a Coffee at ko-fi.com 33 | -------------------------------------------------------------------------------- /blog/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.6 on 2019-10-13 10:21 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Post', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('title', models.CharField(max_length=200, unique=True)), 22 | ('slug', models.SlugField(max_length=200, unique=True)), 23 | ('updated_on', models.DateTimeField(auto_now=True)), 24 | ('content', models.TextField()), 25 | ('created_on', models.DateTimeField(auto_now_add=True)), 26 | ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Publish')], default=0)), 27 | ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='blog_posts', to=settings.AUTH_USER_MODEL)), 28 | ], 29 | options={ 30 | 'ordering': ['-created_on'], 31 | }, 32 | ), 33 | migrations.CreateModel( 34 | name='Comment', 35 | fields=[ 36 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 37 | ('name', models.CharField(max_length=80)), 38 | ('email', models.EmailField(max_length=254)), 39 | ('body', models.TextField()), 40 | ('created_on', models.DateTimeField(auto_now_add=True)), 41 | ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Publish')], default=0)), 42 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='blog.Post')), 43 | ], 44 | options={ 45 | 'ordering': ['created_on'], 46 | }, 47 | ), 48 | ] 49 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 |

Welcome to my awesome Blog

13 |

We Love Django As much as you do   14 |

15 |
16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 | 25 | 26 |
27 | {% for post in post_list %} 28 |
29 |
30 |

{{ post.title }}

31 |

{{ post.author }} | {{ post.created_on}}

32 | 33 |

{{post.content|safe|slice:":200" }}

34 | Read More → 35 |
36 | 37 |
38 | {% endfor %} 39 | 40 |
41 | {% block sidebar %} 42 | {% include 'sidebar.html' %} 43 | {% endblock sidebar %} 44 |
45 |
46 | {% if is_paginated %} 47 | 48 | 57 | 58 | 59 | {% endif %} 60 | {%endblock%} 61 | -------------------------------------------------------------------------------- /templates/post_detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} {% block content %} 2 | {% load crispy_forms_tags %} 3 | 4 |
5 |
6 |
7 |
8 |

{% block title %} {{ post.title }} {% endblock title %}

9 |

{{ post.author }} | {{ post.created_on }}

10 |

{{ post.content | safe }}

11 |
12 |
13 | {% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %} 14 | 15 |
16 |
17 | 18 | {% with comments.count as total_comments %} 19 |

{{ total_comments }} comments

20 | 21 |

22 | {% endwith %} {% for comment in comments %} 23 |

24 | 25 |
26 |

27 | {{ comment.name }} 28 | 29 | {{ comment.created_on }} 30 | 31 |

32 | {{ comment.body | linebreaks }} 33 |
34 | 35 | {% endfor %} 36 |
37 |
38 |
39 |
40 | {% if new_comment %} 41 | 44 | {% else %} 45 |

Leave a comment

46 |
47 | {{ comment_form | crispy }} 48 | {% csrf_token %} 49 | 50 |
51 | {% endif %} 52 |
53 |
54 |
55 |
56 | 57 | {% endblock content %} 58 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Django Central 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 51 | 52 | 53 | {% block content %} 54 | 55 | {% endblock content %} 56 | 57 | 58 |
59 |

Copyright © Django Central

60 |
61 | 62 | 65 | 68 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /mysite/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.1.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.1/ref/settings/ 11 | """ 12 | 13 | import os 14 | 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__))) 17 | TEMPLATES_DIR = os.path.join(BASE_DIR, "templates") 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = "0x!b#(1*cd73w$&azzc6p+essg7v=g80ls#z&xcx*mpemx&@9$" 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = [] 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | "django.contrib.admin", 36 | "django.contrib.auth", 37 | "django.contrib.contenttypes", 38 | "django.contrib.sessions", 39 | "django.contrib.messages", 40 | "django.contrib.staticfiles", 41 | "django.contrib.sitemaps", 42 | 'debug_toolbar', 43 | "blog", 44 | "crispy_forms", 45 | "django_summernote", 46 | ] 47 | 48 | 49 | 50 | 51 | MIDDLEWARE = [ 52 | "django.middleware.security.SecurityMiddleware", 53 | "django.contrib.sessions.middleware.SessionMiddleware", 54 | 'debug_toolbar.middleware.DebugToolbarMiddleware', 55 | "django.middleware.common.CommonMiddleware", 56 | "django.middleware.csrf.CsrfViewMiddleware", 57 | "django.contrib.auth.middleware.AuthenticationMiddleware", 58 | "django.contrib.messages.middleware.MessageMiddleware", 59 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 60 | ] 61 | 62 | ROOT_URLCONF = "mysite.urls" 63 | 64 | # Django Debug Toolbar https://django-debug-toolbar.readthedocs.io/en/latest/installation.html 65 | INTERNAL_IPS = [ 66 | '127.0.0.1', 67 | ] 68 | 69 | 70 | TEMPLATES = [ 71 | { 72 | "BACKEND": "django.template.backends.django.DjangoTemplates", 73 | "DIRS": [TEMPLATES_DIR], 74 | "APP_DIRS": True, 75 | "OPTIONS": { 76 | "context_processors": [ 77 | "django.template.context_processors.debug", 78 | "django.template.context_processors.request", 79 | "django.contrib.auth.context_processors.auth", 80 | "django.contrib.messages.context_processors.messages", 81 | ], 82 | }, 83 | }, 84 | ] 85 | 86 | WSGI_APPLICATION = "mysite.wsgi.application" 87 | 88 | 89 | # Database 90 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 91 | 92 | DATABASES = { 93 | "default": { 94 | "ENGINE": "django.db.backends.sqlite3", 95 | "NAME": os.path.join(BASE_DIR, "db.sqlite3"), 96 | } 97 | } 98 | 99 | 100 | # Password validation 101 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 102 | 103 | AUTH_PASSWORD_VALIDATORS = [ 104 | { 105 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 106 | }, 107 | { 108 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 109 | }, 110 | { 111 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 112 | }, 113 | { 114 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 115 | }, 116 | ] 117 | 118 | 119 | # Internationalization 120 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 121 | 122 | LANGUAGE_CODE = "en-us" 123 | 124 | TIME_ZONE = "UTC" 125 | 126 | USE_I18N = True 127 | 128 | USE_L10N = True 129 | 130 | USE_TZ = True 131 | 132 | 133 | # Static files (CSS, JavaScript, Images) 134 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 135 | 136 | STATIC_URL = "/static/" 137 | 138 | # Location of static files 139 | STATICFILES_DIRS = [ 140 | os.path.join(BASE_DIR, "static"), 141 | ] 142 | 143 | 144 | STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") 145 | 146 | 147 | CRISPY_TEMPLATE_PACK = "bootstrap4" 148 | 149 | 150 | # Media paths 151 | 152 | # Base url to serve media files 153 | MEDIA_URL = "/media/" 154 | 155 | # Path where media is stored 156 | MEDIA_ROOT = os.path.join(BASE_DIR, "media/") 157 | 158 | 159 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 160 | X_FRAME_OPTIONS = "SAMEORIGIN" 161 | --------------------------------------------------------------------------------