├── seller ├── __init__.py ├── migrations │ └── __init__.py ├── tests.py ├── admin.py ├── models.py ├── apps.py ├── urls.py ├── views.py └── templates │ └── seller │ ├── login.html │ ├── register.html │ ├── registerbaseuser.html │ ├── basic.html │ └── index.html ├── firstapp ├── __init__.py ├── migrations │ └── __init__.py ├── templatetags │ ├── __init__.py │ └── myfilters.py ├── templates │ └── firstapp │ │ ├── cart.html │ │ ├── registration │ │ ├── password_reset_sent.html │ │ ├── password_change_done.html │ │ ├── password_reset_done.html │ │ ├── acc_active_email.html │ │ ├── password_change.html │ │ ├── password_reset.html │ │ ├── password_reset_form.html │ │ └── forgot_password_email.html │ │ ├── sessiontesting.html │ │ ├── payment │ │ ├── paymentsuccess.html │ │ ├── emailinvoice.html │ │ ├── paymentfailed.html │ │ ├── paymentsummaryrazorpay.html │ │ └── invoice.html │ │ ├── productdetail.html │ │ ├── contactus.html │ │ ├── contactus2.html │ │ ├── listpremiumproducts.html │ │ ├── login.html │ │ ├── registerseller.html │ │ ├── displaycart.html │ │ ├── registercustomer.html │ │ ├── registerbasicuser.html │ │ ├── register.html │ │ ├── basic.html │ │ ├── listproducts.html │ │ └── index.html ├── tests.py ├── logo.png ├── apps.py ├── mixins.py ├── tokens.py ├── decorators.py ├── managers.py ├── forms.py ├── urls.py ├── admin.py ├── models.py └── views.py ├── firstproject ├── __init__.py ├── admin_urls.py ├── hosts.py ├── wsgi.py ├── asgi.py ├── urls.py └── settings.py ├── requirements.txt ├── README.md ├── .gitignore └── manage.py /seller/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firstapp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firstproject/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firstapp/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firstapp/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /seller/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/cart.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /seller/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /firstapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /seller/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /seller/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | 5 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu2015/MasteringDjango/HEAD/requirements.txt -------------------------------------------------------------------------------- /firstapp/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu2015/MasteringDjango/HEAD/firstapp/logo.png -------------------------------------------------------------------------------- /seller/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SellerConfig(AppConfig): 5 | name = 'seller' 6 | -------------------------------------------------------------------------------- /firstapp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FirstappConfig(AppConfig): 5 | name = 'firstapp' 6 | -------------------------------------------------------------------------------- /firstproject/admin_urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path, include 3 | 4 | 5 | urlpatterns = [ 6 | path('', admin.site.urls), 7 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Complete Django Course for django web development 2 | 3 | Ultimate Roadmap to Mastering Django(New✨): https://www.letsprogressify.com/roadmaps/93f13210-efd8-4663-ad7e-ed0b70fad7f7/preview 4 | -------------------------------------------------------------------------------- /firstproject/hosts.py: -------------------------------------------------------------------------------- 1 | from django_hosts import patterns, host 2 | from django.contrib import admin 3 | from . import admin_urls 4 | 5 | host_patterns = patterns('', 6 | host(r'www', 'firstapp.urls', name='www'), 7 | host(r'services', 'seller.urls', name='services'), 8 | host(r'admin', admin_urls, name='admin'), 9 | ) -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_reset_sent.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 | Link has been sent to your email id. 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 | Your password has been changed. Now you can login with your new password. 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/sessiontesting.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 | {% if user.is_authenticated %} 10 |

{{user.name}}

11 | {% endif %} 12 | {{ request.session.test }} 13 | {{ request.session.test2 }} 14 | {% endblock %} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | 3 | # Django # 4 | *.log 5 | *.pot 6 | *.pyc 7 | __pycache__ 8 | db.sqlite3 9 | 10 | **/migrations/** 11 | !**/migrations 12 | !**/migrations/__init__.py 13 | 14 | testasync.py 15 | sendotp.html 16 | verifyotp.html 17 | otp_settings.txt 18 | views2.py 19 | 20 | media 21 | static 22 | static_cdn 23 | .env 24 | data.json 25 | backends.py 26 | testsocket.py -------------------------------------------------------------------------------- /firstapp/mixins.py: -------------------------------------------------------------------------------- 1 | from django.core.exceptions import PermissionDenied 2 | class CheckPremiumGroupMixin: 3 | def dispatch(self, request, *args, **kwargs): 4 | if request.user.groups.filter(name = "premium").exists(): 5 | #return True 6 | return super().dispatch(request, *args, **kwargs) 7 | 8 | else: 9 | raise PermissionDenied -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 | Your new password has been set. Now you can login with your newly entered password. 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/tokens.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.tokens import PasswordResetTokenGenerator 2 | import six 3 | class TokenGenerator(PasswordResetTokenGenerator): 4 | def _make_hash_value(self, user, timestamp): 5 | return ( 6 | six.text_type(user.pk) + six.text_type(timestamp) + 7 | six.text_type(user.is_active) 8 | ) 9 | account_activation_token = TokenGenerator() -------------------------------------------------------------------------------- /firstapp/templatetags/myfilters.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | def addclass(value, token): 6 | value.field.widget.attrs["class"] = token 7 | return value 8 | 9 | def addplaceholder(value, token): 10 | value.field.widget.attrs["placeholder"] = token 11 | return value 12 | 13 | register.filter(addclass) 14 | register.filter(addplaceholder) -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/acc_active_email.html: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | Hi {{ user.name }}, 3 | Thanks for signing up to WonderShop! 4 | 5 | To set up your account, Please click on the link to confirm your registration, 6 | http://{{ domain }}{% url 'activate' uidb64=uid token=token %} 7 | 8 | Thanks for using our site! 9 | 10 | Sincerely, 11 | WonderShop Team 12 | 13 | {% endautoescape %} 14 | 15 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 |
{% csrf_token %} 11 | {{form.as_p}} 12 | 13 |
14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_reset.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 |
{% csrf_token %} 11 | {{form.as_p}} 12 | 13 |
14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 |
{% csrf_token %} 11 | {{form.as_p}} 12 | 13 |
14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registration/forgot_password_email.html: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | Hi {{ user.name }}, 3 | You have requested for password change on WonderShop Website! 4 | 5 | To change your password, click on the link give n below, 6 | http://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} 7 | 8 | Thanks for using our site! 9 | 10 | Sincerely, 11 | WonderShop Team 12 | 13 | {% endautoescape %} 14 | -------------------------------------------------------------------------------- /firstproject/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for firstproject project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'firstproject.settings') 15 | 16 | application = get_wsgi_application() 17 | 18 | # from dj_static import Cling 19 | # application = Cling(get_wsgi_application()) 20 | -------------------------------------------------------------------------------- /seller/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path, include 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path('', views.index, name="index"), 7 | path('signup/', views.RegisterView.as_view(), name="signup"), 8 | path('signupseller/', views.RegisterViewSeller.as_view(), name="signupseller"), 9 | path('login/', views.LoginViewUser.as_view(), name="login"), 10 | path('logout/', views.LogoutViewUser.as_view(), name="logout"), 11 | 12 | #path('sendotp/', views.otp_send, name = "sendotp"), 13 | #path('verifyotp/', views.otp_verify, name = "verifyotp"), 14 | ] -------------------------------------------------------------------------------- /firstapp/templates/firstapp/payment/paymentsuccess.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | 5 | {% endblock %} 6 | {% block css %} 7 | 9 | {% endblock %} 10 | 11 | {% block body %} 12 |
13 |
14 |

Payment Success

15 |
16 |

Congratulations! You have successfully done the payment. Your order will reach to you in 5 days.

17 | 18 |
19 |
20 | {% endblock %} 21 | 22 | 23 | {% block js %} 24 | 27 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/payment/emailinvoice.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | Hi {{ user.name }}, 5 | Your order with order id: {{order.order_id}} has been placed successfully. 6 | 7 | Your order consists of - 8 | {% for i in order.productinorder_set.all %} 9 | Product:{{i.product}} Quantity:{{i.quantity}} Price:{{i.price}} 10 | {% endfor %} 11 | Total:{{order.total_amount}} 12 | 13 | Order will reach to you in 5-7 days. 14 | 15 | We have attached the invoice for your order with this mail. 16 | 17 | Thanks for trusting us and using our services! 18 | 19 | Sincerely, 20 | WonderShop Team 21 | 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 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'firstproject.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/payment/paymentfailed.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | 5 | {% endblock %} 6 | {% block css %} 7 | 9 | {% endblock %} 10 | 11 | {% block body %} 12 |
13 |
14 |

Payment Failed

15 |

Sorry! Your payment has been failed. Please try again.

16 |
17 |

18 | In case your money has been deducted, money will be autorefunded in 7-10 days. 19 |

20 |
21 |

Thank You for choosing us. You can contact us for any queries or details.

22 |
23 |
24 | {% endblock %} 25 | 26 | 27 | {% block js %} 28 | 31 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/decorators.py: -------------------------------------------------------------------------------- 1 | import six 2 | from django.core.exceptions import PermissionDenied 3 | from django.contrib.auth.decorators import user_passes_test 4 | 5 | def group_required(group, login_url=None, raise_exception=False): 6 | def check_perms(user): 7 | if isinstance(group, six.string_types): 8 | groups = (group, ) 9 | else: 10 | groups = group 11 | # First check if the user has the permission (even anon users) 12 | 13 | if user.groups.filter(name__in=groups).exists(): 14 | return True 15 | # In case the 403 handler should be called raise the exception 16 | if raise_exception: 17 | raise PermissionDenied 18 | # As the last resort, show the login form 19 | return False 20 | return user_passes_test(check_perms, login_url=login_url) -------------------------------------------------------------------------------- /firstproject/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for firstproject project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | # os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'firstproject.settings') 15 | 16 | # application = get_asgi_application() 17 | 18 | 19 | 20 | import os 21 | import django 22 | from channels.http import AsgiHandler 23 | from channels.routing import ProtocolTypeRouter, URLRouter 24 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "firstproject.settings") 25 | django.setup() 26 | #from apps.ws_routing import websocket_urlpatterns 27 | 28 | application = ProtocolTypeRouter({ 29 | "http": get_asgi_application(), #AsgiHandler(),#,#AsgiHandler(), 30 | # 'websocket': 31 | # URLRouter( 32 | # websocket_urlpatterns 33 | # ) 34 | }) 35 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/productdetail.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 20 | {% endblock %} 21 | 22 | {% block body%} 23 |
24 |
25 |
26 |
27 | ... 28 | 29 |
30 |
31 |

{{product.product_name}}

32 |

Rs. {{product.price}}

33 | Add To Cart 34 |
35 | 36 |
37 |
38 | 39 |
40 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/contactus.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | {% endblock %} 7 | 8 | {% block body%} 9 |
10 |
{% csrf_token %} 11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 |
27 | 28 |
29 |
30 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/contactus2.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 12 | {% endblock %} 13 | 14 | {% block body%} 15 |
16 |
{% csrf_token %} 17 | 18 | {{ form.non_field_errors }} 19 | 20 | {{ form.email.errors }} 21 | {{ form.email|addclass:'form-control'|addplaceholder:'Email Address'}} 22 | 23 | 24 | {{ form.phone.errors }} 25 | {{ form.phone|addclass:'form-control'|addplaceholder:'Password' }} 26 | 27 | {{ form.query.errors }} 28 | {{ form.query|addclass:'form-control'|addplaceholder:'Any Query' }} 29 | 30 | {{ form.name.errors }} 31 | {{ form.name|addclass:'form-control'|addplaceholder:'Your Name' }} 32 | 33 |
34 | 35 |
36 | {% endblock %} -------------------------------------------------------------------------------- /firstproject/urls.py: -------------------------------------------------------------------------------- 1 | """firstproject URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | 21 | urlpatterns = [ 22 | path('admin/', admin.site.urls), 23 | path('', include('firstapp.urls')), 24 | path('services/', include('seller.urls')), 25 | ] 26 | 27 | 28 | # when debug=True 29 | # if settings.DEBUG: 30 | # urlpatterns += static(settings.STATIC_URL ,document_root = settings.STATIC_ROOT) 31 | # urlpatterns += static(settings.MEDIA_URL ,document_root = settings.MEDIA_ROOT) 32 | 33 | 34 | -------------------------------------------------------------------------------- /seller/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, HttpResponse, redirect 2 | from django.views.generic import TemplateView, FormView, CreateView 3 | from django.core.exceptions import ValidationError 4 | from firstapp.forms import ContactUsForm, RegistrationFormSeller, RegistrationForm, RegistrationFormSeller2 5 | from django.urls import reverse_lazy, reverse 6 | from firstapp.models import SellerAdditional, CustomUser 7 | from django.contrib.auth.views import LoginView, LogoutView 8 | from django.contrib.auth.mixins import LoginRequiredMixin 9 | # Create your views here. 10 | 11 | def index(request): 12 | return render(request, 'seller/index.html') 13 | 14 | class LoginViewUser(LoginView): 15 | template_name = "seller/login.html" 16 | #success_url = reverse_lazy('index') 17 | 18 | class RegisterViewSeller(LoginRequiredMixin, CreateView): 19 | template_name = 'seller/register.html' 20 | form_class = RegistrationFormSeller2 21 | success_url = reverse_lazy('index') 22 | 23 | def form_valid(self, form): 24 | user = self.request.user 25 | user.type.append(user.Types.SELLER) 26 | user.save() 27 | form.instance.user = self.request.user 28 | return super().form_valid(form) 29 | 30 | 31 | class LogoutViewUser(LogoutView): 32 | success_url = reverse_lazy('index') 33 | 34 | class RegisterView(CreateView): 35 | template_name = 'seller/registerbaseuser.html' 36 | form_class = RegistrationForm 37 | success_url = reverse_lazy('index') -------------------------------------------------------------------------------- /firstapp/managers.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.base_user import BaseUserManager 2 | from django.utils.translation import ugettext_lazy as _ 3 | 4 | 5 | class CustomUserManager(BaseUserManager): 6 | """ 7 | Custom user model manager where email is the unique identifiers 8 | for authentication instead of usernames. 9 | """ 10 | def create_user(self, email, password, **extra_fields): 11 | """ 12 | Create and save a User with the given email and password. 13 | """ 14 | if not email: 15 | raise ValueError(_('The Email must be set')) 16 | email = self.normalize_email(email) #self.normalize_email(email).lower 17 | user = self.model(email=email, **extra_fields) 18 | user.set_password(password) 19 | user.save() 20 | return user 21 | 22 | def create_superuser(self, email, password, **extra_fields): 23 | """ 24 | Create and save a SuperUser with the given email and password. 25 | """ 26 | extra_fields.setdefault('is_staff', True) 27 | extra_fields.setdefault('is_superuser', True) 28 | extra_fields.setdefault('is_active', True) 29 | 30 | if extra_fields.get('is_staff') is not True: 31 | raise ValueError(_('Superuser must have is_staff=True.')) 32 | if extra_fields.get('is_superuser') is not True: 33 | raise ValueError(_('Superuser must have is_superuser=True.')) 34 | return self.create_user(email, password, **extra_fields) 35 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/listpremiumproducts.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load hosts %} 3 | {% load static %} 4 | {% load myfilters %} 5 | {% block title %} 6 | {% endblock %} 7 | {% block css %} 8 | 33 | {% endblock %} 34 | 35 | {% block body%} 36 |
37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | {% for i in product %} 47 |
48 |
49 | ... 50 |
51 |
{{i.product_name}}
52 |

{{i.price}}

53 |
54 | Add To Cart 55 |
56 |
57 | {% endfor %} 58 |
59 | 60 | 61 | 62 | 63 |
64 |
65 | 66 | 67 | 68 |
69 | {% endblock %} 70 | 71 | {% block js %} 72 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/payment/paymentsummaryrazorpay.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | 8 | {% endblock %} 9 | 10 | {% block body %} 11 |
12 |
13 |

Payment Summary

14 | Total Amount - {{order.total_amount}} 15 |
16 | 17 |
18 | 19 |
20 | 21 | 22 | 23 | {% endblock %} 24 | 25 | 26 | {% block js %} 27 | 28 | 52 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Login

55 | 56 | {{ form.username.errors }} 57 | {{ form.username|addclass:'form-control'|addplaceholder:'Email Address'}} 58 | 59 | {{ form.password.errors }} 60 | {{ form.password|addclass:'form-control'|addplaceholder:'Your Password' }} 61 |
62 | 63 | 64 |
65 |
66 | {% endblock %} -------------------------------------------------------------------------------- /seller/templates/seller/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'seller/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

WonderShop

54 |

Login For Sellers

55 | 56 | {{ form.username.errors }} 57 | {{ form.username|addclass:'form-control'|addplaceholder:'Email Address'}} 58 | 59 | {{ form.password.errors }} 60 | {{ form.password|addclass:'form-control'|addplaceholder:'Your Password' }} 61 |
62 | 63 | 64 |
65 |
66 | {% endblock %} -------------------------------------------------------------------------------- /seller/templates/seller/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'seller/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Sign Up For Seller

55 | 56 | {{ form.gst.errors }} 57 | {{ form.gst|addclass:'form-control'|addplaceholder:'GST' }} 58 | 59 | {{ form.warehouse_location.errors }} 60 | {{ form.warehouse_location|addclass:'form-control'|addplaceholder:'Warehouse Location' }} 61 |
62 | 63 | 64 |
65 |
66 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registerseller.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Sign Up For Seller

55 | 56 | {{ form.gst.errors }} 57 | {{ form.gst|addclass:'form-control'|addplaceholder:'GST' }} 58 | 59 | {{ form.warehouse_location.errors }} 60 | {{ form.warehouse_location|addclass:'form-control'|addplaceholder:'Warehouse Location' }} 61 |
62 | 63 | 64 |
65 |
66 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/displaycart.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load hosts %} 3 | {% load static %} 4 | {% load myfilters %} 5 | {% block title %} 6 | {% endblock %} 7 | {% block css %} 8 | 25 | {% endblock %} 26 | 27 | {% block body%} 28 |
29 |
30 |

CART

31 | 32 | {% for i in cart %} 33 |
34 |
35 | ... 36 |
37 |
38 |

{{i.product.product_name}}

39 |

Rs. {{i.product.price}}

40 |

Quantity- {{i.quantity}}

41 |
{% csrf_token %} 42 | 43 | 44 |
45 |
{% csrf_token %} 46 | 47 |
48 |
49 | 50 |
51 |
52 | {% empty %} 53 |

Empty Cart

54 | {% endfor %} 55 | 56 |
{% csrf_token %} 57 | 58 |
59 |
60 | 61 |
62 | {% endblock %} -------------------------------------------------------------------------------- /seller/templates/seller/registerbaseuser.html: -------------------------------------------------------------------------------- 1 | {% extends 'seller/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Sign Up

55 | 56 | {{ form.email.errors }} 57 | {{ form.email|addclass:'form-control'|addplaceholder:'Email Address'}} 58 | 59 | 60 | {{ form.name.errors }} 61 | {{ form.name|addclass:'form-control'|addplaceholder:'Your Name' }} 62 | 63 | {{ form.password1.errors }} 64 | {{ form.password1|addclass:'form-control'|addplaceholder:'Your Password' }} 65 | 66 | {{ form.password2.errors }} 67 | {{ form.password2|addclass:'form-control'|addplaceholder:'Your Password' }} 68 |
69 | 70 | 71 |
72 |
73 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registercustomer.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Sign Up For Customer

55 | 56 | {{ form.email.errors }} 57 | {{ form.email|addclass:'form-control'|addplaceholder:'Email Address'}} 58 | 59 | 60 | {{ form.name.errors }} 61 | {{ form.name|addclass:'form-control'|addplaceholder:'Your Name' }} 62 | 63 | {{ form.password1.errors }} 64 | {{ form.password1|addclass:'form-control'|addplaceholder:'Your Password' }} 65 | 66 | {{ form.password2.errors }} 67 | {{ form.password2|addclass:'form-control'|addplaceholder:'Your Password' }} 68 |
69 | 70 | 71 |
72 |
73 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/registerbasicuser.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 | 50 |
{% csrf_token %} 51 |
52 |
53 | 54 |

Wonder Shop

55 |

Sign Up

56 |

{{ form.non_field_errors }}

57 | 58 | {{ form.email.errors }} 59 | {{ form.email|addclass:'form-control'|addplaceholder:'Email Address'}} 60 | 61 | 62 | {{ form.name.errors }} 63 | {{ form.name|addclass:'form-control'|addplaceholder:'Your Name' }} 64 | 65 | {{ form.password1.errors }} 66 | {{ form.password1|addclass:'form-control'|addplaceholder:'Your Password' }} 67 | 68 | {{ form.password2.errors }} 69 | {{ form.password2|addclass:'form-control'|addplaceholder:'Your Password' }} 70 |
71 | 72 | 73 |
74 |
75 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% load myfilters %} 4 | {% block title %} 5 | {% endblock %} 6 | {% block css %} 7 | 46 | {% endblock %} 47 | 48 | {% block body%} 49 |
{% csrf_token %} 50 |
51 |
52 | {{ form.non_field_errors }} 53 |

Wonder Shop

54 |

Sign Up For Seller

55 | 56 | {{ form.email.errors }} 57 | {{ form.email|addclass:'form-control'|addplaceholder:'Email Address'}} 58 | 59 | 60 | {{ form.name.errors }} 61 | {{ form.name|addclass:'form-control'|addplaceholder:'Your Name' }} 62 | 63 | {{ form.password1.errors }} 64 | {{ form.password1|addclass:'form-control'|addplaceholder:'Your Password' }} 65 | 66 | {{ form.password2.errors }} 67 | {{ form.password2|addclass:'form-control'|addplaceholder:'Your Password' }} 68 | 69 | {{ form.gst.errors }} 70 | {{ form.gst|addclass:'form-control'|addplaceholder:'GST' }} 71 | 72 | {{ form.warehouse_location.errors }} 73 | {{ form.warehouse_location|addclass:'form-control'|addplaceholder:'Warehouse Location' }} 74 |
75 | 76 | 77 |
78 |
79 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.forms import UserCreationForm, UserChangeForm 2 | 3 | from .models import CustomUser, Contact, Customer, Seller, SellerAdditional, ProductInCart 4 | from django import forms 5 | from django.core.validators import RegexValidator 6 | 7 | class CustomUserCreationForm(UserCreationForm): 8 | 9 | class Meta(UserCreationForm): 10 | model = CustomUser 11 | fields = ('email',) 12 | 13 | 14 | class CustomUserChangeForm(UserChangeForm): 15 | 16 | class Meta: 17 | model = CustomUser 18 | fields = ('email',) 19 | 20 | class ContactUsForm(forms.ModelForm): 21 | # email = forms.EmailField(required=True) 22 | # name = forms.CharField(max_length=5, required=True) 23 | 24 | # phone_regex = RegexValidator( regex = r'^\d{10}$',message = "phone number should exactly be in 10 digits") 25 | # phone = forms.CharField(max_length=255, required=True, validators=[phone_regex]) 26 | # query = forms.CharField(widget = forms.Textarea) 27 | class Meta: 28 | model = Contact 29 | fields = [ 30 | 'email', 31 | 'phone', 32 | 'query', 33 | 'name' 34 | ] 35 | 36 | class RegistrationForm(UserCreationForm): 37 | class Meta: 38 | model = Seller 39 | fields = [ 40 | 'email', 41 | 'name', 42 | 'password1', 43 | 'password2', 44 | ] 45 | 46 | class RegistrationFormSeller(UserCreationForm): 47 | gst = forms.CharField(max_length=10) 48 | warehouse_location = forms.CharField(max_length=1000) 49 | class Meta: 50 | model = Seller 51 | fields = [ 52 | 'email', 53 | 'name', 54 | 'password1', 55 | 'password2', 56 | 'gst', 57 | 'warehouse_location' 58 | ] 59 | 60 | class RegistrationFormSeller2(forms.ModelForm): 61 | class Meta: 62 | model = SellerAdditional 63 | fields = [ 64 | 'gst', 65 | 'warehouse_location' 66 | ] 67 | 68 | 69 | class SendOtpBasicForm(forms.Form): 70 | phone_regex = RegexValidator( regex = r'^\d{10}$',message = "phone number should exactly be in 10 digits") 71 | phone = forms.CharField(max_length=255, validators=[phone_regex]) 72 | 73 | class Meta: 74 | fields = [ 75 | 'phone', 76 | ] 77 | 78 | class VerifyOtpBasicForm(forms.Form): 79 | otp_regex = RegexValidator( regex = r'^\d{4}$',message = "otp should be in six digits") 80 | otp = forms.CharField(max_length=6, validators=[otp_regex]) 81 | 82 | # class Meta: 83 | # field 84 | 85 | 86 | 87 | class CartForm(forms.ModelForm): 88 | class Meta: 89 | model = ProductInCart 90 | fields = [ 91 | 'quantity' 92 | ] 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | class RegistrationFormCustomer(UserCreationForm): 117 | class Meta: 118 | model = Customer 119 | fields = [ 120 | 'email', 121 | 'name', 122 | 'password1', 123 | 'password2', 124 | ] -------------------------------------------------------------------------------- /firstapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path, include 3 | from . import views 4 | from django.contrib import admin 5 | from django.urls import reverse_lazy 6 | from django.contrib.auth import views as auth_views 7 | 8 | from django.conf import settings 9 | from django.conf.urls.static import static 10 | 11 | urlpatterns = [ 12 | path('admin/', admin.site.urls), 13 | path('', views.Index.as_view(), name="index"), 14 | path('contactus/', views.contactus2, name="contact"), 15 | path('contactusclass/', views.ContactUs.as_view(), name="contactclass"), 16 | path('testsessions/', views.testsessions, name="testsessions"), 17 | path('firstasyncview/', views.firstasyncview, name="firstasyncview"), 18 | 19 | #path('listproducts/', views.ListProducts.as_view(), name="listproducts"), 20 | path('listproducts/', views.listProducts, name="listproducts"), 21 | path('productdetail//', views.ProductDetail.as_view(), name="productdetail"), 22 | path('addtocart//', views.addToCart, name="addtocart"), 23 | path('displaycart/', views.DisplayCart.as_view(), name="displaycart"), 24 | path('updatecart//', views.UpdateCart.as_view(), name="updatecart"), 25 | path('deletefromcart//', views.DeleteFromCart.as_view(), name="deletefromcart"), 26 | 27 | 28 | path('addtopremium/', views.addToPremiumGroup, name="addtopremium"), 29 | #path('premiumproducts/', views.premiumProducts, name="premiumproducts"), 30 | path('premiumproducts/', views.PremiumProducts.as_view(), name="premiumproducts"), 31 | 32 | path('api/listproductsapi/', views.listProductsApi, name="listproductsapi"), 33 | path('api/suggestionapi/', views.suggestionApi, name="suggestionapi"), 34 | 35 | # Payment APIs 36 | path('payment/', views.payment, name = 'payment'), 37 | path('handlerequest/', views.handlerequest, name = 'handlerequest'), 38 | # Generating Invoice 39 | path('generateinvoice//', views.GenerateInvoice.as_view(), name = 'generateinvoice'), 40 | 41 | 42 | # Authentication Endpoints 43 | path('signup/', views.RegisterView.as_view(), name="signup"), 44 | path('login/', views.LoginViewUser.as_view(), name="login"), 45 | path('logout/', views.LogoutViewUser.as_view(), name="logout"), 46 | path('activate//', views.activate, name='activate'), 47 | 48 | 49 | # change password 50 | path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='firstapp/registration/password_change_done.html'), 51 | name='password_change_done'), 52 | 53 | path('password_change/', auth_views.PasswordChangeView.as_view(template_name='firstapp/registration/password_change.html', success_url = reverse_lazy("password_change_done")), 54 | name='password_change'), 55 | 56 | #Forgot password 57 | path('reset///',auth_views.PasswordResetConfirmView.as_view(template_name = "firstapp/registration/password_reset_form.html", success_url = reverse_lazy("password_reset_complete")), 58 | name="password_reset_confirm"), # 3 59 | path('reset_password/',auth_views.PasswordResetView.as_view(template_name = "firstapp/registration/password_reset.html", success_url = reverse_lazy("password_reset_done"), email_template_name = 'firstapp/registration/forgot_password_email.html'), 60 | name="reset_password"), # 1 61 | path('reset_password_sent/',auth_views.PasswordResetDoneView.as_view(template_name = "firstapp/registration/password_reset_sent.html"), 62 | name="password_reset_done"), # 2 63 | 64 | path('reset_password_complete/',auth_views.PasswordResetCompleteView.as_view(template_name = "firstapp/registration/password_reset_done.html"), 65 | name="password_reset_complete"), # 4 66 | 67 | ] 68 | 69 | 70 | # when debug=True 71 | #if settings.DEBUG: 72 | #urlpatterns += static(settings.STATIC_URL ,document_root = settings.STATIC_ROOT) 73 | urlpatterns += static(settings.MEDIA_URL ,document_root = settings.MEDIA_ROOT) 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | # path('signupcustomer/', views.RegisterViewCustomer.as_view(), name="signupcustomer"), 89 | # path('login/', views.LoginViewUser.as_view(), name="login"), 90 | # path('logout/', views.LogoutViewUser.as_view(), name="logout"), -------------------------------------------------------------------------------- /firstapp/templates/firstapp/payment/invoice.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% load static %} 4 | 5 | Invoice WonderShop 6 | 145 | 146 | 147 | 148 |
149 | 155 |

INVOICE

156 |
157 |
WonderShop
158 | 159 | 160 |
161 |
162 |
CLIENT: {{name}}
163 | 164 |
DATE: {{date}}
165 |
INVOICE ID: {{order_id}}
166 |
TRANSACTION ID: {{transaction_id}}
167 |
168 |
169 |
170 |
171 |
172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | {% for i in order.productinorder_set.all %} 182 | 183 | 184 | 185 | 186 | 187 | 188 | {% endfor %} 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 |
PRODUCTQUANTITYPRICE
{{i.product}}{{i.quantity}}{{i.price}}
TOTAL: {{amount}}
197 | 198 |
199 |

*All values are in INR

200 | 201 | 202 | -------------------------------------------------------------------------------- /seller/templates/seller/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% load hosts %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | {% block title %}{% endblock %} 14 | {% block css %}{% endblock %} 15 | 16 | 17 | 18 |

77 | 78 | {% block body %} 79 | {% endblock %} 80 | 81 | 82 | 83 | 84 | 87 | 88 | 92 | 93 | {% block js %} 94 | {% endblock %} 95 | 96 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% load hosts %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | {% block title %}{% endblock %} 14 | {% block css %}{% endblock %} 15 | 16 | 17 | 18 | 75 | {% if messages %} 76 | {% for message in messages %} 77 | 83 | {% endfor %} 84 | {% endif %} 85 | 86 | {% block body %} 87 | {% endblock %} 88 | 89 | 90 | 91 | 92 | 95 | 96 | 100 | 101 | {% block js %} 102 | {% endblock %} 103 | 104 | -------------------------------------------------------------------------------- /firstapp/templates/firstapp/listproducts.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load hosts %} 3 | {% load static %} 4 | {% load myfilters %} 5 | {% block title %} 6 | {% endblock %} 7 | {% block css %} 8 | 9 | 34 | {% endblock %} 35 | 36 | {% block body%} 37 |
38 |
39 |
40 | 41 |
42 | 44 | 45 |
46 | 47 | 48 | 55 | 56 | 57 | 64 | 65 | 66 | 67 |
68 |
69 |
70 | {% for i in product %} 71 |
72 |
73 | ... 74 |
75 |
{{i.product_name}}
76 |

{{i.price}}

77 |
78 | Add To Cart 79 |
80 |
81 | {% endfor %} 82 |
83 | 84 | 85 | 86 | 87 |
88 | 89 | 90 | {% if is_paginated %} 91 | 115 | {% endif %} 116 |
117 | 118 | 119 | 120 |
121 | {% endblock %} 122 | 123 | {% block js %} 124 | 163 | 164 | 165 | 166 | 167 | 176 | {% endblock %} -------------------------------------------------------------------------------- /firstproject/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for firstproject project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | import environ 15 | env = environ.Env( 16 | # set casting, default value, if DEBUG=True/On in .env then True otherwise False 17 | DEBUG=(bool, False) 18 | ) 19 | # reading .env file 20 | environ.Env.read_env() 21 | 22 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 23 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 24 | 25 | 26 | 27 | 28 | # Quick-start development settings - unsuitable for production 29 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 30 | 31 | # SECURITY WARNING: keep the secret key used in production secret! 32 | SECRET_KEY = 'f%dk29k%3z7c1!&1587(2gv=@-xao^ko&0s=@sg8=fembuf)8a' 33 | 34 | # SECURITY WARNING: don't run with debug turned on in production! 35 | DEBUG = True 36 | 37 | ALLOWED_HOSTS = ['www.wondershop.in', 'services.wondershop.in', '127.0.0.1', 'admin.wondershop.in'] 38 | 39 | 40 | # Application definition 41 | 42 | INSTALLED_APPS = [ 43 | 'django.contrib.admin', 44 | 'django.contrib.auth', 45 | 'django.contrib.contenttypes', 46 | 'django.contrib.sessions', 47 | 'django.contrib.messages', 48 | 'django.contrib.staticfiles', 49 | #'django.contrib.sites', 50 | 51 | 'firstapp', 52 | 'seller', 53 | 'django_hosts', 54 | 55 | #'channels', 56 | 57 | #Gunicorn development server 58 | #'dj_static', 59 | ] 60 | 61 | # CACHES = { 62 | # 'default': { 63 | # 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 64 | # 'LOCATION': 'my_cache_table', 65 | # } 66 | # } 67 | 68 | #SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" 69 | #SESSION_ENGINE = "django.contrib.sessions.backends.file" 70 | #SESSION_FILE_PATH = r"D:\Mastering Django\firstproject" 71 | #SESSION_ENGINE = "django.contrib.sessions.backends.cache" 72 | #SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" 73 | #SESSION_CACHE_ALIAS 74 | 75 | MIDDLEWARE = [ 76 | 'django_hosts.middleware.HostsRequestMiddleware', 77 | 'django.middleware.security.SecurityMiddleware', 78 | 'django.contrib.sessions.middleware.SessionMiddleware', 79 | 'django.middleware.common.CommonMiddleware', 80 | 'django.middleware.csrf.CsrfViewMiddleware', 81 | 'django.contrib.auth.middleware.AuthenticationMiddleware', #method_is_async = False 82 | 'django.contrib.messages.middleware.MessageMiddleware', 83 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 84 | 'django_hosts.middleware.HostsResponseMiddleware' 85 | ] 86 | 87 | 88 | # AUTHENTICATION_BACKENDS = ( 89 | # 'firstapp.backends.MyAuthBackend', # our custom authentication backend 90 | # 'django.contrib.auth.backends.ModelBackend' # fallback to default authentication backend if first fails 91 | # ) 92 | 93 | ROOT_URLCONF = 'firstproject.urls' 94 | ROOT_HOSTCONF = 'firstproject.hosts' 95 | DEFAULT_HOST = 'www' 96 | PARENT_HOST = 'wondershop.in' 97 | HOST_PORT = "8000" 98 | 99 | TEMPLATES = [ 100 | { 101 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 102 | 'DIRS': [], 103 | 'APP_DIRS': True, 104 | 'OPTIONS': { 105 | 'context_processors': [ 106 | 'django.template.context_processors.debug', 107 | 'django.template.context_processors.request', 108 | 'django.contrib.auth.context_processors.auth', 109 | 'django.contrib.messages.context_processors.messages', 110 | ], 111 | }, 112 | }, 113 | ] 114 | 115 | WSGI_APPLICATION = 'firstproject.wsgi.application' 116 | 117 | ASGI_APPLICATION = 'firstproject.asgi.application' 118 | 119 | 120 | # Database 121 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 122 | 123 | DATABASES = { 124 | 'default': { 125 | 'ENGINE': 'django.db.backends.sqlite3', 126 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 127 | }, 128 | # 'default': { 129 | # 'ENGINE': 'django.db.backends.mysql', 130 | # 'NAME': 'TestDB', 131 | # 'USER': 'root', 132 | # 'PASSWORD': '', 133 | # 'HOST': '127.0.0.1', 134 | # 'PORT': '3306', 135 | # } 136 | } 137 | 138 | 139 | # Password validation 140 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 141 | 142 | AUTH_PASSWORD_VALIDATORS = [ 143 | { 144 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 145 | }, 146 | { 147 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 148 | }, 149 | { 150 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 151 | }, 152 | { 153 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 154 | }, 155 | ] 156 | 157 | 158 | # Internationalization 159 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 160 | 161 | LANGUAGE_CODE = 'en-us' 162 | 163 | TIME_ZONE = 'UTC' 164 | 165 | USE_I18N = True 166 | 167 | USE_L10N = True 168 | 169 | USE_TZ = True 170 | 171 | 172 | # Static files (CSS, JavaScript, Images) 173 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 174 | 175 | 176 | STATIC_URL = '/static/' 177 | STATIC_ROOT = os.path.join(BASE_DIR , 'static_cdn') # when deployemnt do collectstatic command and then in static file settings in web server(apache/nginx) mention alias as '/static' after it path of static_cdn folder or static folder as set by you 178 | MEDIA_URL = '/media/' 179 | MEDIA_ROOT = os.path.join(BASE_DIR , 'media') 180 | STATICFILES_DIRS = [ 181 | os.path.join(BASE_DIR, "static"), # mention folders in saticfiles_dirs where django has to look for static files except static folder inside apps during development 182 | ] 183 | 184 | 185 | 186 | AUTH_USER_MODEL = 'firstapp.CustomUser' 187 | 188 | 189 | LOGIN_URL = 'login' 190 | LOGIN_REDIRECT_URL = 'index' 191 | LOGOUT_REDIRECT_URL = 'index' 192 | 193 | from django.contrib.messages import constants as messages 194 | MESSAGE_TAGS = { 195 | messages.ERROR : 'danger' # here we can override tags meaning in place of there actual color replace by another 196 | } 197 | 198 | 199 | #SMTP SETTINGS 200 | EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" 201 | EMAIL_USE_TLS = True 202 | EMAIL_HOST = "smtp.gmail.com" 203 | EMAIL_PORT = 587 204 | EMAIL_HOST_USER ='priyanshuguptacontact@gmail.com' 205 | EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD') 206 | DEFAULT_FROM_EMAIL = 'Testing ' 207 | 208 | #PASSWORD_RESET_TIMEOUT_DAYS = "7" 209 | 210 | 211 | # PAYMENT GATEWAY SETTINGS 212 | razorpay_id = env('RAZORPAY_ID') 213 | razorpay_account_id = env('razorpay_account_id') 214 | 215 | 216 | -------------------------------------------------------------------------------- /firstapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.admin import UserAdmin 3 | from django.contrib.auth.models import User 4 | 5 | # Register your models here. 6 | 7 | from .models import Cart, Product, ProductInCart, Order, ProductInOrder, Deal, Customer, Seller, Contact, SellerAdditional, OtpModel, PremiumProduct 8 | 9 | from django.contrib import admin 10 | from django.contrib.auth.admin import UserAdmin 11 | 12 | from .forms import CustomUserCreationForm, CustomUserChangeForm 13 | from .models import CustomUser 14 | 15 | class SellerAdditionalInline(admin.TabularInline): 16 | model = SellerAdditional 17 | 18 | class CustomUserAdmin(UserAdmin): 19 | add_form = CustomUserCreationForm 20 | form = CustomUserChangeForm 21 | model = CustomUser 22 | list_display = ('email', 'is_staff', 'is_active',) 23 | list_filter = ('email', 'is_staff', 'is_active',) 24 | fieldsets = ( 25 | (None, {'fields': ('email', 'phone', 'name','type', 'password')}), 26 | ('Permissions', {'fields': ('is_staff', 'is_active', 'is_superuser', 'groups', 'user_permissions',)}), #'is_customer' , 'is_seller' 27 | ) 28 | add_fieldsets = ( 29 | (None, { 30 | 'classes': ('wide',), 31 | 'fields': ('email', 'phone', 'name', 'type', 'password1', 'password2', 'is_staff', 'is_active')} 32 | ), 33 | ) 34 | search_fields = ('email',) 35 | ordering = ('email',) 36 | 37 | class SellerAdmin(admin.ModelAdmin): 38 | inlines = ( 39 | SellerAdditionalInline, 40 | ) 41 | 42 | 43 | 44 | 45 | 46 | #admin.site.unregister(User) 47 | admin.site.register(CustomUser, CustomUserAdmin) 48 | 49 | 50 | #admin.site.register(User, UserAdmin) 51 | 52 | 53 | class ProductInCartInline(admin.TabularInline): 54 | model = ProductInCart 55 | 56 | class CartInline(admin.TabularInline): 57 | model = Cart #onetoonefield foreignkey 58 | 59 | class DealInline(admin.TabularInline): 60 | model = Deal.user.through 61 | 62 | 63 | # class UserAdmin(UserAdmin): 64 | # model = User 65 | # list_display = ('username', 'get_cart', 'is_staff', 'is_active',) 66 | # list_filter = ('username', 'is_staff', 'is_active', 'is_superuser') 67 | # fieldsets = ( 68 | # (None, {'fields': ('username', 'password')}), 69 | # ('Permissions', {'fields': ('is_staff', ('is_active' , 'is_superuser'), )}), 70 | # ('Important dates',{'fields': ('last_login', 'date_joined')}), 71 | # #('Cart', {'fields': ('get_cart',)}) 72 | # ('Advanced options', { 73 | # 'classes': ('collapse',), 74 | # 'fields': ('groups', 'user_permissions'), 75 | # }), 76 | # ) 77 | # add_fieldsets = ( 78 | # (None, { 79 | # 'classes': ('wide',), # class for css 80 | # 'fields': ('username', 'password1', 'password2', 'is_staff', 'is_active', 'is_superuser', 'groups')} # fields shown on create user page on admin panel 81 | # ), 82 | # ) 83 | # inlines = [ 84 | # CartInline, DealInline 85 | # ] 86 | # def get_cart(self,obj): # this function only works in list_display 87 | # return obj.cart # through reverse related relationship 88 | # search_fields = ('username',) #search_filter for search bar 89 | # ordering = ('username',) 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | # from django.utils.html import format_html 100 | # from django.urls import reverse 101 | # def linkify(field_name): 102 | # """ 103 | # Converts a foreign key value into clickable links. 104 | 105 | # If field_name is 'parent', link text will be str(obj.parent) 106 | # Link will be admin url for the admin url for obj.parent.id:change 107 | # """ 108 | # def _linkify(obj): 109 | # linked_obj = getattr(obj, field_name) 110 | # if linked_obj is None: 111 | # return '-' 112 | # app_label = linked_obj._meta.app_label 113 | # model_name = linked_obj._meta.model_name 114 | # view_name = f'admin:{app_label}_{model_name}_change' 115 | # link_url = reverse(view_name, args=[linked_obj.pk]) 116 | # return format_html('{}', link_url, linked_obj) 117 | 118 | # _linkify.short_description = field_name # Sets column name 119 | # return _linkify 120 | 121 | 122 | 123 | @admin.register(Cart) # through register decorator 124 | class CartAdmin(admin.ModelAdmin): 125 | model = Cart 126 | list_display = ('user','staff', 'created_on',) # here user__is_staff will not work 127 | list_filter = ('user', 'created_on',) 128 | #fields = ('staff',) # either fields or fieldset 129 | fieldsets = ( 130 | (None, {'fields': ('user', 'created_on',)}), # only direct relationship no nested relationship('__') ex. user__is_staff 131 | #('User', {'fields': ('staff',)}), 132 | ) 133 | inlines = ( 134 | ProductInCartInline, 135 | ) 136 | # To display only in list_display 137 | def staff(self,obj): 138 | return obj.user.is_staff 139 | # staff.empty_value_display = '???' 140 | staff.admin_order_field = 'user__is_staff' #Allows column order sorting 141 | staff.short_description = 'Staff User' #Renames column head 142 | 143 | #Filtering on side - for some reason, this works 144 | list_filter = ['user__is_staff', 'created_on',] # with direct foreign key(user) no error but not shown in filters, with function error 145 | # ordering = ['user',] 146 | search_fields = ['user__username'] # with direct foreign key no error but filtering not possible directly 147 | 148 | 149 | 150 | # class DealAdmin(admin.ModelAdmin): 151 | # inlines = [ 152 | # DealInline, 153 | # ] 154 | # exclude = ('user',) 155 | 156 | 157 | 158 | class ProductInOrderInline(admin.TabularInline): 159 | model = ProductInOrder 160 | 161 | @admin.register(Order) # through register decorator 162 | class CartAdmin(admin.ModelAdmin): 163 | model = Cart 164 | inlines = ( 165 | ProductInOrderInline, 166 | ) 167 | 168 | #admin.site.register(Cart) 169 | admin.site.register(Product) 170 | admin.site.register(ProductInCart) 171 | admin.site.register(Deal)#, DealAdmin) 172 | #admin.site.register(UserType) 173 | admin.site.register(Customer) 174 | admin.site.register(Seller, SellerAdmin) 175 | admin.site.register(Contact) 176 | admin.site.register(SellerAdditional) 177 | 178 | 179 | #1 using simple database for sessions 180 | from django.contrib.sessions.models import Session 181 | import pprint 182 | 183 | # If you remove this model admin below for sessions then you will see encrypted data only 184 | # class SessionAdmin(admin.ModelAdmin): 185 | # def _session_data(self, obj): 186 | # return obj.get_decoded() 187 | # list_display = ['session_key', '_session_data', 'expire_date'] 188 | # admin.site.register(Session, SessionAdmin) 189 | 190 | # class SessionAdmin(admin.ModelAdmin): 191 | # def _session_data(self, obj): 192 | # return pprint.pformat(obj.get_decoded()).replace('\n', '
\n') 193 | # _session_data.allow_tags=True 194 | # list_display = ['session_key', '_session_data', 'expire_date'] 195 | # readonly_fields = ['_session_data'] 196 | # exclude = ['session_data'] 197 | # date_hierarchy='expire_date' 198 | 199 | class SessionAdmin(admin.ModelAdmin): 200 | def _session_data(self, obj): 201 | return pprint.pformat(obj.get_decoded()).replace('\n', '
\n') 202 | _session_data.allow_tags=True 203 | list_display = ['session_key', '_session_data', 'expire_date'] 204 | readonly_fields = ['_session_data'] 205 | exclude = ['session_data'] 206 | 207 | admin.site.register(Session, SessionAdmin) 208 | 209 | admin.site.register(ProductInOrder) 210 | 211 | #admin.site.register(Session) 212 | 213 | 214 | #from django.contrib.sites.models import Site 215 | #admin.site.register(Site) 216 | 217 | 218 | # from django_cache.models import my_cache_table 219 | # admin.site.register(my_cache_table) 220 | 221 | 222 | admin.site.register(OtpModel) 223 | admin.site.register(PremiumProduct) -------------------------------------------------------------------------------- /firstapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from django.contrib.auth.models import User 4 | from django.core.validators import RegexValidator 5 | from django.utils import timezone 6 | # Create your models here. 7 | from multiselectfield import MultiSelectField 8 | 9 | 10 | from django.contrib.auth.models import AbstractUser, AbstractBaseUser 11 | from django.utils.translation import ugettext_lazy as _ 12 | 13 | from .managers import CustomUserManager 14 | 15 | from django.contrib.auth.models import PermissionsMixin 16 | 17 | from django.db.models import Q 18 | from datetime import timedelta 19 | 20 | 21 | # class UserType(models.Model): 22 | # CUSTOMER = 1 23 | # SELLER = 2 24 | # TYPE_CHOICES = ( 25 | # (SELLER, 'Seller'), 26 | # (CUSTOMER, 'Customer') 27 | # ) 28 | 29 | # id = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, primary_key=True) 30 | 31 | # def __str__(self): 32 | # return self.get_id_display() 33 | 34 | class LowercaseEmailField(models.EmailField): 35 | """ 36 | Override EmailField to convert emails to lowercase before saving. 37 | """ 38 | def to_python(self, value): 39 | """ 40 | Convert email to lowercase. 41 | """ 42 | value = super(LowercaseEmailField, self).to_python(value) 43 | # Value can be None so check that it's a string before lowercasing. 44 | if isinstance(value, str): 45 | return value.lower() 46 | return value 47 | 48 | class CustomUser(AbstractBaseUser, PermissionsMixin): 49 | # username = None 50 | email = LowercaseEmailField(_('email address'), unique=True) 51 | name = models.CharField(max_length=255) 52 | is_staff = models.BooleanField(default=False) 53 | is_active = models.BooleanField(default=True) 54 | date_joined = models.DateTimeField(default=timezone.now) 55 | 56 | # if you require phone number field in your project 57 | phone_regex = RegexValidator( regex = r'^\d{10}$',message = "phone number should exactly be in 10 digits") 58 | phone = models.CharField(max_length=255, validators=[phone_regex], blank = True, null=True) # you can set it unique = True 59 | 60 | # is_customer = models.BooleanField(default=True) 61 | # is_seller = models.BooleanField(default = False) 62 | 63 | # type = ( 64 | # (1, 'Seller'), 65 | # (2, 'Customer') 66 | # ) 67 | # user_type = models.IntegerField(choices = type, default=1) 68 | 69 | #usertype = models.ManyToManyField(UserType) 70 | 71 | class Types(models.TextChoices): 72 | SELLER = "Seller", "SELLER" 73 | CUSTOMER = "Customer", "CUSTOMER" 74 | 75 | # Types = ( 76 | # (1, 'SELLER'), 77 | # (2, 'CUSTOMER') 78 | # ) 79 | # type = models.IntegerField(choices=Types, default=2) 80 | 81 | default_type = Types.CUSTOMER 82 | 83 | #type = models.CharField(_('Type'), max_length=255, choices=Types.choices, default=default_type) 84 | type = MultiSelectField(choices=Types.choices, default=[], null=True, blank=True) 85 | 86 | 87 | 88 | USERNAME_FIELD = 'email' 89 | REQUIRED_FIELDS = [] 90 | 91 | objects = CustomUserManager() 92 | 93 | def __str__(self): 94 | return self.email 95 | 96 | #place here 97 | # if not the code below then taking default value in User model not in proxy models 98 | def save(self, *args, **kwargs): 99 | if not self.id: 100 | #self.type = self.default_type 101 | self.type.append(self.default_type) 102 | return super().save(*args, **kwargs) 103 | 104 | class CustomerAdditional(models.Model): 105 | user = models.OneToOneField(CustomUser, on_delete = models.CASCADE) 106 | address = models.CharField(max_length=1000) 107 | 108 | 109 | class SellerAdditional(models.Model): 110 | user = models.OneToOneField(CustomUser, on_delete = models.CASCADE) 111 | gst = models.CharField(max_length=10) 112 | warehouse_location = models.CharField(max_length=1000) 113 | 114 | # Model Managers for proxy models 115 | class SellerManager(models.Manager): 116 | def get_queryset(self, *args, **kwargs): 117 | #return super().get_queryset(*args, **kwargs).filter(type = CustomUser.Types.SELLER) 118 | return super().get_queryset(*args, **kwargs).filter(Q(type__contains = CustomUser.Types.SELLER)) 119 | 120 | class CustomerManager(models.Manager): 121 | def get_queryset(self, *args, **kwargs): 122 | #return super().get_queryset(*args, **kwargs).filter(type = CustomUser.Types.CUSTOMER) 123 | return super().get_queryset(*args, **kwargs).filter(Q(type__contains = CustomUser.Types.CUSTOMER)) 124 | 125 | 126 | # Proxy Models. They do not create a seperate table 127 | class Seller(CustomUser): 128 | default_type = CustomUser.Types.SELLER 129 | objects = SellerManager() 130 | class Meta: 131 | proxy = True 132 | 133 | def sell(self): 134 | print("I can sell") 135 | 136 | @property 137 | def showAdditional(self): 138 | return self.selleradditional 139 | 140 | class Customer(CustomUser): 141 | default_type = CustomUser.Types.CUSTOMER 142 | objects = CustomerManager() 143 | class Meta: 144 | proxy = True 145 | 146 | def buy(self): 147 | print("I can buy") 148 | 149 | @property 150 | def showAdditional(self): 151 | return self.customeradditional 152 | 153 | 154 | class Contact(models.Model): 155 | email = models.EmailField() 156 | name = models.CharField(max_length=5) 157 | phone_regex = RegexValidator( regex = r'^\d{10}$',message = "phone number should exactly be in 10 digits") 158 | phone = models.CharField(max_length=255, validators=[phone_regex]) 159 | query = models.TextField() 160 | 161 | 162 | 163 | 164 | 165 | class Product(models.Model): 166 | product_id = models.AutoField(primary_key=True) 167 | product_name = models.CharField(max_length=15) 168 | image = models.ImageField(upload_to = "firstapp/productimages", default = None, null = True, blank = True) 169 | price = models.FloatField() 170 | brand = models.CharField(max_length=1000) 171 | date_added = models.DateTimeField(default=timezone.now) 172 | 173 | #class Meta: 174 | #ordering = ['-price'] # default ordering whenever you query to database retrieval in order as stored in DB ---> ordering ---> returned as a queryset where called 175 | 176 | @classmethod 177 | def updateprice(cls,product_id, price): 178 | product = cls.objects.filter(product_id = product_id) 179 | product = product.first() 180 | product.price = price 181 | product.save() 182 | return product 183 | 184 | @classmethod 185 | def create(cls, product_name, price): 186 | product = Product(product_name = product_name, price = price) 187 | product.save() 188 | return product 189 | 190 | 191 | # @staticmethod 192 | # def a_static_method(): 193 | # """A static method has no information about instances or classes 194 | # unless explicitly given. It just lives in the class (and thus its 195 | # instances') namespace. 196 | # """ 197 | # return some_function_h() 198 | 199 | def __str__(self): 200 | return self.product_name 201 | 202 | 203 | 204 | class CartManager(models.Manager): 205 | def create_cart(self, user): 206 | cart = self.create(user = user) 207 | # you can perform more operations 208 | return cart 209 | 210 | class Cart(models.Model): 211 | cart_id = models.AutoField(primary_key=True) 212 | user = models.OneToOneField(CustomUser, on_delete = models.CASCADE) 213 | created_on = models.DateTimeField(default=timezone.now) 214 | 215 | objects = CartManager() 216 | 217 | class ProductInCart(models.Model): 218 | class Meta: 219 | unique_together = (('cart', 'product'),) 220 | product_in_cart_id = models.AutoField(primary_key=True) 221 | cart = models.ForeignKey(Cart, on_delete = models.CASCADE) 222 | product = models.ForeignKey(Product, on_delete = models.CASCADE) 223 | quantity = models.PositiveIntegerField() 224 | 225 | 226 | class Order(models.Model): 227 | status_choices = ( 228 | (1, 'Not Packed'), 229 | (2, 'Ready For Shipment'), 230 | (3, 'Shipped'), 231 | (4, 'Delivered') 232 | ) 233 | payment_status_choices = ( 234 | (1, 'SUCCESS'), 235 | (2, 'FAILURE' ), 236 | (3, 'PENDING'), 237 | ) 238 | user = models.ForeignKey(CustomUser, on_delete=models.CASCADE) 239 | status = models.IntegerField(choices = status_choices, default=1) 240 | 241 | total_amount = models.FloatField() 242 | payment_status = models.IntegerField(choices = payment_status_choices, default=3) 243 | order_id = models.CharField(unique=True, max_length=100, null=True, blank=True, default=None) 244 | datetime_of_payment = models.DateTimeField(default=timezone.now) 245 | # related to razorpay 246 | razorpay_order_id = models.CharField(max_length=500, null=True, blank=True) 247 | razorpay_payment_id = models.CharField(max_length=500, null=True, blank=True) 248 | razorpay_signature = models.CharField(max_length=500, null=True, blank=True) 249 | 250 | 251 | def save(self, *args, **kwargs): 252 | if self.order_id is None and self.datetime_of_payment and self.id: 253 | self.order_id = self.datetime_of_payment.strftime('PAY2ME%Y%m%dODR') + str(self.id) 254 | return super().save(*args, **kwargs) 255 | 256 | def __str__(self): 257 | return self.user.email + " " + str(self.id) 258 | 259 | 260 | class ProductInOrder(models.Model): 261 | class Meta: 262 | unique_together = (('order', 'product'),) 263 | order = models.ForeignKey(Order, on_delete = models.CASCADE) 264 | product = models.ForeignKey(Product, on_delete = models.CASCADE) 265 | quantity = models.PositiveIntegerField() 266 | price = models.FloatField() 267 | 268 | 269 | 270 | 271 | class Deal(models.Model): 272 | user = models.ManyToManyField(CustomUser) 273 | deal_name = models.CharField(max_length=255) 274 | 275 | 276 | 277 | class OtpModel(models.Model): 278 | otp_regex = RegexValidator( regex = r'^\d{6}$',message = "otp should be in six digits") 279 | otp = models.CharField(max_length=6, validators=[otp_regex]) 280 | phone_regex = RegexValidator( regex = r'^\d{10}$',message = "phone number should exactly be in 10 digits") 281 | phone = models.CharField(max_length=255, validators=[phone_regex]) 282 | expiry = models.DateTimeField(default = (timezone.now() + timedelta(minutes = 5))) 283 | is_verified = models.BooleanField(default=False) 284 | 285 | # expiry_after_verified 286 | 287 | 288 | 289 | # class Category(models.Model): 290 | # category_name = models.CharField(max_length=1000) 291 | 292 | # class Subcategory(models.Model): 293 | # subcategory_name = models.CharField(max_length=1000) 294 | # category = models.ForeignKey(Category, on_delete = models.CASCADE) 295 | 296 | 297 | 298 | class PremiumProduct(models.Model): 299 | product_name = models.CharField(max_length=15) 300 | image = models.ImageField(upload_to = "firstapp/premiumproductimages", default = None, null = True, blank = True) 301 | price = models.FloatField() 302 | brand = models.CharField(max_length=1000) 303 | date_added = models.DateTimeField(default=timezone.now) 304 | 305 | # # custom permissions dependent to a specific model 306 | class Meta: 307 | permissions = ( 308 | ('can_avail_premium_delivery', 'can avail for premium delivery on premium products'), 309 | ('can_add_premium_discount', 'can avail more premium discount on premium products') 310 | ) 311 | 312 | 313 | 314 | class CustomPermissions(models.Model): 315 | 316 | class Meta: 317 | 318 | managed = False # No database table creation or deletion \ 319 | # operations will be performed for this model. 320 | 321 | default_permissions = () # disable "add", "change", "delete" 322 | # and "view" default permissions 323 | 324 | # All the custom permissions not related to models on Manufacturer 325 | permissions = ( 326 | ('accept_order', 'can accept order'), 327 | ('reject_order', 'can reject order'), 328 | ('view_order', 'can view order'), 329 | ('change_order', 'can change order'), 330 | ('view_return', 'can view return'), 331 | ('accept_return', 'can accept return'), 332 | ('reject_return', 'can reject return'), 333 | ('change_return', 'can change return'), 334 | ('view_dashboard', 'can view dashboard'), 335 | ) 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | -------------------------------------------------------------------------------- /seller/templates/seller/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'seller/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | 121 | {% endblock %} 122 | 123 | {% block body%} 124 | 125 |
126 | Hello World! 127 | 128 | {{age}} 129 | {{array}} 130 | {% for i in array %} 131 | {{i}} 132 | {% endfor %} 133 | {{dic}} 134 | {% for key,value in dic.items %} 135 | {{key}} {{value}} 136 | {% endfor %} 137 |
138 | {{dic.a}} 139 | 198 | 199 | 200 | 202 | 203 | 204 |
205 | 206 | 207 |
208 |
209 | 212 | Placeholder 213 | 140x140 215 | 216 | 217 |

Heading

218 |

Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies 219 | vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo 220 | cursus magna.

221 |

View details »

222 |
223 |
224 | 227 | Placeholder 228 | 140x140 230 | 231 | 232 |

Heading

233 |

Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras 234 | mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris 235 | condimentum nibh.

236 |

View details »

237 |
238 |
239 | 242 | Placeholder 243 | 140x140 245 | 246 | 247 |

Heading

248 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula 249 | porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, 250 | ut fermentum massa justo sit amet risus.

251 |

View details »

252 |
253 |
254 | 255 | 256 | 257 | 258 |
259 | 260 |
261 |
262 |

First featurette heading. It’ll blow your 263 | mind.

264 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 265 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 266 | tellus ac cursus commodo.

267 |
268 |
269 | 272 | Placeholder 273 | 500x500 275 | 276 | 277 |
278 |
279 | 280 |
281 | 282 |
283 |
284 |

Oh yeah, it’s that good. See for 285 | yourself.

286 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 287 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 288 | tellus ac cursus commodo.

289 |
290 |
291 | 294 | Placeholder 295 | 500x500 297 | 298 | 299 |
300 |
301 | 302 |
303 | 304 |
305 |
306 |

And lastly, this one. Checkmate.

307 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 308 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 309 | tellus ac cursus commodo.

310 |
311 |
312 | 315 | Placeholder 316 | 500x500 318 | 319 | 320 |
321 |
322 | 323 |
324 | 325 | 326 | 327 |
328 | 329 | 330 | 331 | 335 |
336 | 337 | 338 | 341 | 342 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/templates/firstapp/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'firstapp/basic.html' %} 2 | {% load static %} 3 | {% block title %} 4 | {% endblock %} 5 | {% block css %} 6 | 121 | {% endblock %} 122 | 123 | {% block body%} 124 | 125 |
126 | Hello World! 127 | 128 |

