├── base
├── __init__.py
├── migrations
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-39.pyc
│ │ ├── 0001_initial.cpython-39.pyc
│ │ ├── 0010_product_user.cpython-39.pyc
│ │ ├── 0005_website_url_name.cpython-39.pyc
│ │ ├── 0011_user_purchased.cpython-39.pyc
│ │ ├── 0002_auto_20211004_1727.cpython-39.pyc
│ │ ├── 0002_auto_20211006_1651.cpython-39.pyc
│ │ ├── 0003_alter_website_user.cpython-39.pyc
│ │ ├── 0003_auto_20211006_1625.cpython-39.pyc
│ │ ├── 0004_alter_product_name.cpython-39.pyc
│ │ ├── 0005_alter_website_name.cpython-39.pyc
│ │ ├── 0006_alter_website_name.cpython-39.pyc
│ │ ├── 0007_auto_20211016_1433.cpython-39.pyc
│ │ ├── 0008_auto_20211016_1444.cpython-39.pyc
│ │ ├── 0009_auto_20211016_1448.cpython-39.pyc
│ │ └── 0002_alter_website_products.cpython-39.pyc
│ ├── 0011_user_purchased.py
│ ├── 0004_alter_product_name.py
│ ├── 0005_alter_website_name.py
│ ├── 0006_alter_website_name.py
│ ├── 0002_alter_website_products.py
│ ├── 0008_auto_20211016_1444.py
│ ├── 0003_alter_website_user.py
│ ├── 0010_product_user.py
│ ├── 0007_auto_20211016_1433.py
│ ├── 0009_auto_20211016_1448.py
│ └── 0001_initial.py
├── tests.py
├── __pycache__
│ ├── apps.cpython-39.pyc
│ ├── urls.cpython-39.pyc
│ ├── admin.cpython-39.pyc
│ ├── forms.cpython-39.pyc
│ ├── models.cpython-39.pyc
│ ├── views.cpython-39.pyc
│ └── __init__.cpython-39.pyc
├── apps.py
├── admin.py
├── templates
│ ├── home.html
│ ├── create-website.html
│ ├── products
│ │ ├── create.html
│ │ ├── update.html
│ │ └── info.html
│ ├── update-website.html
│ ├── dashboard.html
│ ├── website
│ │ └── base.html
│ ├── base.html
│ └── website-info.html
├── forms.py
├── urls.py
├── models.py
└── views.py
├── src
├── __init__.py
├── __pycache__
│ ├── urls.cpython-39.pyc
│ ├── wsgi.cpython-39.pyc
│ ├── __init__.cpython-39.pyc
│ └── settings.cpython-39.pyc
├── asgi.py
├── wsgi.py
├── urls.py
└── settings.py
├── authentication
├── __init__.py
├── migrations
│ ├── __init__.py
│ └── __pycache__
│ │ └── __init__.cpython-39.pyc
├── models.py
├── admin.py
├── tests.py
├── __pycache__
│ ├── apps.cpython-39.pyc
│ ├── urls.cpython-39.pyc
│ ├── admin.cpython-39.pyc
│ ├── forms.cpython-39.pyc
│ ├── models.cpython-39.pyc
│ ├── views.cpython-39.pyc
│ ├── __init__.cpython-39.pyc
│ └── decorators.cpython-39.pyc
├── apps.py
├── templates
│ ├── email_sent.html
│ ├── signup.html
│ ├── activate.html
│ ├── registration
│ │ ├── account.html
│ │ ├── password.html
│ │ ├── delete-account.html
│ │ └── login.html
│ └── payments
│ │ └── purchase.html
├── urls.py
├── decorators.py
├── forms.py
└── views.py
├── .gitignore
├── requirements.txt
├── README.md
├── password reset
└── registration
│ ├── password_reset_done.html
│ ├── password_reset_complete.html
│ ├── password_reset_form.html
│ └── password_reset_confirm.html
└── manage.py
/base/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/authentication/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/base/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/authentication/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/base/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/authentication/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/authentication/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/authentication/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Scripts/
2 | Include/
3 | Lib/
4 | media/
5 | db.sqlite3
6 | pyvenv.cfg
7 | .vscode/
8 | .env
9 | staticfiles/
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.4.1
2 | Django==3.2.7
3 | Pillow==8.3.2
4 | pytz==2021.3
5 | sqlparse==0.4.2
6 | python-dotenv==0.19.0
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Affiliate Website Builder
2 |
3 | A simple affiliate website builder with,
4 | - Django
5 | - Bootstrap
6 | - Javascript
--------------------------------------------------------------------------------
/base/__pycache__/apps.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/apps.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/urls.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/urls.cpython-39.pyc
--------------------------------------------------------------------------------
/src/__pycache__/urls.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/src/__pycache__/urls.cpython-39.pyc
--------------------------------------------------------------------------------
/src/__pycache__/wsgi.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/src/__pycache__/wsgi.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/admin.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/admin.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/forms.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/forms.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/models.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/models.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/views.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/views.cpython-39.pyc
--------------------------------------------------------------------------------
/src/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/src/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/src/__pycache__/settings.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/src/__pycache__/settings.cpython-39.pyc
--------------------------------------------------------------------------------
/base/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/apps.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/apps.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/urls.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/urls.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/admin.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/admin.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/forms.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/forms.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/models.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/models.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/views.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/views.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/__pycache__/decorators.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/__pycache__/decorators.cpython-39.pyc
--------------------------------------------------------------------------------
/base/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class BaseConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'base'
7 |
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0001_initial.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0001_initial.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/migrations/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/authentication/migrations/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0010_product_user.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0010_product_user.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0005_website_url_name.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0005_website_url_name.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0011_user_purchased.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0011_user_purchased.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0002_auto_20211004_1727.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0002_auto_20211004_1727.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0002_auto_20211006_1651.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0002_auto_20211006_1651.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0003_alter_website_user.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0003_alter_website_user.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0003_auto_20211006_1625.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0003_auto_20211006_1625.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0004_alter_product_name.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0004_alter_product_name.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0005_alter_website_name.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0005_alter_website_name.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0006_alter_website_name.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0006_alter_website_name.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0007_auto_20211016_1433.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0007_auto_20211016_1433.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0008_auto_20211016_1444.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0008_auto_20211016_1444.cpython-39.pyc
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0009_auto_20211016_1448.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0009_auto_20211016_1448.cpython-39.pyc
--------------------------------------------------------------------------------
/authentication/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AuthenticationConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'authentication'
7 |
--------------------------------------------------------------------------------
/base/migrations/__pycache__/0002_alter_website_products.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nepul321/Affiliate-website-builder/HEAD/base/migrations/__pycache__/0002_alter_website_products.cpython-39.pyc
--------------------------------------------------------------------------------
/base/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import (
3 | Website,
4 | Product,
5 | User
6 | )
7 |
8 | def register(model):
9 | admin.site.register(model)
10 |
11 | register(Website)
12 | register(Product)
13 | register(User)
--------------------------------------------------------------------------------
/password reset/registration/password_reset_done.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Email sent
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
Email with instructions sent
9 | We send you an email with some instructions to reset the password.
10 | {% endblock %}
--------------------------------------------------------------------------------
/authentication/templates/email_sent.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Verify your email
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Verify your email
10 |
We have send you a verification email
11 |
12 | {% endblock content %}
--------------------------------------------------------------------------------
/password reset/registration/password_reset_complete.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Password reset completed
5 | {% endblock %}
6 |
7 | {% block content %}
8 | Password reset completed
9 | You have reset your password successfully
10 | Login
11 | {% endblock %}
--------------------------------------------------------------------------------
/base/templates/home.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}
4 | Affiliate Website builder
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 | {% if user.is_authenticated %}
10 |
Hello {{ user.username }}!
11 | {% else %}
12 | Hello Visitor
13 | {% endif %}
14 |
15 | {% endblock content %}
--------------------------------------------------------------------------------
/authentication/templates/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}
4 | Sign up
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Sign up
10 |
15 |
16 |
17 | {% endblock content %}
--------------------------------------------------------------------------------
/src/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for src 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.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', 'src.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/src/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for src 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.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', 'src.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/base/templates/create-website.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Create website
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Create website
10 |
15 |
16 | {% endblock content %}
--------------------------------------------------------------------------------
/base/templates/products/create.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Create a product
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Create product
10 |
15 |
16 | {% endblock content %}
--------------------------------------------------------------------------------
/authentication/templates/activate.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Account activated
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
10 |
11 |
Congrats We have activated your account
12 |
Login
13 |
14 |
15 |
16 | {% endblock content %}
--------------------------------------------------------------------------------
/base/templates/products/update.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Update {{ product.name }}
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Update {{ product.name }}
10 |
15 |
16 | {% endblock content %}
--------------------------------------------------------------------------------
/base/migrations/0011_user_purchased.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-23 18:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0010_product_user'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='user',
15 | name='purchased',
16 | field=models.BooleanField(default=False),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/migrations/0004_alter_product_name.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 00:19
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0003_alter_website_user'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='product',
15 | name='name',
16 | field=models.CharField(max_length=1000),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/migrations/0005_alter_website_name.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 00:46
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0004_alter_product_name'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='website',
15 | name='name',
16 | field=models.CharField(max_length=255),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/migrations/0006_alter_website_name.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 00:46
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0005_alter_website_name'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='website',
15 | name='name',
16 | field=models.CharField(max_length=255, unique=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/migrations/0002_alter_website_products.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-15 23:33
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='website',
15 | name='products',
16 | field=models.ManyToManyField(blank=True, related_name='website_products', to='base.Product'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/migrations/0008_auto_20211016_1444.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 18:44
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0007_auto_20211016_1433'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='website',
15 | name='header_text',
16 | ),
17 | migrations.RemoveField(
18 | model_name='website',
19 | name='header_title',
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/password reset/registration/password_reset_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Reset password
5 | {% endblock %}
6 |
7 | {% block content %}
8 | Reset password
9 | Enter your email below so we can send you the instructions to reset your password
10 |
15 |
19 | {% endblock %}
--------------------------------------------------------------------------------
/authentication/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from .views import (
3 | SignupView,
4 | PasswordView,
5 | AccountView,
6 | UserDeleteView,
7 | ActivateAccountView,
8 | purchaseview
9 | )
10 |
11 | urlpatterns = [
12 | path('sign-up/', SignupView, name='signup'),
13 | path('password/', PasswordView, name="password"),
14 | path('account/', AccountView, name="account"),
15 | path('delete-account/', UserDeleteView, name="delete-user"),
16 | path('activate-account//', ActivateAccountView, name="activate"),
17 | path('purchase/', purchaseview, name="purchase"),
18 | ]
19 |
--------------------------------------------------------------------------------
/base/templates/products/info.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | {{ product.name }}
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
10 |
11 |
12 |

13 |
{{ product.name }}
14 |
{{ product.description|safe }}
15 |
16 |
17 |
18 |
Back to dashboard
19 |
20 | {% endblock content %}
--------------------------------------------------------------------------------
/base/migrations/0003_alter_website_user.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 00:12
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 | ('base', '0002_alter_website_products'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='website',
16 | name='user',
17 | field=models.ForeignKey(default='', on_delete=django.db.models.deletion.CASCADE, to='base.user'),
18 | preserve_default=False,
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/base/migrations/0010_product_user.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 19:12
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 | ('base', '0009_auto_20211016_1448'),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name='product',
16 | name='user',
17 | field=models.ForeignKey(blank=True, default='', on_delete=django.db.models.deletion.CASCADE, to='base.user'),
18 | preserve_default=False,
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/password reset/registration/password_reset_confirm.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Password reset confirm
5 | {% endblock %}
6 |
7 | {% block content %}
8 | Enter your new password
9 |
14 |
20 | {% endblock %}
--------------------------------------------------------------------------------
/base/migrations/0007_auto_20211016_1433.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 18:33
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0006_alter_website_name'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='website',
15 | name='header_text',
16 | field=models.TextField(default=''),
17 | ),
18 | migrations.AddField(
19 | model_name='website',
20 | name='header_title',
21 | field=models.CharField(default='', max_length=255),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/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', 'src.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 |
--------------------------------------------------------------------------------
/authentication/templates/registration/account.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Account settings
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Account settings
10 |
15 |
16 |
19 |
20 |
Not satisfied ? Delete your account
21 |
Delete
22 |
23 |
24 |
25 |
26 | {% endblock content %}
--------------------------------------------------------------------------------
/authentication/templates/registration/password.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Change password
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Change password
10 |
15 |
16 | {% block js %}
17 |
26 | {% endblock js %}
27 | {% endblock content %}
--------------------------------------------------------------------------------
/base/migrations/0009_auto_20211016_1448.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-16 18:48
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('base', '0008_auto_20211016_1444'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='website',
15 | name='image1',
16 | field=models.ImageField(default='', upload_to='carousel/'),
17 | ),
18 | migrations.AddField(
19 | model_name='website',
20 | name='image2',
21 | field=models.ImageField(default='', upload_to='carousel/'),
22 | ),
23 | migrations.AddField(
24 | model_name='website',
25 | name='image3',
26 | field=models.ImageField(default='', upload_to='carousel/'),
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/authentication/templates/registration/delete-account.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Delete account
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
24 | {% endblock content %}
--------------------------------------------------------------------------------
/authentication/templates/registration/login.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}
4 | Login
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 | {% if user.is_authenticated %}
10 |
You are logged in
11 |
Home
12 |
Logout
13 | {% else %}
14 |
Login
15 |
20 | {% block js %}
21 |
28 | {% endblock js %}
29 | {% endif %}
30 |
31 | {% endblock content %}
32 |
--------------------------------------------------------------------------------
/base/forms.py:
--------------------------------------------------------------------------------
1 | from .models import (
2 | Website,
3 | Product
4 | )
5 | from django import forms
6 |
7 | class WebsiteForm(forms.ModelForm):
8 | class Meta:
9 | model = Website
10 | fields = ('name', 'image1', 'image2', 'image3')
11 |
12 | widgets = {
13 | 'name' : forms.TextInput(attrs={'class' : 'form-control'}),
14 | # 'image1' : forms.FileInput(attrs={'class' : 'form-control'}),
15 | # 'image2' : forms.FileInput(attrs={'class' : 'form-control'}),
16 | # 'image3' : forms.FileInput(attrs={'class' : 'form-control'}),
17 | }
18 |
19 | class ProductForm(forms.ModelForm):
20 |
21 | class Meta:
22 | model = Product
23 | fields = ('name', 'link', 'is_active', 'description', 'image')
24 |
25 | labels = {
26 | 'is_active' : "Active"
27 | }
28 |
29 | widgets = {
30 | 'name' : forms.TextInput(attrs={'class' : 'form-control'}),
31 | 'link' : forms.URLInput(attrs={'class' : 'form-control'}),
32 | 'description' : forms.Textarea(attrs={'class' : 'form-control'}),
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/urls.py:
--------------------------------------------------------------------------------
1 | """src URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/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.conf import settings
19 | from .settings import MEDIA_ROOT
20 | from django.conf.urls.static import static
21 |
22 |
23 | urlpatterns = [
24 | path('admin/', admin.site.urls),
25 | path('', include('base.urls')),
26 | path('', include('authentication.urls')),
27 | path('', include('django.contrib.auth.urls')),
28 | ]
29 |
30 | urlpatterns += static(settings.MEDIA_URL, document_root=MEDIA_ROOT)
--------------------------------------------------------------------------------
/authentication/decorators.py:
--------------------------------------------------------------------------------
1 | from django.http.response import HttpResponse
2 | from django.shortcuts import redirect, render
3 |
4 | def unauthenticated_user(view_func):
5 | def wrapper_func(request, *args, **kwargs):
6 | if request.user.is_authenticated:
7 | return redirect('/')
8 | else:
9 | return view_func(request, *args, **kwargs)
10 |
11 | return wrapper_func
12 |
13 | def not_active_user(view_func):
14 | def wrapper_func(request, *args, **kwargs):
15 | if request.user.is_active:
16 | return redirect('/')
17 | else:
18 | return view_func(request, *args, **kwargs)
19 |
20 | return wrapper_func
21 |
22 | def have_purchased(view_func):
23 | def wrapper_func(request, *args, **kwargs):
24 | if request.user.purchased == False and request.user.is_superuser == False:
25 | return view_func(request, *args, **kwargs)
26 | else:
27 | return redirect('dashboard')
28 |
29 | return wrapper_func
30 |
31 | def have_access(view_func):
32 | def wrapper_func(request, *args, **kwargs):
33 | if request.user.purchased == True or request.user.is_superuser:
34 | return view_func(request, *args, **kwargs)
35 | else:
36 | return redirect('purchase')
37 |
38 | return wrapper_func
--------------------------------------------------------------------------------
/authentication/forms.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.forms import (
2 | UserCreationForm,
3 | UserChangeForm
4 | )
5 | from django import forms
6 | from base.models import User
7 |
8 | class CreateUserForm(UserCreationForm):
9 | class Meta:
10 | model = User
11 | fields = ('username', 'name', 'email', 'password1', 'password2')
12 |
13 | def __init__(self, *args, **kwargs):
14 | super(UserCreationForm, self).__init__(*args, **kwargs)
15 | self.fields['username'].widget.attrs.update({'class' : 'form-control'})
16 | self.fields['email'].widget.attrs.update({'class' : 'form-control'})
17 | self.fields['name'].widget.attrs.update({'class' : 'form-control'})
18 | self.fields['password1'].widget.attrs.update({'class' : 'form-control'})
19 | self.fields['password2'].widget.attrs.update({'class' : 'form-control'})
20 |
21 | class AccountForm(UserChangeForm):
22 | class Meta:
23 | model = User
24 | fields = ('username', 'email', 'name')
25 |
26 | widgets = {
27 | 'username' : forms.TextInput(attrs={'class' : 'form-control'}),
28 | 'email' : forms.EmailInput(attrs={'required' : '', 'class' : 'form-control'}),
29 | 'name' : forms.TextInput(attrs={'required' : '', 'class' : 'form-control'}),
30 |
31 | }
--------------------------------------------------------------------------------
/base/urls.py:
--------------------------------------------------------------------------------
1 | from .views import (
2 | HomeView,
3 | CreateWebsite,
4 | Dashboard,
5 | WebsiteInfo,
6 | UpdateView,
7 | AddtoWebsite,
8 | RemoveFromWebsite,
9 | CreateProductView,
10 | UpdateProductView,
11 | DeleteProductView,
12 | DeleteWebsiteView,
13 | ProductInfo,
14 | )
15 |
16 | from django.urls import path
17 |
18 | urlpatterns = [
19 | path('', HomeView, name='home'),
20 | path('create-website/', CreateWebsite, name="create"),
21 | path('dashboard/', Dashboard, name="dashboard"),
22 | path('website//', WebsiteInfo, name="website-info"),
23 | path('update//', UpdateView, name="update"),
24 | path('delete//', DeleteWebsiteView, name="delete"),
25 | path('add//to//', AddtoWebsite, name="add"),
26 | path('remove//from//', RemoveFromWebsite, name="remove"),
27 | path('create-product/', CreateProductView, name="create-product"),
28 | path('update-product//', UpdateProductView, name="update-product"),
29 | path('delete-product//', DeleteProductView, name="delete-product"),
30 | path('product//', ProductInfo, name="product-info"),
31 | ]
32 |
--------------------------------------------------------------------------------
/authentication/templates/payments/purchase.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Purchase
5 | {% endblock title %}
6 |
7 | {% block style %}
8 |
21 | {% endblock style %}
22 |
23 | {% block content %}
24 |
25 |
26 |
27 | Purchase
28 | Invest in yourself to build your own affiliate websites.
29 | Membership includes
30 | Unlimited Affiliate websites
31 | Unlimited Affiliate products
32 | Unlimited Access to blog posts
33 |
34 |
35 |
Lifetime
36 |
$25
37 |
38 |
Unlimited products and websites
39 |
40 |
41 |
42 |
43 | {% endblock content %}
--------------------------------------------------------------------------------
/base/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.contrib.auth.models import AbstractUser
3 |
4 | class User(AbstractUser):
5 | name = models.CharField(max_length=255, null=True)
6 | email = models.EmailField(unique=True)
7 | key = models.CharField(max_length=100000000000000000000000000000000000000000000000000000)
8 | purchased = models.BooleanField(default=False)
9 |
10 | USERNAME_FIELD = 'email'
11 | REQUIRED_FIELDS = ['username', 'name', 'key', 'purchased']
12 |
13 | class Product(models.Model):
14 | name = models.CharField(max_length=1000)
15 | link = models.URLField()
16 | user = models.ForeignKey(User, blank=True, on_delete=models.CASCADE)
17 | is_active = models.BooleanField(default=True)
18 | description = models.TextField()
19 | image = models.ImageField(blank=True, null=True, upload_to='products/')
20 |
21 | def __str__(self):
22 | return "Product " + str(self.id)
23 |
24 | class Website(models.Model):
25 | name = models.CharField(max_length=255, unique=True)
26 | # header_title = models.CharField(max_length=255, default='')
27 | # header_text = models.TextField(default='')
28 | image1 = models.ImageField(upload_to='carousel/', default='')
29 | image2 = models.ImageField(upload_to='carousel/', default='')
30 | image3 = models.ImageField(upload_to='carousel/', default='')
31 | products = models.ManyToManyField(Product, related_name="website_products", blank=True)
32 | user = models.ForeignKey(User, on_delete=models.CASCADE)
33 |
34 | def __str__(self):
35 | return self.name
--------------------------------------------------------------------------------
/base/templates/update-website.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Update {{ website.name }}
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
Update website
10 |
15 |
16 |
17 |
Products
18 | {% for product in products %}
19 |
20 |
21 |
{{ product.name }}
22 | {% if product.id in current %}
23 |
31 | {% else %}
32 |
40 | {% endif %}
41 |
42 |
43 | {% endfor %}
44 |
45 | {% endblock content %}
--------------------------------------------------------------------------------
/base/templates/dashboard.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | Dashboard
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
My websites
10 |
11 |
New website
12 | {% for website in websites %}
13 |
14 |
15 |
{{ website.name }}
16 |
24 |
25 |
26 | {% endfor %}
27 |
Products
28 |
29 |
New product
30 | {% for product in products %}
31 |
32 |
33 |
{{ product.name }}
34 |
42 |
43 |
44 | {% endfor %}
45 | {% if length >= 5 %}
46 |
All products
47 | {% endif %}
48 |
49 |
50 | {% endblock content %}
--------------------------------------------------------------------------------
/base/templates/website/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% block title %}
9 |
10 | {% endblock title %}
11 |
12 |
13 |
14 |
32 |
33 |
48 | {% block content %}
49 |
50 | {% endblock content %}
51 |
52 |
55 |
61 |
62 |
--------------------------------------------------------------------------------
/base/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% block title %}
9 |
10 | {% endblock title %}
11 |
12 |
13 |
14 | {% block style %}
15 |
16 | {% endblock style %}
17 |
18 |
51 | {% block content %}
52 |
53 | {% endblock content %}
54 |
55 | {% block js %}
56 |
57 | {% endblock js %}
58 |
59 |
--------------------------------------------------------------------------------
/authentication/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 | from .forms import (
3 | CreateUserForm,
4 | AccountForm,
5 | )
6 | from .decorators import (have_purchased, unauthenticated_user, not_active_user)
7 | import uuid
8 | from django.contrib.auth.decorators import login_required
9 | from django.contrib.auth import update_session_auth_hash
10 | from base.models import User
11 | from django.contrib.auth.forms import PasswordChangeForm
12 | from django.core.mail import send_mail
13 | from src.settings import ALLOWED_HOSTS
14 | from django.conf import settings
15 |
16 |
17 | @unauthenticated_user
18 | def SignupView(request):
19 | template = "signup.html"
20 | form = CreateUserForm()
21 | if request.method == "POST":
22 | form = CreateUserForm(request.POST)
23 | if form.is_valid():
24 | form.save()
25 | key = uuid.uuid4()
26 | user = User.objects.get(email=request.POST['email'])
27 | user.key = key
28 | user.is_active = False
29 | user.save()
30 | subject = "Verify your email"
31 | message = f"Hi {user.name}, thank you for signing up. \n Please verify your email. \n http://{ALLOWED_HOSTS[0]}:8000/activate-account/{user.key}/"
32 | email_from = settings.EMAIL_HOST_USER
33 | recipient_list = [user.email, ]
34 | send_mail( subject, message, email_from, recipient_list )
35 | template2 = "email_sent.html"
36 | context2 = {}
37 | return render(request, template2, context2)
38 |
39 | context = {
40 | 'form' : form,
41 | }
42 |
43 | return render(request, template, context)
44 |
45 |
46 |
47 | @login_required
48 | def PasswordView(request):
49 | template = "registration/password.html"
50 | form = PasswordChangeForm(user=request.user)
51 | if request.method == "POST":
52 | form = PasswordChangeForm(user=request.user, data=request.POST)
53 | if form.is_valid():
54 | form.save()
55 | update_session_auth_hash(request, form.user)
56 | return redirect('account')
57 |
58 | context = {
59 | 'form': form
60 | }
61 | return render(request, template, context)
62 |
63 |
64 | @login_required
65 | def AccountView(request):
66 | template = "registration/account.html"
67 | form = AccountForm(instance=request.user)
68 | if request.method == "POST":
69 | form = AccountForm(request.POST, instance=request.user)
70 | if form.is_valid():
71 | form.save()
72 | return redirect('account')
73 | context = {
74 | 'form': form
75 | }
76 | return render(request, template, context)
77 |
78 |
79 | @login_required
80 | def UserDeleteView(request):
81 | template = "registration/delete-account.html"
82 | if request.method == "POST":
83 | current_user = request.user
84 | user_object = User.objects.get(id=current_user.id)
85 | user_object.delete()
86 | return redirect('home')
87 |
88 | context = {
89 |
90 | }
91 | return render(request, template, context)
92 |
93 | @not_active_user
94 | def ActivateAccountView(request, token):
95 | try:
96 | user = User.objects.get(key=token)
97 | if user.is_active == False:
98 | user.is_active = True
99 | user.save()
100 | else:
101 | return redirect('/')
102 | except:
103 | return redirect('/')
104 | template = 'activate.html'
105 | context = {
106 |
107 | }
108 | return render(request, template, context)
109 |
110 | @login_required
111 | @have_purchased
112 | def purchaseview(request):
113 | template = 'payments/purchase.html'
114 | context = {
115 |
116 | }
117 | return render(request, template, context)
--------------------------------------------------------------------------------
/base/templates/website-info.html:
--------------------------------------------------------------------------------
1 | {% extends 'website/base.html' %}
2 |
3 | {% block title %}
4 | {{ website.name|capfirst }}
5 | {% endblock title %}
6 |
7 | {% block content %}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |

18 |
19 |
20 |

21 |
22 |
23 |

24 |
25 |
26 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Products
41 |
42 |
43 | {% for product in products %}
44 |
45 |
46 |
47 |

48 |
49 |
50 |
51 |
52 |
{{ product.name }}
53 |
54 |
55 | {{ product.description|safe }}
56 |
57 |
58 |
59 |
60 |
61 |
64 |
65 |
66 | {% endfor %}
67 |
68 |
69 | {% if products %}
70 |
97 | {% endif %}
98 |
99 |
100 |
101 | {% endblock content %}
--------------------------------------------------------------------------------
/base/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.7 on 2021-10-15 23:28
2 |
3 | from django.conf import settings
4 | import django.contrib.auth.models
5 | import django.contrib.auth.validators
6 | from django.db import migrations, models
7 | import django.db.models.deletion
8 | import django.utils.timezone
9 |
10 |
11 | class Migration(migrations.Migration):
12 |
13 | initial = True
14 |
15 | dependencies = [
16 | ('auth', '0012_alter_user_first_name_max_length'),
17 | ]
18 |
19 | operations = [
20 | migrations.CreateModel(
21 | name='User',
22 | fields=[
23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24 | ('password', models.CharField(max_length=128, verbose_name='password')),
25 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
26 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
27 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
28 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
29 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
30 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
31 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
32 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
33 | ('name', models.CharField(max_length=255, null=True)),
34 | ('email', models.EmailField(max_length=254, unique=True)),
35 | ('key', models.CharField(max_length=100000000000000000000000000000000000000000000000000000)),
36 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
37 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
38 | ],
39 | options={
40 | 'verbose_name': 'user',
41 | 'verbose_name_plural': 'users',
42 | 'abstract': False,
43 | },
44 | managers=[
45 | ('objects', django.contrib.auth.models.UserManager()),
46 | ],
47 | ),
48 | migrations.CreateModel(
49 | name='Product',
50 | fields=[
51 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
52 | ('name', models.CharField(max_length=1000, unique=True)),
53 | ('link', models.URLField()),
54 | ('is_active', models.BooleanField(default=True)),
55 | ('description', models.TextField()),
56 | ('image', models.ImageField(blank=True, null=True, upload_to='products/')),
57 | ],
58 | ),
59 | migrations.CreateModel(
60 | name='Website',
61 | fields=[
62 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
63 | ('name', models.CharField(max_length=255, unique=True)),
64 | ('products', models.ManyToManyField(related_name='website_products', to='base.Product')),
65 | ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
66 | ],
67 | ),
68 | ]
69 |
--------------------------------------------------------------------------------
/src/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for src project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.7.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 | from dotenv import load_dotenv, find_dotenv
15 | import os
16 |
17 | load_dotenv(find_dotenv())
18 |
19 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
20 | BASE_DIR = Path(__file__).resolve().parent.parent
21 |
22 |
23 | # Quick-start development settings - unsuitable for production
24 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
25 |
26 | # SECURITY WARNING: keep the secret key used in production secret!
27 | SECRET_KEY = os.environ.get('SECRET_KEY')
28 |
29 | DEBUG_OPTIONS = [True, False]
30 |
31 | # SECURITY WARNING: don't run with debug turned on in production!
32 | DEBUG = DEBUG_OPTIONS[int(os.environ.get("DEBUG"))]
33 |
34 | ALLOWED_HOSTS = ['localhost', '127.0.0.1']
35 |
36 |
37 | # Application definition
38 |
39 | INSTALLED_APPS = [
40 | 'django.contrib.admin',
41 | 'django.contrib.auth',
42 | 'django.contrib.contenttypes',
43 | 'django.contrib.sessions',
44 | 'django.contrib.messages',
45 | 'django.contrib.staticfiles',
46 | 'base',
47 | 'authentication',
48 | ]
49 |
50 | AUTH_USER_MODEL = 'base.User'
51 |
52 | MIDDLEWARE = [
53 | 'django.middleware.security.SecurityMiddleware',
54 | 'django.contrib.sessions.middleware.SessionMiddleware',
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 = 'src.urls'
63 |
64 | TEMPLATES = [
65 | {
66 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
67 | 'DIRS': [BASE_DIR / 'password reset'],
68 | 'APP_DIRS': True,
69 | 'OPTIONS': {
70 | 'context_processors': [
71 | 'django.template.context_processors.debug',
72 | 'django.template.context_processors.request',
73 | 'django.contrib.auth.context_processors.auth',
74 | 'django.contrib.messages.context_processors.messages',
75 | ],
76 | },
77 | },
78 | ]
79 |
80 | WSGI_APPLICATION = 'src.wsgi.application'
81 |
82 |
83 | # Database
84 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
85 |
86 | DATABASES = {
87 | 'default': {
88 | 'ENGINE': 'django.db.backends.sqlite3',
89 | 'NAME': BASE_DIR / 'db.sqlite3',
90 | }
91 | }
92 |
93 |
94 | # Password validation
95 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
96 |
97 | AUTH_PASSWORD_VALIDATORS = [
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
103 | },
104 | {
105 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
106 | },
107 | {
108 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
109 | },
110 | ]
111 |
112 |
113 | # Internationalization
114 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
115 |
116 | LANGUAGE_CODE = 'en-us'
117 |
118 | TIME_ZONE = 'UTC'
119 |
120 | USE_I18N = True
121 |
122 | USE_L10N = True
123 |
124 | USE_TZ = True
125 |
126 |
127 | # Static files (CSS, JavaScript, Images)
128 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
129 |
130 | STATIC_URL = '/static/'
131 | MEDIA_URL = '/media/'
132 |
133 | MEDIA_ROOT = BASE_DIR / 'media'
134 |
135 | STATIC_ROOT = BASE_DIR / 'staticfiles'
136 |
137 | LOGIN_URL = 'login'
138 |
139 | LOGIN_REDIRECT_URL = 'home'
140 | LOGOUT_REDIRECT_URL = 'home'
141 |
142 | EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
143 | EMAIL_HOST = 'smtp.gmail.com'
144 | EMAIL_PORT = 587
145 | EMAIL_USE_TLS = True
146 | EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER")
147 | EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
148 |
149 |
150 | # Default primary key field type
151 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
152 |
153 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
154 |
--------------------------------------------------------------------------------
/base/views.py:
--------------------------------------------------------------------------------
1 | from django.http.response import HttpResponse, HttpResponseRedirect
2 | from django.shortcuts import redirect, render
3 |
4 | from authentication.decorators import have_access
5 | from .forms import (
6 | WebsiteForm,
7 | ProductForm
8 | )
9 | from django.contrib.auth.decorators import login_required
10 | from .models import (
11 | Website,
12 | Product
13 |
14 | )
15 | from django.core.paginator import Paginator
16 |
17 | from django.urls import reverse
18 |
19 | def HomeView(request):
20 | template = "home.html"
21 | context = {
22 |
23 | }
24 |
25 | return render(request, template, context)
26 |
27 | @login_required
28 | @have_access
29 | def CreateWebsite(request):
30 | template = "create-website.html"
31 | form = WebsiteForm()
32 | if request.method == "POST":
33 | form = WebsiteForm(request.POST, request.FILES)
34 | form.instance.user = request.user
35 | if form.is_valid():
36 | form.save()
37 | return redirect('dashboard')
38 | context = {
39 | 'form' : form,
40 | }
41 |
42 | return render(request, template, context)
43 |
44 | @login_required
45 | def Dashboard(request):
46 | template = "dashboard.html"
47 | websites = Website.objects.filter(user=request.user)
48 | products = Product.objects.filter(user=request.user)[:5]
49 | context = {
50 | 'websites' : websites,
51 | 'products' : products,
52 | 'length' : len(products),
53 | }
54 |
55 | return render(request, template, context)
56 |
57 | def WebsiteInfo(request, pk):
58 | template = "website-info.html"
59 | website = Website.objects.get(id=pk)
60 | products = website.products.all().filter(is_active=True)
61 | p = Paginator(products.order_by('-id'), 10)
62 | page = request.GET.get('page')
63 | stuff = p.get_page(page)
64 | nums = "a" * stuff.paginator.num_pages
65 | context = {
66 | 'website' : website,
67 | 'products' : stuff,
68 | 'nums' : nums,
69 | }
70 |
71 | return render(request, template, context)
72 |
73 | @login_required
74 | def AddtoWebsite(request, website_id, product_id):
75 | website = Website.objects.get(id=website_id)
76 | product = Product.objects.get(id=product_id)
77 | if website.user == request.user and product.user == request.user:
78 | if request.method == "POST":
79 | website.products.add(product)
80 | return HttpResponseRedirect(reverse('update', args=[str(website.id)]))
81 | else:
82 | return redirect('/')
83 |
84 | @login_required
85 | def RemoveFromWebsite(request, website_id, product_id):
86 | website = Website.objects.get(id=website_id)
87 | product = Product.objects.get(id=product_id)
88 | if website.user == request.user and product.user == request.user:
89 | if request.method == "POST":
90 | website.products.remove(product)
91 | return HttpResponseRedirect(reverse('update', args=[str(website.id)]))
92 | else:
93 | return redirect('/')
94 |
95 | @login_required
96 | def UpdateView(request, pk):
97 | website = Website.objects.get(id=pk)
98 | if request.user == website.user:
99 | template = "update-website.html"
100 | form = WebsiteForm(instance=website)
101 | products = Product.objects.filter(user=request.user)
102 | website_products = website.products.all()
103 | current_products = []
104 | for product in website_products:
105 | current_products.append(product.id)
106 | if request.method == "POST":
107 | form = WebsiteForm(request.POST, request.FILES, instance=website)
108 | if form.is_valid():
109 | form.save()
110 | return redirect(request.path)
111 | context = {
112 | 'form' : form,
113 | 'products' : products.filter(is_active=True),
114 | 'current' : current_products,
115 | 'website' : website,
116 | }
117 | return render(request, template, context)
118 | else:
119 | return redirect('home')
120 |
121 | @login_required
122 | @have_access
123 | def CreateProductView(request):
124 | template = "products/create.html"
125 | form = ProductForm()
126 | if request.method == "POST":
127 | form = ProductForm(request.POST, request.FILES)
128 | form.instance.user = request.user
129 | if form.is_valid():
130 | form.save()
131 | return redirect('dashboard')
132 | context = {
133 | 'form' : form,
134 | }
135 |
136 | return render(request, template, context)
137 |
138 | @login_required
139 | def UpdateProductView(request, pk):
140 | product = Product.objects.get(id=pk)
141 | if product.user == request.user:
142 | template = "products/update.html"
143 | form = ProductForm(instance=product)
144 | if request.method == "POST":
145 | form = ProductForm(request.POST, request.FILES, instance=product)
146 | if form.is_valid():
147 | form.save()
148 | return redirect('dashboard')
149 | context = {
150 | 'product' : product,
151 | 'form' : form,
152 | }
153 |
154 | return render(request, template, context)
155 | else:
156 | return redirect('/')
157 |
158 | @login_required
159 | def DeleteProductView(request, pk):
160 | product = Product.objects.get(id=pk)
161 | if request.method == "POST":
162 | if product.user == request.user:
163 | product.delete()
164 | return redirect('dashboard')
165 | else:
166 | return redirect('/')
167 |
168 | @login_required
169 | def DeleteWebsiteView(request, pk):
170 | website = Website.objects.get(id=pk)
171 | if request.method == "POST":
172 | if website.user == request.user:
173 | website.delete()
174 | return redirect('dashboard')
175 | else:
176 | return redirect('/')
177 |
178 | @login_required
179 | def ProductInfo(request, pk):
180 | product = Product.objects.get(id=pk)
181 | if product.user == request.user:
182 | template = "products/info.html"
183 | context = {
184 | 'product' : product,
185 | }
186 |
187 | return render(request, template, context)
188 | else:
189 | return redirect('/')
--------------------------------------------------------------------------------