├── db.sqlite3
├── botora
├── __init__.py
├── asgi.py
├── wsgi.py
├── urls.py
└── settings.py
├── backup
├── blog
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ ├── 0001_initial.cpython-38.pyc
│ │ │ └── 0002_auto_20201026_0133.cpython-38.pyc
│ │ ├── 0002_auto_20201026_0133.py
│ │ └── 0001_initial.py
│ ├── tests.py
│ ├── apps.py
│ ├── __pycache__
│ │ ├── admin.cpython-38.pyc
│ │ ├── forms.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ ├── views.cpython-38.pyc
│ │ ├── models.cpython-38.pyc
│ │ └── __init__.cpython-38.pyc
│ ├── admin.py
│ ├── templates
│ │ ├── blog
│ │ │ ├── post_confirm_delete.html
│ │ │ ├── post_draft_list.html
│ │ │ ├── post_form.html
│ │ │ ├── comment_form.html
│ │ │ ├── about.html
│ │ │ ├── post_list.html
│ │ │ ├── post_detail.html
│ │ │ └── base.html
│ │ └── registration
│ │ │ └── login.html
│ ├── forms.py
│ ├── urls.py
│ ├── static
│ │ └── css
│ │ │ └── blog.css
│ ├── models.py
│ └── views.py
├── blog_site
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── urls.cpython-38.pyc
│ │ ├── wsgi.cpython-38.pyc
│ │ ├── __init__.cpython-38.pyc
│ │ └── settings.cpython-38.pyc
│ ├── asgi.py
│ ├── wsgi.py
│ ├── urls.py
│ └── settings.py
├── README.md
├── db.sqlite3
├── test.py
└── manage.py
├── tenants
├── __init__.py
├── migrations
│ ├── __init__.py
│ └── 0001_initial.py
├── tests.py
├── views.py
├── apps.py
├── admin.py
└── models.py
├── .gitignore
├── requirements.txt
├── settings
└── env.py
├── manage.py
└── .flake8
/db.sqlite3:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/botora/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backup/blog/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tenants/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backup/blog_site/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tenants/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backup/README.md:
--------------------------------------------------------------------------------
1 | # blog_django
2 |
--------------------------------------------------------------------------------
/backup/blog/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | botora/env.py
2 | /env
3 | __pycache__
4 | /media
5 |
--------------------------------------------------------------------------------
/backup/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/db.sqlite3
--------------------------------------------------------------------------------
/tenants/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/backup/blog/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/tenants/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/backup/blog/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class BlogConfig(AppConfig):
5 | name = 'blog'
6 |
--------------------------------------------------------------------------------
/backup/blog/__pycache__/admin.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/admin.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/__pycache__/forms.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/forms.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/__pycache__/views.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/views.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/__pycache__/models.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/models.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog_site/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog_site/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog_site/__pycache__/wsgi.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog_site/__pycache__/wsgi.cpython-38.pyc
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==5.1.5
2 | psycopg2-binary
3 | flake8
4 | djangorestframework==3.15.2
5 | djangorestframework-simplejwt
6 | django-tenants
7 |
--------------------------------------------------------------------------------
/backup/blog_site/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog_site/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog_site/__pycache__/settings.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog_site/__pycache__/settings.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from blog.models import Post, Comment
3 |
4 | admin.site.register(Post)
5 | admin.site.register(Comment)
6 |
--------------------------------------------------------------------------------
/backup/blog/migrations/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/migrations/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/blog/migrations/__pycache__/0001_initial.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/migrations/__pycache__/0001_initial.cpython-38.pyc
--------------------------------------------------------------------------------
/tenants/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class TenantsConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'tenants'
7 |
--------------------------------------------------------------------------------
/backup/blog/migrations/__pycache__/0002_auto_20201026_0133.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rkshaon/botora/HEAD/backup/blog/migrations/__pycache__/0002_auto_20201026_0133.cpython-38.pyc
--------------------------------------------------------------------------------
/backup/test.py:
--------------------------------------------------------------------------------
1 | import os
2 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blog_site.settings')
3 |
4 | import django
5 | django.setup()
6 |
7 | from django.utils import timezone
8 |
9 | now = timezone.now()
10 | print(now)
11 |
--------------------------------------------------------------------------------
/tenants/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django_tenants.admin import TenantAdminMixin
3 |
4 | from tenants.models import Client
5 |
6 |
7 | @admin.register(Client)
8 | class ClientAdmin(TenantAdminMixin, admin.ModelAdmin):
9 | list_display = ('name', 'paid_until')
10 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/post_confirm_delete.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 |
8 | {% endblock %}
9 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/post_draft_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 | {% for post in posts %}
4 |
5 |
created: {{ post.created_date|date:"d-m-Y"}}
6 |
7 |
{{ post.text|truncatechars:200 }}
8 |
9 | {% endfor %}
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/post_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 | New Post
4 |
9 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/comment_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 | New Comment
4 |
9 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/botora/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for botora project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'botora.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/botora/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for botora 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/4.2/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', 'botora.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/backup/blog_site/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for blog_site project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blog_site.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/backup/blog_site/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for blog_site 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/3.0/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', 'blog_site.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/tenants/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django_tenants.models import TenantMixin, DomainMixin
3 |
4 |
5 | class Client(TenantMixin):
6 | name = models.CharField(max_length=100)
7 | paid_until = models.DateField()
8 | on_trial = models.BooleanField()
9 | created_on = models.DateField(auto_now_add=True)
10 | # default true, schema will be automatically created
11 | # and synced when it is saved
12 | auto_create_schema = True
13 |
14 |
15 | class Domain(DomainMixin):
16 | pass
17 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/about.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 | About the Blog
4 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5 | {% endblock %}
6 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/post_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 |
4 | {% for post in post_list %}
5 |
16 | {% endfor %}
17 |
18 | {% endblock %}
19 |
--------------------------------------------------------------------------------
/settings/env.py:
--------------------------------------------------------------------------------
1 | # Database Settings
2 | DATABASES_SETTINGS = {
3 | 'default': {
4 | 'ENGINE': 'django.db.backends.postgresql_psycopg2',
5 | 'NAME': 'db_name',
6 | 'USER': 'db_username',
7 | 'PASSWORD': 'db_password',
8 | 'HOST': 'localhost',
9 | 'PORT': '5432',
10 | }
11 | }
12 |
13 | ALLOWED_HOSTS_SETTINGS = []
14 |
15 | SECRET_KEY_SETTINGS = 'projectssecretekey'
16 | CORS_ALLOWED_ORIGINS_SETTINGS = [
17 | "http://localhost:8080",
18 | "http://127.0.0.1:8080",
19 | ]
20 |
21 | X_FRAME_OPTIONS_SETTINGS = 'ALLOW-FROM http://localhost:8080'
22 |
23 | FRONTEND_BASE_URL_SETTINGS = ''
24 |
--------------------------------------------------------------------------------
/backup/blog/templates/registration/login.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 |
3 | {% block content %}
4 |
5 |
Please Login:
6 |
(Must be SuperUser, please check with the site admin)
7 | {% if form.errors %}
8 |
Your username or password didn't match!
9 |
Please try again
10 | {% endif %}
11 |
17 |
18 | {% endblock %}
19 |
--------------------------------------------------------------------------------
/backup/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blog_site.settings')
9 | try:
10 | from django.core.management import execute_from_command_line
11 | except ImportError as exc:
12 | raise ImportError(
13 | "Couldn't import Django. Are you sure it's installed and "
14 | "available on your PYTHONPATH environment variable? Did you "
15 | "forget to activate a virtual environment?"
16 | ) from exc
17 | execute_from_command_line(sys.argv)
18 |
19 |
20 | if __name__ == '__main__':
21 | main()
22 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'botora.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
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
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | # it's not a bug that we aren't using all of hacking, ignore:
3 | # F812: list comprehension redefines ...
4 | # H101: Use TODO(NAME)
5 | # H202: assertRaises Exception too broad
6 | # H233: Python 3.x incompatible use of print operator
7 | # H301: one import per line
8 | # H306: imports not in alphabetical order (time, os)
9 | # H401: docstring should not start with a space
10 | # H403: multi line docstrings should end on a new line
11 | # H404: multi line docstring should start without a leading new line
12 | # H405: multi line docstring summary not separated with an empty line
13 | # H501: Do not use self.__dict__ for string formatting
14 | ; ignore = F812,H101,H202,H233,H301,H306,H401,H403,H404,H405,H501
15 | exclude = __pycache__,tests.py,migrations,env,env.py
--------------------------------------------------------------------------------
/backup/blog/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from blog.models import Post, Comment
3 |
4 | class PostForm(forms.ModelForm):
5 | class Meta():
6 | model = Post
7 | fields = ('author', 'title', 'text')
8 | widgets = {
9 | 'title': forms.TextInput(attrs={'class': 'textinputclass'}),
10 | 'text': forms.Textarea(attrs={'class': 'editable medium-editor-textarea postcontent'}),
11 | }
12 |
13 | class CommentForm(forms.ModelForm):
14 | class Meta():
15 | model = Comment
16 | fields = ('author', 'text')
17 | widgets = {
18 | 'author': forms.TextInput(attrs={'class': 'textinputclass'}),
19 | 'text': forms.Textarea(attrs={'class': 'editable medium-editor-textarea'}),
20 | }
21 |
--------------------------------------------------------------------------------
/backup/blog/migrations/0002_auto_20201026_0133.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-10-25 19:33
2 |
3 | import datetime
4 | from django.db import migrations, models
5 | from django.utils.timezone import utc
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('blog', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='comment',
17 | name='create_date',
18 | field=models.DateTimeField(default=datetime.datetime(2020, 10, 25, 19, 33, 17, 291781, tzinfo=utc)),
19 | ),
20 | migrations.AlterField(
21 | model_name='post',
22 | name='created_date',
23 | field=models.DateTimeField(default=datetime.datetime(2020, 10, 25, 19, 33, 17, 290782, tzinfo=utc)),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/botora/urls.py:
--------------------------------------------------------------------------------
1 | """
2 | URL configuration for botora project.
3 |
4 | The `urlpatterns` list routes URLs to views. For more information please see:
5 | https://docs.djangoproject.com/en/4.2/topics/http/urls/
6 | Examples:
7 | Function views
8 | 1. Add an import: from my_app import views
9 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
10 | Class-based views
11 | 1. Add an import: from other_app.views import Home
12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
13 | Including another URLconf
14 | 1. Import the include() function: from django.urls import include, path
15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
16 | """
17 | from django.contrib import admin
18 | from django.urls import path
19 |
20 | urlpatterns = [
21 | path('admin/', admin.site.urls),
22 | ]
23 |
--------------------------------------------------------------------------------
/backup/blog/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, re_path
2 | from blog import views
3 |
4 | urlpatterns = [
5 | path('', views.PostListView.as_view(), name='post_list'),
6 | path('about', views.AboutView.as_view(), name='about'),
7 | re_path(r'^post/(?P\d+)$', views.PostDetailView.as_view(), name='post_detail'),
8 | # url(r'post/(?P\d+)$')
9 | # https://docs.djangoproject.com/en/2.0/topics/http/urls/
10 | path('post/new/', views.CreatePostView.as_view(), name='post_new'),
11 | re_path(r'^post/(?P\d+)/edit/$', views.PostUpdateView.as_view(), name='post_edit'),
12 | re_path(r'^post/(?P\d+)/remove/$', views.PostDeleteView.as_view(), name='post_remove'),
13 | path('drafts/', views.DraftListView.as_view(), name='post_draft_list'),
14 | re_path(r'^post/(?P\d+)/comment/$', views.add_comment_to_post, name='add_comment_to_post'),
15 | re_path(r'^comment/(?P\d+)/approve/$', views.comment_approve, name='comment_approve'),
16 | re_path(r'^comment/(?P\d+)/remove/$', views.comment_remove, name='comment_remove'),
17 | re_path(r'^post/(?P\d+)/publish/$', views.post_publish, name='post_publish'),
18 | ]
19 |
--------------------------------------------------------------------------------
/backup/blog_site/urls.py:
--------------------------------------------------------------------------------
1 | """blog_site URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.0/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.contrib import admin
17 | from django.urls import path, include
18 | # from django.contrib.auth import views
19 | # from django.contrib.auth import views as auth_views
20 | from django.contrib.auth.views import LoginView
21 | from django.contrib.auth.views import LogoutView
22 |
23 | urlpatterns = [
24 | path('admin/', admin.site.urls),
25 | path('', include('blog.urls')),
26 | # url(r'^accounts/login/$', views.login, name='login'),
27 | path('accounts/login/', LoginView.as_view(), name='login'),
28 | path('accounts/logout', LogoutView.as_view(), name='logout', kwargs={'next_page': '/'}),
29 | ]
30 |
--------------------------------------------------------------------------------
/backup/blog/static/css/blog.css:
--------------------------------------------------------------------------------
1 | .techfont{
2 | font-family: 'Russo One', sans-serif;
3 | font-size: 1.5em;
4 | margin-bottom: 10px;
5 | }
6 | .bigbrand{
7 | font-size: 1.5em;
8 | }
9 | .centerstage{
10 | margin-left: auto;
11 | margin-right: auto;
12 | }
13 | .postdate{
14 | text-align: center;
15 | }
16 | .posttitle{
17 | font-family: 'Russo One', sans-serif;
18 | font-size: 3em;
19 | text-align: center;
20 | }
21 | .postcontent{
22 | font-family: 'Montserrat';
23 | font-size: 1.5em;
24 | }
25 | .btn-comment{
26 | position: absolute;
27 | right: 0px;
28 | }
29 | /* Color Changer */
30 | .loader {
31 | filter:hue-rotate(0deg);
32 | color:linear-gradient(45deg,#0f8,#08f);
33 | animation:hue 10000ms infinite linear;
34 |
35 | }
36 | @keyframes spinify {
37 | 0% {
38 | transform: translate(0px,0px);
39 |
40 | }
41 | 33% {
42 | transform: translate(0px,24px);
43 | border-radius:100%;
44 | width:10px;
45 | height:10px;
46 |
47 | }
48 | 66% {
49 | transform:translate(0px,-16px);
50 | }
51 |
52 | 88% {
53 | transform:translate(0px,4px);
54 |
55 | }
56 | 100% {
57 | transform:translate(0px,0px);
58 | }
59 | }
60 | @keyframes hue{
61 | 0%{filter: hue-rotate(0deg);}
62 | 100%{filter:hue-rotate(360deg);}
63 |
64 | }
65 | /* Font */
66 | /* font-family: 'Montserrat', sans-serif;
67 | font-family: 'Russo One', sans-serif; */
68 |
--------------------------------------------------------------------------------
/backup/blog/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.utils import timezone
3 | # from django.utils.timezone.now import timezone
4 | # from django.core.urlresolver import reverse
5 | from django.urls import reverse
6 |
7 | class Post(models.Model):
8 | author = models.ForeignKey('auth.user', on_delete=models.CASCADE)
9 | title = models.CharField(max_length=200)
10 | text = models.TextField()
11 | created_date = models.DateTimeField(default=timezone.now())
12 | # create_date = models.DateTimeField(default=django.utils.timezone.now)
13 | published_date = models.DateTimeField(blank=True, null=True)
14 |
15 | def publish(self):
16 | self.published_date = timezone.now()
17 | self.save()
18 |
19 | def approve_comments(self):
20 | return self.comments.filter(approve_comment=True)
21 |
22 | def get_absolute_url(self):
23 | return reverse('post_detail', kwargs={'pk': self.pk})
24 |
25 | def __str__(self):
26 | return self.title
27 |
28 | class Comment(models.Model):
29 | post = models.ForeignKey('blog.Post', related_name='comments', on_delete=models.CASCADE)
30 | author = models.CharField(max_length=200)
31 | text = models.TextField()
32 | create_date = models.DateTimeField(default=timezone.now())
33 | # create_date = models.DateTimeField(default=django.utils.timezone.now)
34 | approve_comment = models.BooleanField(default=False)
35 |
36 | def approve(self):
37 | self.approve_comment = True
38 | self.save()
39 |
40 | def get_absolute_url(self):
41 | return reverse('post_list')
42 | def __str__(self):
43 | return self.text
44 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/post_detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% block content %}
3 | {{ post.title }}
4 | {% if post.published_date %}
5 |
6 | {{ post.published_date }}
7 |
8 | {% else %}
9 | Publish
10 | {% endif %}
11 | {{ post.text|safe|linebreaksbr }}
12 | {% if user.is_authenticated %}
13 |
14 |
15 |
16 |
17 |
18 |
19 | {% endif %}
20 |
21 |
22 |
23 | {% for comment in post.comments.all %}
24 |
25 | {% if user.is_authenticated or comment.approved_comment %}
26 | {{ comment.created_date }}
27 | {% if not comment.approved_comment %}
28 |
29 |
30 |
31 |
32 |
33 |
34 | {% endif %}
35 |
{{ comment.text|safe|linebreaks }}
36 |
Posted by: {{ comment.author }}
37 | {% endif %}
38 | {% empty %}
39 |
No comments
40 | {% endfor %}
41 |
42 | {% endblock %}
43 |
--------------------------------------------------------------------------------
/tenants/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.1.5 on 2025-02-17 12:23
2 |
3 | import django.db.models.deletion
4 | import django_tenants.postgresql_backend.base
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Client',
18 | fields=[
19 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('schema_name', models.CharField(db_index=True, max_length=63, unique=True, validators=[django_tenants.postgresql_backend.base._check_schema_name])),
21 | ('name', models.CharField(max_length=100)),
22 | ('paid_until', models.DateField()),
23 | ('on_trial', models.BooleanField()),
24 | ('created_on', models.DateField(auto_now_add=True)),
25 | ],
26 | options={
27 | 'abstract': False,
28 | },
29 | ),
30 | migrations.CreateModel(
31 | name='Domain',
32 | fields=[
33 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
34 | ('domain', models.CharField(db_index=True, max_length=253, unique=True)),
35 | ('is_primary', models.BooleanField(db_index=True, default=True)),
36 | ('tenant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domains', to='tenants.client')),
37 | ],
38 | options={
39 | 'abstract': False,
40 | },
41 | ),
42 | ]
43 |
--------------------------------------------------------------------------------
/backup/blog/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-07-25 22:29
2 |
3 | import datetime
4 | from django.conf import settings
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 | from django.utils.timezone import utc
8 |
9 |
10 | class Migration(migrations.Migration):
11 |
12 | initial = True
13 |
14 | dependencies = [
15 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16 | ]
17 |
18 | operations = [
19 | migrations.CreateModel(
20 | name='Post',
21 | fields=[
22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
23 | ('title', models.CharField(max_length=200)),
24 | ('text', models.TextField()),
25 | ('created_date', models.DateTimeField(default=datetime.datetime(2020, 7, 25, 22, 29, 39, 965855, tzinfo=utc))),
26 | ('published_date', models.DateTimeField(blank=True, null=True)),
27 | ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
28 | ],
29 | ),
30 | migrations.CreateModel(
31 | name='Comment',
32 | fields=[
33 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
34 | ('author', models.CharField(max_length=200)),
35 | ('text', models.TextField()),
36 | ('create_date', models.DateTimeField(default=datetime.datetime(2020, 7, 25, 22, 29, 39, 969854, tzinfo=utc))),
37 | ('approve_comment', models.BooleanField(default=False)),
38 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='blog.Post')),
39 | ],
40 | ),
41 | ]
42 |
--------------------------------------------------------------------------------
/backup/blog/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, get_object_or_404, redirect
2 | from django.contrib.auth.decorators import login_required
3 | from django.contrib.auth.mixins import LoginRequiredMixin
4 | from django.urls import reverse_lazy
5 | from django.utils import timezone
6 | from django.views.generic import (TemplateView, ListView, DetailView, CreateView, UpdateView, DeleteView)
7 | from blog.forms import PostForm, CommentForm
8 | from blog.models import Post, Comment
9 |
10 | class AboutView(TemplateView):
11 | template_name = 'about.html'
12 |
13 | class PostListView(ListView):
14 | model = Post
15 |
16 | def get_queryset(self):
17 | return Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
18 |
19 | class PostDetailView(DetailView):
20 | model = Post
21 |
22 | class CreatePostView(LoginRequiredMixin, CreateView):
23 | login_url = '/login/'
24 | redirect_field_name = 'blog/post_detail.html'
25 | form_class = PostForm
26 | model = Post
27 |
28 | class PostUpdateView(LoginRequiredMixin, UpdateView):
29 | login_url = '/login/'
30 | redirect_field_name = 'blog/post_detail.html'
31 | form_class = PostForm
32 | model = Post
33 |
34 | class PostDeleteView(LoginRequiredMixin, DeleteView):
35 | model = Post
36 | success_url = reverse_lazy('post_list')
37 |
38 | class DraftListView(LoginRequiredMixin, ListView):
39 | login_url = '/login/'
40 | redirect_field_name = 'blog/post_list.html'
41 | model = Post
42 |
43 | def get_queryset(self):
44 | return Post.objects.filter(published_date__isnull=True).order_by('created_date')
45 |
46 | ################
47 | ################
48 | @login_required
49 | def post_publish(request, pk):
50 | post = get_object_or_404(Post, pk=pk)
51 | post.publish()
52 | return redirect('post_detail', pk=pk)
53 |
54 | @login_required
55 | def add_comment_to_post(request, pk):
56 | post = get_object_or_404(Post, pk=pk)
57 |
58 | if request.method == 'POST':
59 | form = CommentForm(request.POST)
60 | if form.is_valid():
61 | comment = form.save(commit=False)
62 | comment.post = post
63 | comment.save()
64 | return redirect('post_detail', pk=post.pk)
65 | else:
66 | form = CommentForm()
67 | return render(request, 'blog/comment_form.html', {'form': form})
68 |
69 | @login_required
70 | def comment_approve(request, pk):
71 | comment = get_object_or_404(Comment, pk=pk)
72 | comment.approve()
73 | return redirect('post_detail', pk=comment.post.pk)
74 |
75 | @login_required
76 | def comment_remove(request, pk):
77 | comment = get_object_or_404(Comment, pk=pk)
78 | post_pk = comment.post.pk
79 | comment.delete()
80 | return redirect('post_detail', pk=post_pk)
81 |
--------------------------------------------------------------------------------
/botora/settings.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from botora.env import DATABASES_SETTINGS
4 | from botora.env import SECRET_KEY_SETTINGS
5 | from botora.env import ALLOWED_HOSTS_SETTINGS
6 |
7 |
8 | BASE_DIR = Path(__file__).resolve().parent.parent
9 | SECRET_KEY = SECRET_KEY_SETTINGS
10 | DEBUG = True
11 | ALLOWED_HOSTS = ALLOWED_HOSTS_SETTINGS
12 |
13 | SHARED_APPS = (
14 | 'django_tenants',
15 | 'tenants',
16 | 'django.contrib.admin',
17 | 'django.contrib.auth',
18 | 'django.contrib.contenttypes',
19 | 'django.contrib.sessions',
20 | 'django.contrib.messages',
21 | 'django.contrib.staticfiles',
22 | )
23 | TENANT_APPS = (
24 | 'tenants',
25 | )
26 | INSTALLED_APPS = list(SHARED_APPS) + [
27 | app for app in TENANT_APPS if app not in SHARED_APPS
28 | ]
29 |
30 | DATABASE_ROUTERS = (
31 | 'django_tenants.routers.TenantSyncRouter',
32 | )
33 |
34 | MIDDLEWARE = [
35 | 'django_tenants.middleware.TenantMiddleware',
36 | 'django.middleware.security.SecurityMiddleware',
37 | 'django.contrib.sessions.middleware.SessionMiddleware',
38 | 'django.middleware.common.CommonMiddleware',
39 | 'django.middleware.csrf.CsrfViewMiddleware',
40 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
41 | 'django.contrib.messages.middleware.MessageMiddleware',
42 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
43 | ]
44 |
45 | ROOT_URLCONF = 'botora.urls'
46 |
47 | TEMPLATES = [
48 | {
49 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
50 | 'DIRS': [],
51 | 'APP_DIRS': True,
52 | 'OPTIONS': {
53 | 'context_processors': [
54 | 'django.template.context_processors.debug',
55 | 'django.template.context_processors.request',
56 | 'django.contrib.auth.context_processors.auth',
57 | 'django.contrib.messages.context_processors.messages',
58 | ],
59 | },
60 | },
61 | ]
62 |
63 | WSGI_APPLICATION = 'botora.wsgi.application'
64 | DATABASES = DATABASES_SETTINGS
65 | TENANT_MODEL = "tenants.Client"
66 | TENANT_DOMAIN_MODEL = "tenants.Domain"
67 |
68 | AUTH_PASSWORD_VALIDATORS = [
69 | {
70 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', # noqa
71 | },
72 | {
73 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', # noqa
74 | },
75 | {
76 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', # noqa
77 | },
78 | {
79 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', # noqa
80 | },
81 | ]
82 |
83 | LANGUAGE_CODE = 'en-us'
84 | TIME_ZONE = 'UTC'
85 | USE_I18N = True
86 | USE_TZ = True
87 | STATIC_URL = 'static/'
88 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
89 |
--------------------------------------------------------------------------------
/backup/blog/templates/blog/base.html:
--------------------------------------------------------------------------------
1 |
2 | {% load static %}
3 |
4 |
5 |
6 | Blog
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | {% block content %}
65 | {% endblock %}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/backup/blog_site/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for blog_site project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.0.7.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.0/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 | TEMPLATE_DIR = os.path.join(BASE_DIR, 'blog/templates/blog')
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | # SECRET_KEY = 'xfb&18+9th6h51+7j#vu2gbu_a9l^*e!gewqvct4lm(r_svkr7'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'blog',
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | 'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'blog_site.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [TEMPLATE_DIR,],
59 | 'APP_DIRS': True,
60 | 'OPTIONS': {
61 | 'context_processors': [
62 | 'django.template.context_processors.debug',
63 | 'django.template.context_processors.request',
64 | 'django.contrib.auth.context_processors.auth',
65 | 'django.contrib.messages.context_processors.messages',
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = 'blog_site.wsgi.application'
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
76 |
77 | DATABASES = {
78 | 'default': {
79 | 'ENGINE': 'django.db.backends.sqlite3',
80 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91 | },
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.0/topics/i18n/
106 |
107 | LANGUAGE_CODE = 'en-us'
108 |
109 | TIME_ZONE = 'UTC'
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.0/howto/static-files/
120 |
121 | STATIC_URL = '/static/'
122 | STATIC_ROOT = os.path.join(BASE_DIR, 'static')
123 |
124 | LOGIN_REDIRECT_URL = '/'
125 |
--------------------------------------------------------------------------------