{{request.session.test}}

129 | {% if user.is_authenticated %} 130 |

{{user.name}}

131 | {% endif %} 132 | {{age}} 133 | {{array}} 134 | {% for i in array %} 135 | {{i}} 136 | {% endfor %} 137 | {{dic}} 138 | {% for key,value in dic.items %} 139 | {{key}} {{value}} 140 | {% endfor %} 141 |
142 | {{dic.a}} 143 | 202 | 203 | 204 | 206 | 207 | 208 |
209 | 210 | 211 |
212 |
213 | 216 | Placeholder 217 | 140x140 219 | 220 | 221 |

Heading

222 |

Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies 223 | vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo 224 | cursus magna.

225 |

View details »

226 |
227 |
228 | 231 | Placeholder 232 | 140x140 234 | 235 | 236 |

Heading

237 |

Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras 238 | mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris 239 | condimentum nibh.

240 |

View details »

241 |
242 |
243 | 246 | Placeholder 247 | 140x140 249 | 250 | 251 |

Heading

252 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula 253 | porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, 254 | ut fermentum massa justo sit amet risus.

255 |

View details »

256 |
257 |
258 | 259 | 260 | 261 | 262 |
263 | 264 |
265 |
266 |

First featurette heading. It’ll blow your 267 | mind.

