├── 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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
10 | {% csrf_token %} 11 | {{ form.as_p }} 12 | 13 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
15 |
16 |
17 |

Delete account

18 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
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 |
9 |
10 |
11 |

Are you sure you want to delete your account?

12 |
13 |
14 |
15 | {% csrf_token %} 16 |
17 | Cancel 18 | 19 |
20 |
21 |
22 |
23 |
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 |
16 | {% csrf_token %} 17 | {{ form.as_p }} 18 | 19 |
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 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
15 |
16 |
17 |

Products

18 | {% for product in products %} 19 |
20 |
21 |

{{ product.name }}

22 | {% if product.id in current %} 23 |
24 | {% csrf_token %} 25 |
26 | View 27 | Update 28 | 29 |
30 |
31 | {% else %} 32 |
33 | {% csrf_token %} 34 |
35 | View 36 | Update 37 | 38 |
39 |
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 |
17 | {% csrf_token %} 18 |
19 | View 20 | Update 21 | 22 |
23 |
24 |
25 |
26 | {% endfor %} 27 |

Products

28 |
29 | New product 30 | {% for product in products %} 31 |
32 |
33 |

{{ product.name }}

34 |
35 | {% csrf_token %} 36 |
37 | View 38 | Update 39 | 40 |
41 |
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 |
53 |

54 |
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 | 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('/') --------------------------------------------------------------------------------