268 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 269 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 270 | tellus ac cursus commodo.

271 |
272 |
273 | 276 | Placeholder 277 | 500x500 279 | 280 | 281 |
282 |
283 | 284 |
285 | 286 |
287 |
288 |

Oh yeah, it’s that good. See for 289 | yourself.

290 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 291 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 292 | tellus ac cursus commodo.

293 |
294 |
295 | 298 | Placeholder 299 | 500x500 301 | 302 | 303 |
304 |
305 | 306 |
307 | 308 |
309 |
310 |

And lastly, this one. Checkmate.

311 |

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis 312 | euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, 313 | tellus ac cursus commodo.

314 |
315 |
316 | 319 | Placeholder 320 | 500x500 322 | 323 | 324 |
325 |
326 | 327 |
328 | 329 | 330 | 331 |
332 | 333 | 334 | 335 | 339 |
340 | 341 | 342 | 345 | 346 | {% endblock %} -------------------------------------------------------------------------------- /firstapp/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, HttpResponse, redirect 2 | from django.http import JsonResponse 3 | from django.views.generic import TemplateView, FormView, CreateView, ListView, UpdateView, DeleteView, DetailView, View 4 | from django.core.exceptions import ValidationError 5 | from .forms import ContactUsForm, RegistrationFormSeller, RegistrationForm, RegistrationFormSeller2, CartForm 6 | from django.urls import reverse_lazy, reverse 7 | from .models import SellerAdditional, CustomUser, Contact, Product, ProductInCart, Cart 8 | from django.contrib.auth.views import LoginView, LogoutView 9 | from django.contrib.auth.mixins import LoginRequiredMixin 10 | 11 | 12 | from firstproject import settings 13 | from django.core.mail import EmailMessage 14 | from .tokens import account_activation_token 15 | from django.core.mail import send_mail 16 | from django.contrib.sites.shortcuts import get_current_site 17 | from django.utils.encoding import force_bytes, force_text 18 | from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode 19 | from django.template.loader import render_to_string 20 | from django.contrib.auth import authenticate, login, logout 21 | from django.contrib import messages 22 | 23 | from django.contrib.auth.decorators import login_required 24 | from django.views.decorators.csrf import csrf_exempt 25 | 26 | 27 | # Create your views here. 28 | # def index(request): 29 | # age = 10 30 | # arr = ['priyanshu', 'aman', 'rohit', 'shubhi'] 31 | # dic = {'a':'one', 'b':'two'} 32 | # return render(request, 'firstapp/index.html', {'age':age, 'array':arr, 'dic':dic}) 33 | # #return HttpResponse("

Hello

") 34 | 35 | class Index(TemplateView): 36 | template_name = 'firstapp/index.html' 37 | def get_context_data(self, **kwargs): 38 | age = 10 39 | arr = ['priyanshu', 'aman', 'rohit', 'shubhi'] 40 | dic = {'a':'one', 'b':'two'} 41 | context_old = super().get_context_data(**kwargs) 42 | context = {'age':age, 'array':arr, 'dic':dic, 'context_old':context_old} 43 | return context 44 | 45 | 46 | 47 | def testsessions(request): 48 | if request.session.get('test', False): 49 | print(request.session["test"]) 50 | #request.session.set_expiry(1) 51 | # if request.session['test']: 52 | # print(request.session['test']) 53 | request.session['test'] = "testing" 54 | request.session['test2'] = "testing2" 55 | return render(request, "firstapp/sessiontesting.html") 56 | 57 | 58 | 59 | 60 | 61 | def contactus(request): 62 | if request.method == 'POST': 63 | name = request.POST.get('name') 64 | email = request.POST.get('email') 65 | phone = request.POST['phone'] 66 | if len(phone)<10 or len(phone)>10: 67 | raise ValidationError("Phone number length is not right") 68 | query = request.POST['query'] 69 | print(name + " " + email + " " + phone + " " +query) 70 | return render(request, 'firstapp/contactus.html') 71 | 72 | def contactus2(request): 73 | if request.method == 'POST': 74 | form = ContactUsForm(request.POST) 75 | if form.is_valid(): #clean_data 76 | if len(form.cleaned_data.get('query'))>10: 77 | form.add_error('query', 'Query length is not right') 78 | return render(request, 'firstapp/contactus2.html', {'form':form}) 79 | form.save() 80 | return HttpResponse("Thank YOu") 81 | else: 82 | if len(form.cleaned_data.get('query'))>10: 83 | #form.add_error('query', 'Query length is not right') 84 | form.errors['__all__'] = 'Query length is not right. It should be in 10 digits.' 85 | return render(request, 'firstapp/contactus2.html', {'form':form}) 86 | return render(request, 'firstapp/contactus2.html', {'form':ContactUsForm}) 87 | 88 | class ContactUs(FormView): 89 | form_class = ContactUsForm 90 | template_name = 'firstapp/contactus2.html' 91 | #success_url = '/' #hardcoded url 92 | success_url = reverse_lazy('index') 93 | def form_valid(self, form): 94 | if len(form.cleaned_data.get('query'))>10: 95 | form.add_error('query', 'Query length is not right') 96 | return render(self.request, 'firstapp/contactus2.html', {'form':form}) 97 | form.save() 98 | response = super().form_valid(form) 99 | return response 100 | 101 | def form_invalid(self, form): 102 | if len(form.cleaned_data.get('query'))>10: 103 | form.add_error('query', 'Query length is not right') 104 | #form.errors['__all__'] = 'Query length is not right. It should be in 10 digits.' 105 | response = super().form_invalid(form) 106 | return response 107 | 108 | 109 | # class RegisterViewSeller(CreateView): 110 | # template_name = 'firstapp/register.html' 111 | # form_class = RegistrationFormSeller 112 | # success_url = reverse_lazy('index') 113 | 114 | # def post(self, request, *args, **kwargs): 115 | # response = super().post(request, *args, **kwargs) 116 | # if response.status_code == 302: 117 | # gst = request.POST.get('gst') 118 | # warehouse_location = request.POST.get('warehouse_location') 119 | # user = CustomUser.objects.get(email = request.POST.get('email')) 120 | # s_add = SellerAdditional.objects.create(user = user, gst = gst, warehouse_location = warehouse_location) 121 | # return response 122 | # else: 123 | # return response 124 | 125 | class RegisterView(CreateView): 126 | template_name = 'firstapp/registerbasicuser.html' 127 | form_class = RegistrationForm 128 | success_url = reverse_lazy('signup') 129 | 130 | def post(self, request, *args, **kwargs): 131 | #form = RegistrationForm(request.POST) 132 | user_email = request.POST.get('email') 133 | try: 134 | existing_user = CustomUser.objects.get(email = user_email) 135 | if(existing_user.is_active == False): 136 | existing_user.delete() 137 | except: 138 | pass 139 | response = super().post(request, *args, **kwargs) 140 | if response.status_code == 302: 141 | user = CustomUser.objects.get(email = user_email) 142 | user.is_active = False 143 | user.save() 144 | current_site = get_current_site(request) #www.wondershop.in:8000 127.0.0.1:8000 145 | mail_subject = 'Activate your account.' 146 | message = render_to_string('firstapp/registration/acc_active_email.html', { 147 | 'user': user, 148 | 'domain': current_site.domain, 149 | 'uid':urlsafe_base64_encode(force_bytes(user.pk)), 150 | 'token':account_activation_token.make_token(user), 151 | }) 152 | #print(message) 153 | to_email = user_email 154 | #form = RegistrationForm(request.POST) # here we are again calling all its validations 155 | form = self.get_form() 156 | try: 157 | send_mail( 158 | subject=mail_subject, 159 | message=message, 160 | from_email=settings.EMAIL_HOST_USER, 161 | recipient_list= [to_email], 162 | fail_silently=False, # if it fails due to some error or email id then it get silenced without affecting others 163 | ) 164 | messages.success(request, "link has been sent to your email id. please check your inbox and if its not there check your spam as well.") 165 | return self.render_to_response({'form':form}) 166 | except: 167 | form.add_error('', 'Error Occured In Sending Mail, Try Again') 168 | messages.error(request, "Error Occured In Sending Mail, Try Again") 169 | return self.render_to_response({'form':form}) 170 | else: 171 | return response 172 | 173 | 174 | def activate(request, uidb64, token): 175 | try: 176 | uid = force_text(urlsafe_base64_decode(uidb64)) 177 | user = CustomUser.objects.get(pk=uid) 178 | except(TypeError, ValueError, OverflowError, CustomUser.DoesNotExist) as e: 179 | user = None 180 | if user is not None and account_activation_token.check_token(user, token): 181 | user.is_active = True 182 | user.save() 183 | login(request, user) 184 | messages.success(request, "Successfully Logged In") 185 | return redirect(reverse_lazy('index')) 186 | # return HttpResponse('Thank you for your email confirmation. Now you can login your account.') 187 | else: 188 | return HttpResponse('Activation link is invalid or your account is already Verified! Try To Login') 189 | 190 | class LoginViewUser(LoginView): 191 | template_name = "firstapp/login.html" 192 | #success_url = reverse_lazy('index') 193 | 194 | # class RegisterViewSeller(LoginRequiredMixin, CreateView): 195 | # template_name = 'firstapp/registerseller.html' 196 | # form_class = RegistrationFormSeller2 197 | # success_url = reverse_lazy('index') 198 | 199 | # def form_valid(self, form): 200 | # user = self.request.user 201 | # user.type.append(user.Types.SELLER) 202 | # user.save() 203 | # form.instance.user = self.request.user 204 | # return super().form_valid(form) 205 | 206 | 207 | class LogoutViewUser(LogoutView): 208 | success_url = reverse_lazy('index') 209 | 210 | 211 | class ListProducts(ListView): 212 | template_name = "firstapp/listproducts.html" 213 | model = Product 214 | context_object_name = "product" 215 | paginate_by = 2 216 | 217 | 218 | 219 | from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator 220 | import json 221 | from django.core.serializers.json import DjangoJSONEncoder 222 | from django.db.models import Q 223 | PRODUCTS_PER_PAGE = 2 224 | def listProducts(request): 225 | 226 | ordering = request.GET.get('ordering', "") # http://www.wondershop.in:8000/listproducts/?page=1&ordering=price 227 | search = request.GET.get('search', "") 228 | price = request.GET.get('price', "") 229 | 230 | if search: 231 | product = Product.objects.filter(Q(product_name__icontains=search) | Q(brand__icontains=search)) # SQLite doesn’t support case-sensitive LIKE statements; contains acts like icontains for SQLite 232 | 233 | else: 234 | product = Product.objects.all() 235 | 236 | if ordering: 237 | product = product.order_by(ordering) 238 | 239 | if price: 240 | product = product.filter(price__lt = price) 241 | 242 | 243 | # Pagination 244 | page = request.GET.get('page',1) 245 | product_paginator = Paginator(product, PRODUCTS_PER_PAGE) 246 | try: 247 | product = product_paginator.page(page) 248 | except EmptyPage: 249 | product = product_paginator.page(product_paginator.num_pages) 250 | except: 251 | product = product_paginator.page(PRODUCTS_PER_PAGE) 252 | return render(request, "firstapp/listproducts.html", {"product":product, 'page_obj':product, 'is_paginated':True, 'paginator':product_paginator}) 253 | 254 | 255 | def suggestionApi(request): 256 | if 'term' in request.GET: 257 | search = request.GET.get('term') 258 | qs = Product.objects.filter(Q(product_name__icontains=search))[0:10] 259 | # print(list(qs.values())) 260 | # print(json.dumps(list(qs.values()), cls = DjangoJSONEncoder)) 261 | titles = list() 262 | for product in qs: 263 | titles.append(product.product_name) 264 | #print(titles) 265 | if len(qs)<10: 266 | length = 10 - len(qs) 267 | qs2 = Product.objects.filter(Q(brand__icontains=search))[0:length] 268 | for product in qs2: 269 | titles.append(product.brand) 270 | return JsonResponse(titles, safe=False) # [1,2,3,4] ---> "[1,2,3,4]" queryset ---> serialize into list or dict format ---> json format using json.dumps with a DjangoJSONEncoder(encoder to handle datetime like objects) 271 | 272 | 273 | 274 | 275 | def listProductsApi(request): 276 | # print(Product.objects.all()) 277 | # print(Product.objects.values()) 278 | #result = json.dumps(list(Product.objects.values()), sort_keys=False, indent=0, cls=DjangoJSONEncoder) # will return error if you have a datetime object as it is not jsonserializable so thats why use DjangoJSONEncoder, indent to beautify and sort_keys to sort keys 279 | #print(type(result)) #str type 280 | #print(result) 281 | result = list(Product.objects.values()) # will work like passing queryset as a context data if used by a template 282 | #print(result) 283 | #return render(request, "firstapp/listproducts.html", {"product":result}) 284 | return JsonResponse(result, safe=False) 285 | 286 | 287 | 288 | 289 | class ProductDetail(DetailView): 290 | model = Product 291 | template_name = "firstapp/productdetail.html" 292 | context_object_name = "product" 293 | 294 | 295 | @login_required 296 | def addToCart(request, id): 297 | try: 298 | cart = Cart.objects.get(user = request.user) 299 | try: 300 | product = Product.objects.get(product_id = id) 301 | try: 302 | productincart = ProductInCart.objects.get(cart = cart, product = product) 303 | productincart.quantity = productincart.quantity + 1 304 | productincart.save() 305 | messages.success(request, "Successfully added to cart") 306 | return redirect(reverse_lazy("displaycart")) 307 | except: 308 | productincart = ProductInCart.objects.create(cart = cart, product = product, quantity=1) 309 | messages.success(request, "Successfully added to cart") 310 | return redirect(reverse_lazy("displaycart")) 311 | except: 312 | messages.error(request, "Product can not be found") 313 | return redirect(reverse_lazy('listproducts')) 314 | except: 315 | cart = Cart.objects.create(user = request.user) 316 | try: 317 | product = Product.objects.get(product_id = id) 318 | productincart = ProductInCart.objects.create(cart = cart, product = product, quantity = 1) 319 | messages.success(request, "Successfully added to cart") 320 | return redirect(reverse_lazy("displaycart")) 321 | except: 322 | messages.error(request, "Error in adding to cart. Please try again") 323 | return redirect(reverse_lazy('listproducts')) 324 | 325 | 326 | class DisplayCart(LoginRequiredMixin, ListView): 327 | model = ProductInCart 328 | template_name = "firstapp/displaycart.html" 329 | context_object_name = "cart" 330 | 331 | def get_queryset(self): 332 | queryset = ProductInCart.objects.filter(cart = self.request.user.cart) 333 | return queryset 334 | 335 | class UpdateCart(LoginRequiredMixin, UpdateView): 336 | model = ProductInCart 337 | form_class = CartForm 338 | success_url = reverse_lazy("displaycart") 339 | 340 | def post(self, request, *args, **kwargs): 341 | response = super().post(request, *args, **kwargs) 342 | if response.status_code == 302: 343 | if int(request.POST.get("quantity")) == 0: 344 | productincart = self.get_object() 345 | productincart.delete() 346 | return response 347 | else: 348 | messages.error(request, "error in quantity") 349 | return redirect(reverse_lazy("displaycart")) 350 | 351 | class DeleteFromCart(LoginRequiredMixin, DeleteView): 352 | model = ProductInCart 353 | success_url = reverse_lazy("displaycart") 354 | 355 | 356 | 357 | # Adding Payment Gateway 358 | import razorpay 359 | razorpay_client = razorpay.Client(auth=(settings.razorpay_id, settings.razorpay_account_id)) 360 | 361 | from .models import Order, ProductInOrder, Cart 362 | 363 | @login_required 364 | def payment(request): 365 | if request.method == "POST": 366 | try: 367 | cart = Cart.objects.get(user = request.user) 368 | products_in_cart = ProductInCart.objects.filter(cart = cart) 369 | final_price = 0 370 | if(len(products_in_cart)>0): 371 | order = Order.objects.create(user = request.user, total_amount = 0) 372 | # order.save() 373 | for product in products_in_cart: 374 | product_in_order = ProductInOrder.objects.create(order = order, product = product.product, quantity = product.quantity, price = product.product.price) 375 | final_price = final_price + (product.product.price * product.quantity) 376 | else: 377 | return HttpResponse("No product in cart") 378 | except: 379 | return HttpResponse("No product in cart") 380 | 381 | order.total_amount = final_price 382 | order.save() 383 | 384 | order_currency = 'INR' 385 | 386 | callback_url = 'http://'+ str(get_current_site(request))+"/handlerequest/" 387 | print(callback_url) 388 | notes = {'order-type': "basic order from the website", 'key':'value'} 389 | razorpay_order = razorpay_client.order.create(dict(amount=final_price*100, currency=order_currency, notes = notes, receipt=order.order_id, payment_capture='0')) 390 | print(razorpay_order['id']) 391 | order.razorpay_order_id = razorpay_order['id'] 392 | order.save() 393 | 394 | return render(request, 'firstapp/payment/paymentsummaryrazorpay.html', {'order':order, 'order_id': razorpay_order['id'], 'orderId':order.order_id, 'final_price':final_price, 'razorpay_merchant_id':settings.razorpay_id, 'callback_url':callback_url}) 395 | else: 396 | return HttpResponse("505 Not Found") 397 | 398 | 399 | # for generating pdf invoice 400 | from io import BytesIO 401 | from django.http import HttpResponse 402 | from django.template.loader import get_template 403 | from xhtml2pdf import pisa 404 | import os 405 | 406 | 407 | 408 | def fetch_resources(uri, rel): 409 | path = os.path.join(uri.replace(settings.STATIC_URL, "")) 410 | return path 411 | 412 | def render_to_pdf(template_src, context_dict={}): 413 | template = get_template(template_src) 414 | html = template.render(context_dict) 415 | result = BytesIO() 416 | pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)#, link_callback=fetch_resources) 417 | if not pdf.err: 418 | return HttpResponse(result.getvalue(), content_type='application/pdf') 419 | return None 420 | 421 | from django.core.mail import EmailMultiAlternatives 422 | @csrf_exempt 423 | def handlerequest(request): 424 | if request.method == "POST": 425 | try: 426 | payment_id = request.POST.get('razorpay_payment_id', '') 427 | order_id = request.POST.get('razorpay_order_id','') 428 | signature = request.POST.get('razorpay_signature','') 429 | params_dict = { 430 | 'razorpay_order_id': order_id, 431 | 'razorpay_payment_id': payment_id, 432 | 'razorpay_signature': signature 433 | } 434 | try: 435 | order_db = Order.objects.get(razorpay_order_id=order_id) 436 | except: 437 | return HttpResponse("505 Not Found") 438 | order_db.razorpay_payment_id = payment_id 439 | order_db.razorpay_signature = signature 440 | order_db.save() 441 | result = razorpay_client.utility.verify_payment_signature(params_dict) 442 | if result==None: 443 | amount = order_db.total_amount * 100 #we have to pass in paisa 444 | try: 445 | razorpay_client.payment.capture(payment_id, amount) 446 | order_db.payment_status = 1 447 | order_db.save() 448 | 449 | ## For generating Invoice PDF 450 | template = get_template('firstapp/payment/invoice.html') 451 | data = { 452 | 'order_id': order_db.order_id, 453 | 'transaction_id': order_db.razorpay_payment_id, 454 | 'user_email': order_db.user.email, 455 | 'date': str(order_db.datetime_of_payment), 456 | 'name': order_db.user.name, 457 | 'order': order_db, 458 | 'amount': order_db.total_amount, 459 | } 460 | html = template.render(data) 461 | result = BytesIO() 462 | pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)#, link_callback=fetch_resources) 463 | pdf = result.getvalue() 464 | filename = 'Invoice_' + data['order_id'] + '.pdf' 465 | 466 | mail_subject = 'Recent Order Details' 467 | # message = render_to_string('firstapp/payment/emailinvoice.html', { 468 | # 'user': order_db.user, 469 | # 'order': order_db 470 | # }) 471 | context_dict = { 472 | 'user': order_db.user, 473 | 'order': order_db 474 | } 475 | template = get_template('firstapp/payment/emailinvoice.html') 476 | message = template.render(context_dict) 477 | to_email = order_db.user.email 478 | # email = EmailMessage( 479 | # mail_subject, 480 | # message, 481 | # settings.EMAIL_HOST_USER, 482 | # [to_email] 483 | # ) 484 | 485 | # for including css(only inline css works) in mail and remove autoescape off 486 | email = EmailMultiAlternatives( 487 | mail_subject, 488 | "hello", # necessary to pass some message here 489 | settings.EMAIL_HOST_USER, 490 | [to_email] 491 | ) 492 | email.attach_alternative(message, "text/html") 493 | email.attach(filename, pdf, 'application/pdf') 494 | email.send(fail_silently=False) 495 | 496 | return render(request, 'firstapp/payment/paymentsuccess.html',{'id':order_db.id}) 497 | except: 498 | order_db.payment_status = 2 499 | order_db.save() 500 | return render(request, 'firstapp/payment/paymentfailed.html') 501 | else: 502 | order_db.payment_status = 2 503 | order_db.save() 504 | return render(request, 'firstapp/payment/paymentfailed.html') 505 | except: 506 | return HttpResponse("505 not found") 507 | 508 | 509 | class GenerateInvoice(View): 510 | def get(self, request, pk, *args, **kwargs): 511 | try: 512 | order_db = Order.objects.get(id = pk, user = request.user, payment_status = 1) #you can filter using order_id as well 513 | except: 514 | return HttpResponse("505 Not Found") 515 | data = { 516 | 'order_id': order_db.order_id, 517 | 'transaction_id': order_db.razorpay_payment_id, 518 | 'user_email': order_db.user.email, 519 | 'date': str(order_db.datetime_of_payment), 520 | 'name': order_db.user.name, 521 | 'order': order_db, 522 | 'amount': order_db.total_amount, 523 | } 524 | pdf = render_to_pdf('firstapp/payment/invoice.html', data) 525 | #return HttpResponse(pdf, content_type='application/pdf') 526 | 527 | # force download 528 | if pdf: 529 | response = HttpResponse(pdf, content_type='application/pdf') 530 | filename = "Invoice_%s.pdf" %(data['order_id']) 531 | content = "inline; filename='%s'" %(filename) 532 | #download = request.GET.get("download") 533 | #if download: 534 | content = "attachment; filename=%s" %(filename) 535 | response['Content-Disposition'] = content 536 | return response 537 | return HttpResponse("Not found") 538 | 539 | 540 | 541 | 542 | 543 | 544 | # Relating To Group 545 | 546 | # to make a new group you can do that like any other models by creating a new record in it 547 | 548 | # associating a user to a group 549 | from django.contrib.auth.models import Group 550 | @login_required 551 | def addToPremiumGroup(request): 552 | group = Group.objects.get(name="premium") 553 | request.user.groups.add(group) 554 | return HttpResponse("successfully added") 555 | 556 | 557 | # checking group not permission 558 | # in function based view inside the view or "custom decorator" 559 | from .models import PremiumProduct 560 | # from .decorators import group_required 561 | # @group_required('premium') 562 | # def premiumProducts(request): 563 | # #if request.user.groups.filter(name = "premium").exists(): 564 | # product = PremiumProduct.objects.all() 565 | # return render(request, "firstapp/listpremiumproducts.html", {"product":product}) 566 | 567 | # #else: 568 | # #return HttpResponse("Only for premium members") 569 | 570 | # # in class based view inside the view or a "custom mixin" 571 | # from .mixins import CheckPremiumGroupMixin 572 | # class PremiumProducts(CheckPremiumGroupMixin, ListView): 573 | # template_name = "firstapp/listpremiumproducts.html" 574 | # model = PremiumProduct 575 | # context_object_name = "product" 576 | # #paginate_by = 2 577 | 578 | 579 | 580 | # Relating To Permission 581 | # checking permission and that permission can belong to that user or to the group that user is associated 582 | from django.contrib.auth.decorators import permission_required 583 | @permission_required('firstapp.view_premiumproduct') 584 | def premiumProducts(request): 585 | # ct = ContentType.objects.get_for_model(PremiumProduct) 586 | # if request.user.permissions.filter(codename = "view_premiumproducts" , contentype = ct).exists(): 587 | 588 | #if request.user.has_perm('firstapp.view_premiumproduct'): 589 | product = PremiumProduct.objects.all() 590 | return render(request, "firstapp/listpremiumproducts.html", {"product":product}) 591 | # else: 592 | # return HttpResponse("Not allowed") 593 | 594 | 595 | from django.contrib.auth.mixins import PermissionRequiredMixin 596 | class PremiumProducts(PermissionRequiredMixin, ListView): 597 | template_name = "firstapp/listpremiumproducts.html" 598 | model = PremiumProduct 599 | context_object_name = "product" 600 | paginate_by = 2 601 | permission_required = "firstapp.view_premiumproduct" # if using PermissionRequiredMixin 602 | 603 | 604 | # for creating permissions 605 | #1 Creating Custom Model Depenedent Permission through Code 606 | #from django.contrib.auth.models import Group, ContentType, Permission 607 | # ct = ContentType.objects.get_for_model(PremiumProduct) 608 | # permission = Permission.objects.create(codename="can_do_this", contentype = ct) 609 | 610 | 611 | #2 Creating Custom Model Dependent Permission by adding in Meta of that model 612 | 613 | #3 Creating Custom Model Independent Permission by creating a separate model for permissions 614 | 615 | # filtering existing permissions 616 | # ct = ContentType.obejcts.get_for_model(PremiumProduct) 617 | # permission = Permission.objects.get(codename='view_premiumproduct', content_type=ct) 618 | 619 | 620 | # Adding permission to user 621 | # user.permissions.add(permission) 622 | 623 | # Adding permission to group 624 | # new_group, created = Group.objects.get_or_create(name="new_group") 625 | # new_group.permissions.add(permission) 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | --------------------------------------------------------------------------------