├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── ecom_demo.gif ├── package-lock.json ├── package.json ├── personal_notes.txt ├── requirements.txt ├── src ├── accounts │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-36.pyc │ │ ├── admin.cpython-37.pyc │ │ ├── apps.cpython-36.pyc │ │ ├── apps.cpython-37.pyc │ │ ├── forms.cpython-36.pyc │ │ ├── forms.cpython-37.pyc │ │ ├── models.cpython-36.pyc │ │ ├── models.cpython-37.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── urls.cpython-37.pyc │ │ ├── views.cpython-36.pyc │ │ └── views.cpython-37.pyc │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ └── __init__.cpython-37.pyc │ ├── models.py │ ├── templates │ │ └── accounts │ │ │ ├── home.html │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── assets │ ├── bundles │ │ └── app.js │ └── js │ │ ├── components │ │ ├── checkout_script.vue │ │ ├── navigation.vue │ │ ├── onload.vue │ │ └── products.vue │ │ ├── css │ │ ├── random-css.css │ │ └── vue-carousel.css │ │ ├── helpers │ │ └── tools.vue │ │ ├── index.js │ │ └── mixins │ │ ├── base_global.js │ │ └── vue_slides.js ├── cart │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-37.pyc │ │ ├── apps.cpython-37.pyc │ │ ├── forms.cpython-37.pyc │ │ ├── models.cpython-37.pyc │ │ ├── serializers.cpython-37.pyc │ │ ├── urls.cpython-37.pyc │ │ ├── utils.cpython-37.pyc │ │ └── views.cpython-37.pyc │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20200117_0523.py │ │ ├── 0003_auto_20200117_0526.py │ │ ├── 0004_auto_20200117_0604.py │ │ ├── 0005_auto_20200117_1729.py │ │ ├── 0006_checkoutdetails.py │ │ ├── 0007_checkoutdetails_user.py │ │ ├── 0008_cartitem_user.py │ │ ├── 0009_remove_cartitem_user.py │ │ ├── 0010_cart_user.py │ │ ├── 0011_auto_20201110_2339.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-37.pyc │ │ │ ├── 0002_auto_20200117_0523.cpython-37.pyc │ │ │ ├── 0003_auto_20200117_0526.cpython-37.pyc │ │ │ ├── 0004_auto_20200117_0604.cpython-37.pyc │ │ │ ├── 0005_auto_20200117_1729.cpython-37.pyc │ │ │ ├── 0006_checkoutdetails.cpython-37.pyc │ │ │ ├── 0007_checkoutdetails_user.cpython-37.pyc │ │ │ ├── 0008_cartitem_user.cpython-37.pyc │ │ │ ├── 0009_remove_cartitem_user.cpython-37.pyc │ │ │ ├── 0010_cart_user.cpython-37.pyc │ │ │ ├── 0011_auto_20201110_2315.cpython-37.pyc │ │ │ ├── 0011_auto_20201110_2336.cpython-37.pyc │ │ │ ├── 0011_auto_20201110_2339.cpython-37.pyc │ │ │ ├── 0012_auto_20201110_2330.cpython-37.pyc │ │ │ └── __init__.cpython-37.pyc │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── cart │ │ │ ├── checkout_page.html │ │ │ ├── home.html │ │ │ ├── make_payment.html │ │ │ ├── order_confirmation.html │ │ │ └── order_history.html │ ├── tests.py │ ├── urls.py │ ├── utils │ │ ├── __pycache__ │ │ │ └── cart_management.cpython-37.pyc │ │ └── cart_management.py │ └── views.py ├── db.sqlite3 ├── djangobase │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── __init__.cpython-37.pyc │ │ ├── settings.cpython-36.pyc │ │ ├── settings.cpython-37.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── urls.cpython-37.pyc │ │ ├── wsgi.cpython-36.pyc │ │ └── wsgi.cpython-37.pyc │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ └── images │ │ └── products │ │ ├── amdryzen.jpg │ │ ├── amdryzen_os8lQqg.jpg │ │ ├── craft.png │ │ ├── dell.jpg │ │ ├── dell_EcKwBkR.jpg │ │ ├── dell_EcKwBkR_2F5kFTg.jpg │ │ ├── download.jpg │ │ ├── download_FP4TC6M.jpg │ │ ├── freesyncMonitor.jpg │ │ ├── freesyncMonitor_HpeZe5S.jpg │ │ ├── hard_drive.jpg │ │ ├── ibm_keyboard.png │ │ ├── images.jpg │ │ ├── images_1.jpg │ │ ├── model_o.jpg │ │ ├── monitor.jpg │ │ ├── monitor_QeSctlX.jpg │ │ ├── monitor_RLxIcQV.jpg │ │ ├── monitor_iuwEmNm.jpg │ │ ├── mouse_basic.jpg │ │ ├── ryzen.webp │ │ └── ssd.jpg ├── products │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-37.pyc │ │ ├── apps.cpython-37.pyc │ │ ├── models.cpython-37.pyc │ │ ├── serializers.cpython-37.pyc │ │ ├── urls.cpython-37.pyc │ │ ├── utils.cpython-37.pyc │ │ └── views.cpython-37.pyc │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_remove_supplier_other_contact.py │ │ ├── 0003_auto_20190610_1519.py │ │ ├── 0004_auto_20190610_1521.py │ │ ├── 0005_auto_20191113_0458.py │ │ ├── 0006_auto_20191113_0459.py │ │ ├── 0007_remove_productimage_display_order.py │ │ ├── 0008_auto_20191205_1323.py │ │ ├── 0009_productimage_main_picture.py │ │ ├── 0010_auto_20191230_1805.py │ │ ├── 0011_product_featured.py │ │ ├── 0012_auto_20201028_2346.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-37.pyc │ │ │ ├── 0002_remove_supplier_other_contact.cpython-37.pyc │ │ │ ├── 0003_auto_20190610_1519.cpython-37.pyc │ │ │ ├── 0004_auto_20190610_1521.cpython-37.pyc │ │ │ ├── 0005_auto_20191113_0458.cpython-37.pyc │ │ │ ├── 0006_auto_20191113_0459.cpython-37.pyc │ │ │ ├── 0007_remove_productimage_display_order.cpython-37.pyc │ │ │ ├── 0008_auto_20191205_1323.cpython-37.pyc │ │ │ ├── 0009_productimage_main_picture.cpython-37.pyc │ │ │ ├── 0010_auto_20191230_1805.cpython-37.pyc │ │ │ ├── 0011_product_featured.cpython-37.pyc │ │ │ ├── 0012_auto_20201028_2346.cpython-37.pyc │ │ │ └── __init__.cpython-37.pyc │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── products │ │ │ ├── components │ │ │ ├── categories.html │ │ │ └── category_recursion.html │ │ │ ├── home.html │ │ │ └── product.html │ ├── tests.py │ ├── urls.py │ ├── utils │ │ ├── __pycache__ │ │ │ └── model_string_search.cpython-37.pyc │ │ └── model_string_search.py │ └── views.py ├── static │ └── base │ │ ├── css │ │ └── index.css │ │ └── imgs │ │ ├── cpu.png │ │ ├── shopping-cart.png │ │ └── user.png ├── templates │ └── base │ │ ├── base.html │ │ ├── footer.html │ │ ├── header.html │ │ └── navigation_old.html ├── tools │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-37.pyc │ │ ├── apps.cpython-37.pyc │ │ ├── data_structures.cpython-37.pyc │ │ └── models.cpython-37.pyc │ ├── admin.py │ ├── apps.py │ ├── data_structures.py │ ├── migrations │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-37.pyc │ ├── models.py │ ├── tests.py │ └── views.py └── webpack-stats.json ├── todos.txt ├── webpack-stats.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/env" 4 | ], 5 | "plugins": [ 6 | "@babel/transform-runtime" 7 | ] 8 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | env 3 | node_modules 4 | .python-version 5 | 6 | .ebextensions 7 | .elasticbeanstalk 8 | .python-version -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MohammadRafik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### eCommerce website made with django and vue.js hosted on an AWS EC2 instance inside a docker container 2 | 3 | 4 | ## How to set up 5 | please note the commands below are for the bash shell on linux, you will need to make some changes to the commands to make it work on windows 6 | 1. get python version 3.7 (it does not work on some other python versions so make sure its 3.7),and make sure you also have pip 7 | 2. clone the project `git clone https://github.com/MohammadRafik/ecom_django_vue.git` 8 | 3. redirect path to ecom_django_vue `cd ecom_django_vue` 9 | 4. create a virtual environment `python3 -m venv env` 10 | 5. activate the virtual env `source env/bin/activate` 11 | 6. run `pip3 install -r requirements.txt` 12 | now you need to run a local server using django, so do this: 13 | 7. run `python3 src/manage.py runserver` 14 | on a browser if you go to 127.0.0.1:8000 you should be able to see the site now 15 | 16 | to also setup the front-end with webpacks and generate a new bundled js file follow the steps below: 17 | 1. make sure you are in the correct path as the steps before, you should be in `ecom_django_vue` 18 | 2. run `npm install` 19 | 3. run `./node_modules/.bin/webpack --config ./webpack.config.js` 20 | this will create a new app.js file and replace the old one. its located at ./src/assets/bundles/app.js 21 | 22 | to see the deployment version go to the [deployment branch](https://github.com/MohammadRafik/ecom_django_vue/tree/deployment) 23 | 24 | gif demo: 25 | 26 | ![](ecom_demo.gif) 27 | -------------------------------------------------------------------------------- /ecom_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/ecom_demo.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecommercedjvu", 3 | "version": "1.0.0", 4 | "description": "I'm making an eCommerce website using django and vue.js", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/MohammadRafik/eCommerceDjVu.git" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/MohammadRafik/eCommerceDjVu/issues" 17 | }, 18 | "homepage": "https://github.com/MohammadRafik/eCommerceDjVu#readme", 19 | "devDependencies": { 20 | "@babel/core": "^7.12.10", 21 | "@babel/plugin-transform-runtime": "^7.12.10", 22 | "@babel/preset-env": "^7.12.11", 23 | "@babel/runtime": "^7.12.5", 24 | "axios": "^0.21.1", 25 | "babel-loader": "^8.2.2", 26 | "babel-preset-es2015": "^6.24.1", 27 | "babel-preset-stage-0": "^6.24.1", 28 | "bootstrap": "^4.5.3", 29 | "bootstrap-sass": "^3.4.1", 30 | "bp-vuejs-dropdown": "^2.1.1", 31 | "css-loader": "^2.1.1", 32 | "jquery": "^3.5.1", 33 | "node-sass": "^4.14.1", 34 | "popper.js": "^1.16.1", 35 | "sass-loader": "^7.3.1", 36 | "style-loader": "^0.23.1", 37 | "uglifyjs-webpack-plugin": "^2.2.0", 38 | "vue": "^2.6.12", 39 | "vue-carousel": "^0.18.0", 40 | "vue-hot-reload-api": "^2.3.4", 41 | "vue-loader": "^15.9.5", 42 | "vue-template-compiler": "^2.6.12", 43 | "webpack": "^4.44.2", 44 | "webpack-bundle-tracker": "^0.4.3", 45 | "webpack-cli": "^3.3.12" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /personal_notes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | python version 3.7.2 for windows 4 | and make sure u have node.js with npm,and pip3 5 | to install node nodules from package.json just run: 6 | npm install 7 | 8 | 9 | 10 | webpack commands (windows): 11 | 1. to update app.js just once: .\node_modules\.bin\webpack --config webpack.config.js 12 | 13 | 2. to update app.js every time a change is saved on the frontend files: .\node_modules\.bin\webpack --config webpack.config.js --watch 14 | 15 | 16 | 17 | to run requirements.txt do this in cmd: 18 | pip3 install -r requirements.txt -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | astroid==2.2.* 2 | atomicwrites==1.3.* 3 | attrs==19.3.* 4 | certifi==2019.11.* 5 | chardet==3.0.* 6 | colorama==0.4.* 7 | Django==2.2.* 8 | django-webpack-loader==0.6.* 9 | djangorestframework==3.11.* 10 | Faker==0.9.1 11 | httpie==1.0.* 12 | idna==2.5 13 | importlib-metadata==1.5.* 14 | isort==4.3.* 15 | lazy-object-proxy==1.4.* 16 | mccabe==0.6.* 17 | mixer==6.1.* 18 | more-itertools==8.2.* 19 | optional-django==0.1.* 20 | packaging==20.* 21 | Pillow==8.0.* 22 | pluggy==0.13.* 23 | py==1.8.* 24 | Pygments==2.5.* 25 | pylint==2.3.* 26 | pyparsing==2.4.* 27 | pytest==5.4.* 28 | pytest-django==3.8.* 29 | python-dateutil==2.8.* 30 | pytz==2019.1 31 | requests==2.22.* 32 | six==1.12.* 33 | sqlparse==0.3.* 34 | stripe==2.42.* 35 | text-unidecode==1.2 36 | typed-ast==1.3.* 37 | urllib3==1.25.* 38 | wcwidth==0.1.* 39 | wrapt==1.11.* 40 | zipp==3.1.* 41 | -------------------------------------------------------------------------------- /src/accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__init__.py -------------------------------------------------------------------------------- /src/accounts/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/apps.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/apps.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/apps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/apps.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/forms.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/forms.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/__pycache__/views.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/__pycache__/views.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | name = 'accounts' 6 | -------------------------------------------------------------------------------- /src/accounts/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.models import User 3 | from django.contrib.auth.forms import UserCreationForm 4 | 5 | class RegistrationForm(UserCreationForm): 6 | # username = forms.CharField(length=100) 7 | email = forms.EmailField(required=True) 8 | 9 | 10 | class Meta: 11 | model = User 12 | fields = ('username', 'email', 'password1', 'password2',) 13 | widgets = { 14 | 'username': forms.TextInput(attrs=({'required': ''})), 15 | 'email': forms.EmailInput(attrs=({'required': ''})), 16 | 'password1':forms.PasswordInput(attrs={'required': ''}), 17 | 'password2':forms.PasswordInput(attrs={'required': ''}), 18 | 19 | } 20 | 21 | def save(self, commit=True): 22 | user = super(RegistrationForm, self).save(commit=False) 23 | user.email = self.cleaned_data['email'] 24 | user.username = self.cleaned_data['username'] 25 | 26 | if commit: 27 | user.save() 28 | 29 | return user -------------------------------------------------------------------------------- /src/accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /src/accounts/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /src/accounts/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/accounts/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/accounts/templates/accounts/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 | {% if request.user.is_authenticated %} 4 |
5 | Hello {{request.user.get_username}}, you are logged in, this is the account home page 6 |


7 |
8 |
9 | 12 |
13 |
14 |
15 |
16 | {% csrf_token %} 17 |
18 | 21 |
22 |
23 | {% else %} 24 | You are not logged in 25 |

26 | Click here to go to the login page 27 | {% endif %} 28 | 29 | {% endblock content %} -------------------------------------------------------------------------------- /src/accounts/templates/accounts/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | 3 | 4 | {% block content %} 5 | {% if request.user.is_authenticated %} 6 |
7 |
8 | 12 |
13 |
14 |

if you would like to log in to a different account you must logout of this one first

15 |
16 | {% csrf_token %} 17 | 20 |
21 |
22 |
23 |
24 | {% else %} 25 |
26 |
27 |
28 |
29 | {% csrf_token %} 30 |
31 |
32 |

User Login

33 |
34 |
35 |
36 | {% if error %} 37 | 40 | {% endif %} 41 | 42 |
43 | 44 |
45 | 46 |
47 |
48 | 49 | 50 |
51 | 52 |
53 | 54 |
55 |
56 | 57 |
58 | 61 |
62 |
63 |
64 |
65 | {% comment %} redirect user to registeration page {% endcomment %} 66 |
67 |

Dont have an account yet? Register 68 |
69 |

70 |
71 | {% comment %} redirect user to home page {% endcomment %} 72 |

Take me back Home instead

73 |
74 |
75 |
76 |
77 | {% endif %} 78 | 79 | 80 | {% endblock %} -------------------------------------------------------------------------------- /src/accounts/templates/accounts/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | 3 | 4 | {% block content %} 5 | {% if request.user.is_authenticated %} 6 |
7 |
8 | 12 |
13 |
14 |

if you would like to register a new account you must logout of this one first

15 |
16 | {% csrf_token %} 17 | 20 |
21 |
22 |
23 |
24 | {% else %} 25 | 26 |
27 |
28 |
29 |
30 | {% csrf_token %} 31 |
32 |
33 |

Registration

34 |
35 |
36 |
37 |
38 | 39 |
40 | 41 | {% if form.username.errors %} 42 |
43 | {{ form.username.errors|first|safe }} 44 |
45 | {% endif %} 46 |
47 | 48 | 49 |
50 | 51 |
52 | 53 |
54 | 55 | {% if form.email.errors %} 56 |
57 | {{ form.email.errors|first|safe }} 58 |
59 | {% endif %} 60 |
61 |
62 | 63 |
64 | 65 |
66 | 67 | {% if form.password1.errors %} 68 |
69 | {{ form.password1.errors|first|safe }} 70 |
71 | {% endif %} 72 |
73 |
74 | 75 |
76 | 77 |
78 | 79 | {% if form.password2.errors %} 80 |
81 | {{ form.password2.errors|first|safe }} 82 |
83 | {% endif %} 84 |
85 |
86 | 87 |
88 | 91 |
92 |
93 |
94 |
95 |
96 | {% comment %} redirect user to registeration page {% endcomment %} 97 |
98 |

Already have an account? Login 99 |
100 |

101 |
102 | {% comment %} redirect user to home page {% endcomment %} 103 |

Take me back Home instead

104 |
105 |
106 |
107 |
108 | 109 | {%endif%} 110 | 111 | {% endblock %} -------------------------------------------------------------------------------- /src/accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | app_name = 'accounts' 5 | urlpatterns = [ 6 | path('', views.home, name='home'), 7 | path('register', views.Register.as_view(), name='register'), 8 | path('login', views.Login.as_view(), name='login'), 9 | path('logout', views.Logout.as_view(), name='logout') 10 | 11 | ] 12 | -------------------------------------------------------------------------------- /src/accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from accounts.forms import RegistrationForm 3 | from django.views import View 4 | from django.contrib.auth import authenticate, login, logout, get_user_model 5 | 6 | # Create your views here. 7 | def home(request): 8 | return render(request, 'accounts/home.html') 9 | 10 | 11 | class Register(View): 12 | template_name = 'accounts/register.html' 13 | form_class = RegistrationForm 14 | 15 | def get(self, request): 16 | form = self.form_class() 17 | return render(request, self.template_name,{'form':form}) 18 | 19 | def post(self, request): 20 | form = self.form_class(request.POST) 21 | if form.is_valid(): 22 | form.save() 23 | # logging the user in since hes registration is successful 24 | user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password1']) 25 | login(request, user) 26 | return redirect('../accounts') 27 | else: 28 | return render(request, self.template_name, {'form':form}) 29 | 30 | 31 | class Login(View): 32 | template_name = 'accounts/login.html' 33 | 34 | def get(self, request): 35 | return render(request, self.template_name) 36 | 37 | def post(self,request): 38 | username = request.POST['username'] 39 | password = request.POST['password'] 40 | 41 | User = get_user_model() 42 | if '@' in username: 43 | try: 44 | current_user = User.objects.get(email__iexact=username) 45 | username = current_user.username 46 | except: 47 | error = "Oops! something's wrong. We couldn't find that email" 48 | return render(request, self.template_name, {'error':error, 'form_username':username}) 49 | 50 | user = authenticate(username=username,password=password) 51 | 52 | if user is not None: 53 | login(request, user) 54 | return redirect('../accounts') 55 | else: 56 | error = "Oops! something's wrong. Your username/email and password didnt match" 57 | return render(request, self.template_name, {'error':error, 'form_username':username}) 58 | 59 | 60 | class Logout(View): 61 | 62 | def get(self, request): 63 | logout(request) 64 | return redirect('../') 65 | -------------------------------------------------------------------------------- /src/assets/js/components/checkout_script.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/js/components/navigation.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 37 | 38 | -------------------------------------------------------------------------------- /src/assets/js/components/onload.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/js/components/products.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/js/css/random-css.css: -------------------------------------------------------------------------------- 1 | .fade-enter-active, .fade-leave-active { 2 | transition: opacity .5s; 3 | } 4 | .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { 5 | opacity: 0; 6 | } -------------------------------------------------------------------------------- /src/assets/js/css/vue-carousel.css: -------------------------------------------------------------------------------- 1 | .VueCarousel-slide { 2 | position: relative; 3 | background: #FAFAFA; 4 | color: #fff; 5 | font-family: Arial; 6 | font-size: 24px; 7 | text-align: center; 8 | min-height: 100px; 9 | } -------------------------------------------------------------------------------- /src/assets/js/helpers/tools.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/js/index.js: -------------------------------------------------------------------------------- 1 | // window.$ = window.jQuery = require('jquery'); 2 | // going to load bootstrap using a link in my html so that it loads before this 3 | // import 'bootstrap'; 4 | // import 'bootstrap/dist/css/bootstrap.min.css'; 5 | import Vue from 'vue'; 6 | // importing axios needs to be done on each component or mixin seperatly 7 | 8 | 9 | // components from github 10 | import Dropdown from 'bp-vuejs-dropdown'; 11 | 12 | import { Carousel, Slide } from "vue-carousel"; 13 | import "./css/vue-carousel.css" 14 | 15 | // my custom components 16 | import Navigation from "./components/navigation.vue"; 17 | import Checkout_script from "./components/checkout_script.vue"; 18 | import onload from "./components/onload.vue"; 19 | 20 | 21 | // mixins 22 | import {base_global} from "./mixins/base_global.js" 23 | import {vue_slides} from "./mixins/vue_slides.js" 24 | 25 | // some random css 26 | import "./css/random-css.css" 27 | 28 | const app = new Vue({ 29 | el: '#app', 30 | data: function(){ 31 | return { 32 | 33 | } 34 | }, 35 | delimiters: ["[[","]]"], //changing the default because thats what django's template language uses as well 36 | components: { 37 | Dropdown, 38 | Navigation, 39 | Checkout_script, 40 | onload, 41 | Carousel, 42 | Slide, 43 | 44 | }, 45 | mixins: [base_global, vue_slides], 46 | 47 | }); -------------------------------------------------------------------------------- /src/assets/js/mixins/base_global.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios').default; 2 | axios.defaults.xsrfCookieName = 'csrftoken' 3 | axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" 4 | 5 | export const base_global = { 6 | data: function () { 7 | return { 8 | added_to_cart_successfully: false, 9 | cart_item_count: 0, 10 | failed_adding_to_cart: false, 11 | time_out_already_running: false, 12 | } 13 | }, 14 | created: function() { 15 | // check if there is a saved category in the session 16 | self = this 17 | self.update_cart_item_count() 18 | 19 | }, 20 | methods: { 21 | update_cart_item_count: function(){ 22 | self = this 23 | axios.get('/cart/get_cart_items_count') 24 | .then(function (response){ 25 | self.cart_item_count = response.data; 26 | }) 27 | }, 28 | 29 | add_product_to_cart: function(){ 30 | let self= this; 31 | 32 | let form_ele = document.getElementById('cart_products_update_form'); 33 | let cart_url = form_ele.cart.value 34 | let product_url = form_ele.product.value 35 | let quantity = form_ele.quantity.value 36 | let updated_by = form_ele.updated_by.value 37 | let created_by = form_ele.created_by.value 38 | axios.post('/cart/update_', { 39 | cart: cart_url, 40 | product: product_url, 41 | quantity: quantity, 42 | updated_by: updated_by, 43 | created_by: created_by 44 | }) 45 | .then(function(response){ 46 | self.added_to_cart_successfully = true; 47 | self.update_cart_item_count(); 48 | self.pop_message_timeout(); 49 | }) 50 | .catch(function (error){ 51 | self.failed_adding_to_cart = true; 52 | self.pop_message_timeout(); 53 | }) 54 | .finally(function(){ 55 | 56 | }) 57 | }, 58 | 59 | delete_item_from_cart: function(cart_item_id){ 60 | axios.delete('/api/cartitem/' + cart_item_id) 61 | .then(function(response){ 62 | console.log('item deleted from cart'); 63 | console.log(response); 64 | window.location.reload(true); 65 | }) 66 | .catch(function (error){ 67 | }) 68 | .finally(function(){ 69 | }) 70 | }, 71 | 72 | // this isnt being used????? 73 | pop_message_timeout: function() { 74 | var self = this; 75 | if (self.time_out_already_running == true){ 76 | // reset timeout duration and exit 77 | window.clearTimeout(self.cart_timeout) 78 | self.cart_timeout = window.setTimeout(function() { 79 | self.added_to_cart_successfully = false; 80 | self.failed_adding_to_cart = false; 81 | self.time_out_already_running = false; 82 | }, 1500) 83 | return 84 | } 85 | else{ 86 | self.time_out_already_running = true; 87 | self.cart_timeout = window.setTimeout(function() { 88 | self.added_to_cart_successfully = false; 89 | self.failed_adding_to_cart = false; 90 | self.time_out_already_running = false; 91 | }, 1500) 92 | } 93 | }, 94 | 95 | 96 | } 97 | } 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /src/assets/js/mixins/vue_slides.js: -------------------------------------------------------------------------------- 1 | // i should turn this into a compoenent so that it only loads when its being used instead of being loaded on every page 2 | const axios = require('axios').default; 3 | axios.defaults.xsrfCookieName = 'csrftoken' 4 | axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" 5 | 6 | export const vue_slides = { 7 | data: function () { 8 | return { 9 | slides: [] 10 | } 11 | }, 12 | created: function() { 13 | // all this function does it fetch the needed data using the api to update slides with the featured products 14 | // the proper way to do this would be to set up filters on the django rest framework views so that i can just specify what i want in the url request 15 | self = this 16 | axios.get('/api/products') 17 | .then(function(response_products){ 18 | var featured_results = [] 19 | response_products.data.results.forEach(element =>{ 20 | if (element.featured == true){ 21 | featured_results.push(element) 22 | } 23 | }); 24 | response_products.data.results = featured_results 25 | 26 | axios.get('/api/productimages') 27 | .then(function(response_images){ 28 | // relate each product to its image 29 | response_products.data.results.forEach(element_prod => { 30 | response_images.data.results.forEach(element_img => { 31 | if (element_prod.id == Number(element_img.product.match(/\/[0-9]{1,4}\//g)[0].match(/[0-9]{1,4}/g)[0])){ 32 | element_prod.img_url = element_img.image_url 33 | } 34 | }); 35 | }); 36 | // now we find the products with featured=true and make an api request to get their url's from django 37 | response_products.data.results.forEach(element => { 38 | if (element.featured == true){ 39 | // so here each element is one of the featured items we need to load into slides, before doing anything we need to get the image urls 40 | 41 | 42 | 43 | axios.get('/api/get_url',{ 44 | params: { 45 | app_and_url_name: 'products:product_page', 46 | url_arg: element.id 47 | } 48 | }) 49 | .then(function(response_url){ 50 | // now we have url in response_url.data, and everything else in element, so time to fill slides 51 | self.slides.push({ 52 | title: element.title, 53 | content: element.description, 54 | id: element.id, 55 | image: element.img_url, 56 | link: response_url.data 57 | }) 58 | }) 59 | 60 | } 61 | }); 62 | }) 63 | }) 64 | .catch(function (error){ 65 | console.log('error with TEH product get request') 66 | console.log(error) 67 | }) 68 | .finally(function(){ 69 | 70 | }) 71 | 72 | }, 73 | methods: { 74 | 75 | } 76 | } 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/cart/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__init__.py -------------------------------------------------------------------------------- /src/cart/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/apps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/apps.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/forms.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/forms.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/serializers.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/serializers.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/utils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/utils.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/__pycache__/views.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/__pycache__/views.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Cart, CartItem, CheckoutDetails 3 | # Register your models here. 4 | 5 | 6 | admin.site.register(Cart) 7 | admin.site.register(CartItem) 8 | admin.site.register(CheckoutDetails) 9 | 10 | -------------------------------------------------------------------------------- /src/cart/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CartConfig(AppConfig): 5 | name = 'cart' 6 | -------------------------------------------------------------------------------- /src/cart/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from cart.models import CheckoutDetails 3 | 4 | class CheckoutForm(forms.ModelForm): 5 | 6 | class Meta: 7 | model = CheckoutDetails 8 | fields = [ 'name_of_receiver', 'main_address', 'secondary_address', 'city', 'province', 'postal_code', 'phone_number'] 9 | widgets = { 10 | 'name_of_receiver': forms.TextInput(attrs={'class': 'form-control'}), 11 | 'main_address': forms.TextInput(attrs={'class': 'form-control'}), 12 | 'secondary_address': forms.TextInput(attrs={'class': 'form-control'}), 13 | 'city': forms.TextInput(attrs={'class': 'form-control'}), 14 | 'province': forms.TextInput(attrs={'class': 'form-control'}), 15 | 'postal_code': forms.TextInput(attrs={'class': 'form-control'}), 16 | 'phone_number': forms.TextInput(attrs={'class': 'form-control'}) 17 | } 18 | 19 | 20 | def __init__(self, *args, **kwargs): 21 | super(CheckoutForm, self).__init__(*args, **kwargs) 22 | 23 | # here we just change the secondary address field so that it wont be required by the frontend 24 | self.fields['secondary_address'].required = False 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/cart/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2020-01-05 03:42 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ('products', '0010_auto_20191230_1805'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='Cart', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('updated_by', models.CharField(max_length=100)), 21 | ('updated_on', models.DateTimeField(auto_now=True)), 22 | ('created_on', models.DateTimeField(auto_now_add=True)), 23 | ('created_by', models.CharField(max_length=100)), 24 | ], 25 | ), 26 | migrations.CreateModel( 27 | name='CartItem', 28 | fields=[ 29 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 30 | ('quantity', models.IntegerField(default=1)), 31 | ('updated_by', models.CharField(max_length=100)), 32 | ('updated_on', models.DateTimeField(auto_now=True)), 33 | ('created_on', models.DateTimeField(auto_now_add=True)), 34 | ('created_by', models.CharField(max_length=100)), 35 | ('cart', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cart_item', to='cart.Cart')), 36 | ('product', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='products.Product')), 37 | ], 38 | ), 39 | ] 40 | -------------------------------------------------------------------------------- /src/cart/migrations/0002_auto_20200117_0523.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-17 13:23 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cart', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cartitem', 16 | name='product', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.Product'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /src/cart/migrations/0003_auto_20200117_0526.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-17 13:26 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cart', '0002_auto_20200117_0523'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cartitem', 16 | name='product', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.Product', unique=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /src/cart/migrations/0004_auto_20200117_0604.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-17 14:04 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cart', '0003_auto_20200117_0526'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cartitem', 16 | name='product', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.Product'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /src/cart/migrations/0005_auto_20200117_1729.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-18 01:29 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cart', '0004_auto_20200117_0604'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cartitem', 16 | name='cart', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cart_items', to='cart.Cart'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /src/cart/migrations/0006_checkoutdetails.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-23 10:24 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cart', '0005_auto_20200117_1729'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='CheckoutDetails', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name_of_receiver', models.CharField(max_length=100)), 19 | ('main_address', models.CharField(max_length=200)), 20 | ('secondary_address', models.CharField(max_length=100, null=True)), 21 | ('city', models.CharField(max_length=100)), 22 | ('province', models.CharField(max_length=20)), 23 | ('postal_code', models.CharField(max_length=12)), 24 | ('phone_number', models.CharField(max_length=12)), 25 | ('updated_by', models.CharField(max_length=100)), 26 | ('updated_on', models.DateTimeField(auto_now=True)), 27 | ('created_on', models.DateTimeField(auto_now_add=True)), 28 | ('created_by', models.CharField(max_length=100)), 29 | ('cart', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checkout_details', to='cart.Cart')), 30 | ], 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /src/cart/migrations/0007_checkoutdetails_user.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-26 23:47 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ('cart', '0006_checkoutdetails'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='checkoutdetails', 18 | name='user', 19 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /src/cart/migrations/0008_cartitem_user.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-29 16:31 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ('cart', '0007_checkoutdetails_user'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='cartitem', 18 | name='user', 19 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /src/cart/migrations/0009_remove_cartitem_user.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-29 16:31 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cart', '0008_cartitem_user'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='cartitem', 15 | name='user', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /src/cart/migrations/0010_cart_user.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-29 16:32 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ('cart', '0009_remove_cartitem_user'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='cart', 18 | name='user', 19 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /src/cart/migrations/0011_auto_20201110_2339.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-11-11 07:39 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('cart', '0010_cart_user'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='cart', 17 | name='active', 18 | field=models.BooleanField(default=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='cart', 22 | name='user', 23 | field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /src/cart/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__init__.py -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0001_initial.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0001_initial.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0002_auto_20200117_0523.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0002_auto_20200117_0523.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0003_auto_20200117_0526.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0003_auto_20200117_0526.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0004_auto_20200117_0604.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0004_auto_20200117_0604.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0005_auto_20200117_1729.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0005_auto_20200117_1729.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0006_checkoutdetails.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0006_checkoutdetails.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0007_checkoutdetails_user.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0007_checkoutdetails_user.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0008_cartitem_user.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0008_cartitem_user.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0009_remove_cartitem_user.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0009_remove_cartitem_user.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0010_cart_user.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0010_cart_user.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0011_auto_20201110_2315.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0011_auto_20201110_2315.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0011_auto_20201110_2336.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0011_auto_20201110_2336.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0011_auto_20201110_2339.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0011_auto_20201110_2339.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/0012_auto_20201110_2330.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/0012_auto_20201110_2330.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from products.models import Product 3 | from django.contrib.auth.models import User, AnonymousUser 4 | 5 | 6 | # Create your models here. 7 | #add functionality to be able to change its quantity 8 | 9 | class Cart(models.Model): 10 | user = models.ForeignKey(User,null=True,blank=True, default=None, on_delete=models.CASCADE) 11 | active = models.BooleanField(default=True) 12 | updated_by = models.CharField(max_length=100) 13 | updated_on = models.DateTimeField(auto_now=True) 14 | created_on = models.DateTimeField(auto_now_add=True) 15 | created_by = models.CharField(max_length=100) 16 | 17 | 18 | 19 | def get_items(self): 20 | return self.cart_items.prefetch_related('product').all() 21 | 22 | @classmethod 23 | def delete_unactive_carts(cls): 24 | # deletes all non-active cart instances 25 | cls.objects.filter(active=False).delete() 26 | 27 | @classmethod 28 | def delete_all_carts(cls): 29 | cls.objects.all().delete() 30 | 31 | 32 | 33 | class CartItem(models.Model): 34 | 35 | cart = models.ForeignKey(Cart, related_name='cart_items', on_delete=models.CASCADE) 36 | product = models.ForeignKey(Product, on_delete=models.CASCADE) 37 | quantity = models.IntegerField(default=1) 38 | updated_by = models.CharField(max_length=100) 39 | updated_on = models.DateTimeField(auto_now=True) 40 | created_on = models.DateTimeField(auto_now_add=True) 41 | created_by = models.CharField(max_length=100) 42 | 43 | def __str__(self): 44 | return self.product.title + ' cart item from cart object ' + str(self.cart.id) 45 | 46 | def find_total_cost(self): 47 | tax = 1.12 48 | self.total_cost = self.quantity * self.product.current_price * tax 49 | return self.total_cost 50 | 51 | def update_quantity(self, quantity): 52 | self.update(quantity=quantity) 53 | 54 | 55 | 56 | class CheckoutDetails(models.Model): 57 | user = models.ForeignKey(User, null=True, on_delete=models.CASCADE) 58 | cart = models.OneToOneField(Cart, related_name='checkout_details', null=True, on_delete=models.SET_NULL) 59 | name_of_receiver = models.CharField(max_length=100) 60 | main_address = models.CharField(max_length=200) 61 | secondary_address = models.CharField(max_length=100, null=True) 62 | city = models.CharField(max_length=100) 63 | province = models.CharField(max_length=20) 64 | postal_code = models.CharField(max_length=12) 65 | phone_number = models.CharField(max_length=12) 66 | updated_by = models.CharField(max_length=100) 67 | updated_on = models.DateTimeField(auto_now=True) 68 | created_on = models.DateTimeField(auto_now_add=True) 69 | created_by = models.CharField(max_length=100) 70 | 71 | def __str__(self): 72 | return 'products to ' + self.main_address + ' for ' + self.name_of_receiver 73 | 74 | -------------------------------------------------------------------------------- /src/cart/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from .models import CartItem, Cart, CheckoutDetails 3 | 4 | class CartItemSerializer(serializers.HyperlinkedModelSerializer): 5 | 6 | 7 | class Meta: 8 | model = CartItem 9 | fields = ( 'id', 'url', 'cart', 'product', 'quantity', 'updated_by', 'updated_on', 'created_on', 'created_by' ) 10 | 11 | 12 | class CartSerializer(serializers.HyperlinkedModelSerializer): 13 | 14 | 15 | class Meta: 16 | model = Cart 17 | fields = ('id', 'url', 'active', 'updated_by', 'updated_on', 'created_on', 'created_by') 18 | 19 | 20 | class CheckoutDetailsSerializer(serializers.HyperlinkedModelSerializer): 21 | class Meta: 22 | model = CheckoutDetails 23 | fields = ('id', 'url', 'cart', 'name_of_receiver', 'main_address', 'secondary_address', 'city', 'province', 'postal_code', 'phone_number', 'updated_by', 'updated_on', 'created_on', 'created_by') -------------------------------------------------------------------------------- /src/cart/templates/cart/checkout_page.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 | 4 |
5 | please fill out this form so we can get your shipping address and other needed data, then proceed to the payment page 6 |

7 | {% if request.user.is_authenticated == False %} 8 | 11 | {%endif%} 12 | 13 |
14 |
15 | {% csrf_token %} 16 |
17 |
18 |
19 |
20 | {% for field in form %} 21 |
22 | 23 |
24 | {{field}} 25 |
26 |
27 | {% endfor %} 28 | 29 |
30 |
31 | 32 |
33 | 34 | 35 | 36 | {% endblock content %} -------------------------------------------------------------------------------- /src/cart/templates/cart/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |
7 |
8 | Cart Porudcts 9 |
10 |
    11 | {% for cart_item in cart_items%} 12 |
  • 13 | {{cart_item.product.title}} 14 | {% for product_image in product_images %} 15 | {% if product_image.product_id == cart_item.product_id %} 16 |
    17 |

    CDN${{cart_item.product.current_price}} x {{cart_item.quantity}}

    18 | {% endif %} 19 | {% endfor %} 20 | {% comment %} button to remove item from cart {% endcomment %} 21 |
    22 | 23 |
    24 | 25 |
  • 26 | {% empty %} 27 |
  • 28 | you dont have any products in your cart 29 |
  • 30 | {% endfor %} 31 |
32 |
33 |
34 | 35 | {% comment %} total cost {% endcomment %} 36 |
37 |
38 |
    39 |
  • 40 | total before tax: {{total_cost}} 41 |
    42 | Tax: {{tax}} 43 |
  • 44 |
  • 45 | final price:

    46 |
    47 | CDN${{total_cost_with_tax}} 48 | 49 | 50 | {% if cart_items%} 51 |
    52 | 53 |
    54 | {% endif %} 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 | {% comment %} checkout {% endcomment %} 64 |
    65 |
  • 66 |
67 |
68 |






69 |
70 |
71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 |






79 |






80 | {% endblock content %} -------------------------------------------------------------------------------- /src/cart/templates/cart/make_payment.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 |
4 |

final step, please make sure all the data is correct, then proceed to make payment:

5 |

shipping address:  {{checkout_details.main_address}}, {{ checkout_details.city }}, {{checkout_details.province}}

6 |

postal code:  {{checkout_details.postal_code}}

7 |

name of receiver:  {{checkout_details.name_of_receiver}}

8 |
9 |

purchasing the following items:

10 |
11 |
12 |
13 | Porudcts you are purchasing 14 |
15 | 27 |
28 | 29 | {% comment %} total cost {% endcomment %} 30 |


31 |
32 |
33 |
    34 |
  • 35 | total before tax: {{total_cost}} 36 |
    37 | Tax: {{tax}} 38 |
  • 39 |
  • 40 | final price:

    41 |
    42 | CDN${{total_cost_with_tax}} 43 |
    44 | {% csrf_token %} 45 | 46 | 47 |
    48 |
    49 | {% comment %} checkout {% endcomment %} 50 |
    51 |
  • 52 |
53 |
54 |
55 |






56 |






57 |



58 | 59 | 60 |


61 | 62 | {% endblock content %} -------------------------------------------------------------------------------- /src/cart/templates/cart/order_confirmation.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 |
4 | {% comment %} this is a simple check, its not important if it fails, its just a check to see what part of the html should be loaded {% endcomment %} 5 | {% if payment_confirmation == total_cost_with_tax %} 6 | 19 | 20 |


21 |
22 |

Thank You!

23 | {% comment %} redirect user to home page {% endcomment %} 24 |

Take me back Home

25 |
26 | {% else %} 27 |
28 |

29 |

Error, your order confirmation failed. did you pay?

30 | {% comment %} redirect user to home page {% endcomment %} 31 |

Take me back Home

32 |
33 | {% endif %} 34 | {% endblock content %} -------------------------------------------------------------------------------- /src/cart/templates/cart/order_history.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block content %} 3 |
4 |

this is a list of all you're previouse orders:

5 | {% for order, cart_items, cost in order_cartitem_history %} 6 | 7 | 8 | 9 |

10 |
11 |
12 |
13 | Order #{{order.id}} 14 |
15 | total cost: CDN${{cost}} 16 |
17 |
18 |
    19 | {% comment %} list of cart items for 1 order {% endcomment %} 20 | {% for cart_item in cart_items %} 21 |
  • 22 | {{cart_item.product.title}} 23 | {% for product_image in product_images %} 24 | {% if product_image.product_id == cart_item.product_id %} 25 |
    26 |

    CDN${{cart_item.product.current_price}} x {{cart_item.quantity}}

    27 | {% endif %} 28 | {% endfor %} 29 |
  • 30 | {% endfor %} 31 |
32 | 43 |
44 |
45 |
46 |

47 | {% empty %} 48 | it looks like you have not ordered anything, or maybe you made your orders without being logged in 49 | {% endfor %} 50 | {% endblock content %} -------------------------------------------------------------------------------- /src/cart/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/cart/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | app_name = 'cart' 5 | urlpatterns = [ 6 | path('', views.CartPageLoader.as_view(), name='cartpageloader'), 7 | path('confirmation', views.order_confirmation, name='order_confirmation'), 8 | path('checkout', views.CheckoutLoader.as_view(), name='checkout_page'), 9 | path('order_history', views.order_history, name='order_history'), 10 | path('get_cart_items_count', views.get_cart_items_count, name='get_cart_items_count'), 11 | path('update_', views.update_cart_items, name='update_cart_items'), 12 | 13 | 14 | ] 15 | -------------------------------------------------------------------------------- /src/cart/utils/__pycache__/cart_management.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/cart/utils/__pycache__/cart_management.cpython-37.pyc -------------------------------------------------------------------------------- /src/cart/utils/cart_management.py: -------------------------------------------------------------------------------- 1 | from cart.models import Cart 2 | 3 | class CartManager(): 4 | 5 | def __init__(self, request): 6 | if request.user.is_authenticated and 'cart_id' in request.session: 7 | # this means session of anon has a cart but now he logged in, so the cart should connect to the user, and if there is an old active cart for this user deactivate it 8 | try: 9 | cart = Cart.objects.get(user= request.user, active=True) 10 | cart.active = False 11 | cart.save() 12 | self.cart = Cart.objects.get(id = request.session['cart_id'], active=True) 13 | self.cart.user = request.user 14 | self.cart.save() 15 | request.session.pop('cart_id') 16 | except: 17 | self.cart = Cart.objects.get(id = request.session['cart_id'], active=True) 18 | self.cart.user = request.user 19 | self.cart.save() 20 | request.session.pop('cart_id') 21 | elif request.user.is_authenticated: 22 | try: 23 | self.cart = Cart.objects.get(user= request.user, active=True) 24 | except: 25 | self.cart = Cart(user = request.user) 26 | self.cart.save() 27 | elif 'cart_id' in request.session: 28 | try: 29 | self.cart = Cart.objects.get(id = request.session['cart_id'], active=True) 30 | except: 31 | request.session.pop('cart_id') 32 | self.cart = Cart() 33 | self.cart.save() 34 | request.session['cart_id'] = self.cart.id 35 | else: 36 | self.cart = Cart() 37 | self.cart.save() 38 | request.session['cart_id'] = self.cart.id 39 | self.load_items() 40 | 41 | def load_items(self): 42 | self.cart_items = self.cart.get_items() 43 | return self.cart_items 44 | 45 | def calc_quanitity(self): 46 | self.load_items() 47 | total_quantity = 0 48 | for cart_item in self.cart_items: 49 | total_quantity += cart_item.quantity 50 | return total_quantity 51 | 52 | def total_cost(self): 53 | self.total_cost = 0.0 54 | if hasattr(self, 'cart_items'): 55 | for cart_item in self.cart_items: 56 | self.total_cost += (float(cart_item.product.current_price) * cart_item.quantity) 57 | self.total_cost = round(self.total_cost, 2) 58 | self.tax = round(self.total_cost * 0.13, 2) 59 | self.total_cost_with_tax = round(self.total_cost + self.tax, 2) 60 | return (self.total_cost, self.tax, self.total_cost_with_tax) 61 | else: 62 | return 0 63 | 64 | def deactivate(self, request): 65 | if 'cart_id' in request.session: 66 | request.session.pop('cart_id') 67 | 68 | self.cart.active = False 69 | self.cart.save() 70 | return self.cart 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/cart/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect, HttpResponse 2 | from django.views import View 3 | from cart.models import Cart,CartItem, CheckoutDetails 4 | from products.models import ProductImage, Product 5 | from django.conf import settings 6 | from django.contrib.auth.models import User, AnonymousUser 7 | from cart.utils.cart_management import CartManager 8 | import re 9 | # Create your views here. 10 | 11 | 12 | 13 | class CartPageLoader(View): 14 | def get(self, request): 15 | 16 | cart_manager = CartManager(request) 17 | cart_manager.load_items() 18 | cart_manager.total_cost() 19 | total_cost_for_stripe = cart_manager.total_cost_with_tax * 100 20 | 21 | # load product images 22 | product_images = [] 23 | if hasattr(cart_manager, 'cart_items'): 24 | 25 | cart_product_ids = set() 26 | for cart_item in cart_manager.cart_items: 27 | cart_product_ids.add(cart_item.product.id) 28 | 29 | for cart_product_id in cart_product_ids: 30 | product_images.append(ProductImage.find_main_product_image(cart_product_id)) 31 | 32 | 33 | # get stipe key 34 | stripe_key = settings.STRIPE_PUBLISHABLE_KEY 35 | 36 | 37 | return render(request, 'cart/home.html', {'cart':cart_manager.cart, 'cart_items':cart_manager.cart_items, 'product_images':product_images, 'total_cost':cart_manager.total_cost,'tax':cart_manager.tax, 'total_cost_with_tax':cart_manager.total_cost_with_tax, 'stripe_key':stripe_key, 'total_cost_for_stripe':total_cost_for_stripe}) 38 | 39 | 40 | from cart.forms import CheckoutForm 41 | class CheckoutLoader(View): 42 | checkout_template_name = 'cart/checkout_page.html' 43 | 44 | 45 | def get(self, request): 46 | form = CheckoutForm() 47 | return render(request, self.checkout_template_name, {'form':form}) 48 | 49 | def post(self, request): 50 | form = CheckoutForm(request.POST) 51 | if form.is_valid(): 52 | cart_manager = CartManager(request) 53 | cart_manager.load_items() 54 | cart_manager.total_cost() 55 | total_cost_for_stripe = cart_manager.total_cost_with_tax * 100 56 | 57 | stripe_key = settings.STRIPE_PUBLISHABLE_KEY 58 | 59 | if request.user.is_authenticated: 60 | user_name = request.user.get_username() 61 | else: 62 | user_name = '' 63 | 64 | # check if checkoutDetails object already exists, if yes update it, if no make one 65 | if CheckoutDetails.objects.filter(cart_id = cart_manager.cart.id).count(): 66 | checkout_details = CheckoutDetails.objects.get(cart_id = cart_manager.cart.id) 67 | if request.user.is_authenticated: 68 | checkout_details.user = request.user 69 | checkout_details.cart = cart_manager.cart 70 | checkout_details.name_of_receiver = form.cleaned_data['name_of_receiver'] 71 | checkout_details.main_address = form.cleaned_data['main_address'] 72 | checkout_details.secondary_address = form.cleaned_data['secondary_address'] 73 | checkout_details.city = form.cleaned_data['city'] 74 | checkout_details.province = form.cleaned_data['province'] 75 | checkout_details.postal_code = form.cleaned_data['postal_code'] 76 | checkout_details.phone_number = form.cleaned_data['phone_number'] 77 | checkout_details.updated_by = user_name 78 | checkout_details.created_by = user_name 79 | checkout_details.save() 80 | else: 81 | if request.user.is_authenticated: 82 | checkout_details = CheckoutDetails( user = request.user, cart = cart_manager.cart, name_of_receiver = form.cleaned_data['name_of_receiver'], main_address = form.cleaned_data['main_address'], secondary_address = form.cleaned_data['secondary_address'], city = form.cleaned_data['city'], province = form.cleaned_data['province'], postal_code = form.cleaned_data['postal_code'], phone_number = form.cleaned_data['phone_number'], updated_by = user_name, created_by = user_name) 83 | else: 84 | checkout_details = CheckoutDetails(cart = cart_manager.cart, name_of_receiver = form.cleaned_data['name_of_receiver'], main_address = form.cleaned_data['main_address'], secondary_address = form.cleaned_data['secondary_address'], city = form.cleaned_data['city'], province = form.cleaned_data['province'], postal_code = form.cleaned_data['postal_code'], phone_number = form.cleaned_data['phone_number'], updated_by = user_name, created_by = user_name) 85 | checkout_details.save() 86 | 87 | 88 | return render(request, 'cart/make_payment.html', { 'form': form,'checkout_details':checkout_details, 'cart':cart_manager.cart, 'cart_items':cart_manager.cart_items, 'total_cost':cart_manager.total_cost,'tax':cart_manager.tax, 'total_cost_with_tax':cart_manager.total_cost_with_tax, 'stripe_key':stripe_key, 'total_cost_for_stripe':total_cost_for_stripe}) 89 | else: 90 | return render(request, self.checkout_template_name, {'form':form}) 91 | 92 | 93 | def update_cart_items(request): 94 | if request.method == 'GET': 95 | return HttpResponse('no access') 96 | elif request.method == 'POST': 97 | cart_manager = CartManager(request) 98 | import ast 99 | dict_request_body = ast.literal_eval(request.body.decode("UTF-8")) 100 | product_url = dict_request_body['product'] 101 | try: 102 | product_id_with_slashes = re.search(r'\/[0-9]{1,6}\/', product_url).group() 103 | product_id = re.search(r'[0-9]{1,6}', product_id_with_slashes).group() 104 | product_id = int(product_id) 105 | product = Product.objects.get(pk = product_id) 106 | try: 107 | cart_item_being_updated = CartItem.objects.get(product = product, cart = cart_manager.cart) 108 | cart_item_being_updated.quantity += 1 109 | cart_item_being_updated.save() 110 | except: 111 | # if we get here means cart item doesnt exist so we make a new one with quanitity of 1 112 | new_cart_item = CartItem(cart = cart_manager.cart, product = product) 113 | new_cart_item.save() 114 | except: 115 | HttpResponse('someone is messing with the hidden html input fields D:') 116 | 117 | return HttpResponse('updated cart items') 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | def order_confirmation(request): 126 | cart_manager = CartManager(request) 127 | cart_manager.load_items() 128 | cart_manager.total_cost() 129 | total_cost_for_stripe = cart_manager.total_cost_with_tax * 100 130 | 131 | 132 | # load main image for each cart item product, should maybe redo this main img finder 133 | product_images = [] 134 | repeated = False 135 | if hasattr(cart_manager, 'cart_items'): 136 | for cart_item in cart_manager.cart_items: 137 | img_in_list = ProductImage.find_main_product_image(cart_item.product.id) 138 | repeated = False 139 | for product_image in product_images: 140 | if product_image.pk == img_in_list.pk: 141 | repeated = True 142 | break 143 | if not repeated: 144 | product_images.append(img_in_list) 145 | repeated = False 146 | 147 | if request.method == "GET": 148 | payment_confirmation = '' 149 | elif request.POST['payment_confirmation']: 150 | payment_confirmation = float(request.POST['payment_confirmation']) 151 | else: 152 | payment_confirmation = '' 153 | 154 | 155 | # deactivate this cart now 156 | cart_manager.deactivate(request) 157 | # cant delete deactiveated carts because they are needed to load order history 158 | 159 | return render(request, 'cart/order_confirmation.html', {'cart':cart_manager.cart, 'cart_items':cart_manager.cart_items, 'product_images':product_images, 'total_cost':cart_manager.total_cost,'tax':cart_manager.tax, 'total_cost_with_tax':cart_manager.total_cost_with_tax, 'total_cost_for_stripe':total_cost_for_stripe, 'payment_confirmation':payment_confirmation, 'true_string':'True'}) 160 | 161 | 162 | 163 | def order_history(request): 164 | order_history = CheckoutDetails.objects.filter(user_id = request.user.id) 165 | cart_items_list = [] 166 | product_images = [] 167 | total_costs = [] 168 | for order in order_history: 169 | cart_items = order.cart.get_items() 170 | cart_items_list.append(cart_items) 171 | #get product images 172 | repeated = False 173 | if cart_items: 174 | for cart_item in cart_items: 175 | img_in_list = ProductImage.find_main_product_image(cart_item.product.id) 176 | repeated = False 177 | for product_image in product_images: 178 | if product_image.pk == img_in_list.pk: 179 | repeated = True 180 | break 181 | if not repeated: 182 | product_images.append(img_in_list) 183 | repeated = False 184 | #get order total cost 185 | total_cost = 0.0 186 | for cart_item in cart_items: 187 | total_cost += (float(cart_item.product.current_price) * cart_item.quantity) 188 | total_cost = round(total_cost, 2) 189 | total_cost_with_tax = total_cost*1.13 190 | total_cost_with_tax = round(total_cost_with_tax, 2) 191 | total_costs.append(total_cost_with_tax) 192 | 193 | order_cartitem_history = zip( order_history, cart_items_list, total_costs) 194 | return render(request, 'cart/order_history.html', {'orders':order_history, 'order_cartitem_history':order_cartitem_history, 'product_images':product_images}) 195 | 196 | 197 | 198 | def get_cart_items_count(request): 199 | cart_manager = CartManager(request) 200 | return HttpResponse(cart_manager.calc_quanitity()) 201 | 202 | 203 | # ---------------------------------------------# 204 | #-----------------rest framework---------------# 205 | # ---------------------------------------------# 206 | from rest_framework import viewsets 207 | from .serializers import CartItemSerializer, CartSerializer, CheckoutDetailsSerializer 208 | 209 | class CartItemViewSet(viewsets.ModelViewSet): 210 | queryset = CartItem.objects.all() 211 | serializer_class = CartItemSerializer 212 | 213 | class CartViewSet(viewsets.ModelViewSet): 214 | queryset = Cart.objects.all() 215 | serializer_class = CartSerializer 216 | 217 | class CheckoutDetailsViewSet(viewsets.ModelViewSet): 218 | queryset = CheckoutDetails.objects.all() 219 | serializer_class = CheckoutDetailsSerializer -------------------------------------------------------------------------------- /src/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/db.sqlite3 -------------------------------------------------------------------------------- /src/djangobase/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__init__.py -------------------------------------------------------------------------------- /src/djangobase/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/settings.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/settings.cpython-37.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /src/djangobase/__pycache__/wsgi.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/djangobase/__pycache__/wsgi.cpython-37.pyc -------------------------------------------------------------------------------- /src/djangobase/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for djangobase project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.1.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.1/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '6++@jy24bl1!on^5p_3(v=aysnnv!g&l$%$#r&50%pp@7danhe' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [ '127.0.0.1',] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 41 | # custom 42 | 'rest_framework', 43 | 'rest_framework.authtoken', 44 | 45 | 46 | 47 | 48 | 'accounts.apps.AccountsConfig', 49 | 'products.apps.ProductsConfig', 50 | 'tools.apps.ToolsConfig', 51 | 'cart.apps.CartConfig', 52 | 53 | 54 | 55 | 'webpack_loader', 56 | ] 57 | 58 | MIDDLEWARE = [ 59 | 'django.middleware.security.SecurityMiddleware', 60 | 'django.contrib.sessions.middleware.SessionMiddleware', 61 | 'django.middleware.common.CommonMiddleware', 62 | 'django.middleware.csrf.CsrfViewMiddleware', 63 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 64 | 'django.contrib.messages.middleware.MessageMiddleware', 65 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 66 | ] 67 | 68 | ROOT_URLCONF = 'djangobase.urls' 69 | 70 | TEMPLATES = [ 71 | { 72 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 73 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 74 | 'APP_DIRS': True, 75 | 'OPTIONS': { 76 | 'context_processors': [ 77 | 'django.template.context_processors.debug', 78 | 'django.template.context_processors.request', 79 | 'django.contrib.auth.context_processors.auth', 80 | 'django.contrib.messages.context_processors.messages', 81 | ], 82 | }, 83 | }, 84 | ] 85 | 86 | WSGI_APPLICATION = 'djangobase.wsgi.application' 87 | 88 | 89 | # Database 90 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 91 | 92 | DATABASES = { 93 | 'default': { 94 | 'ENGINE': 'django.db.backends.sqlite3', 95 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 96 | } 97 | } 98 | 99 | 100 | # Password validation 101 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 102 | 103 | AUTH_PASSWORD_VALIDATORS = [ 104 | { 105 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 106 | }, 107 | { 108 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 109 | }, 110 | { 111 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 112 | }, 113 | { 114 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 115 | }, 116 | ] 117 | 118 | 119 | # Internationalization 120 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 121 | 122 | LANGUAGE_CODE = 'en-us' 123 | 124 | TIME_ZONE = 'UTC' 125 | 126 | USE_I18N = True 127 | 128 | USE_L10N = True 129 | 130 | USE_TZ = True 131 | 132 | 133 | # Static files (CSS, JavaScript, Images) 134 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 135 | 136 | STATIC_URL = '/static/' 137 | 138 | 139 | STATICFILES_DIRS = ( 140 | os.path.join(BASE_DIR, 'assets'), 141 | os.path.join(BASE_DIR, 'static'), 142 | ) 143 | 144 | MEDIA_URL = '/media/' 145 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 146 | 147 | 148 | 149 | 150 | WEBPACK_LOADER = { 151 | 'DEFAULT': { 152 | 'BUNDLE_DIR_NAME': 'bundles/', 153 | 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), 154 | } 155 | } 156 | 157 | 158 | REST_FRAMEWORK = { 159 | 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 160 | 'PAGE_SIZE': 1000, 161 | 'DEFAULT_AUTHENTICATION_CLASSES': [ 162 | 'rest_framework.authentication.TokenAuthentication', 163 | 164 | ], 165 | 166 | 'DEFAULT_PERMISSION_CLASSES': [ 167 | # the below line makes it so that only safe requests can be made. if i disable this it will go to the defualt which enables everyone to make any request they want 168 | # 'rest_framework.permissions.IsAuthenticatedOrReadOnly', 169 | 170 | ], 171 | 172 | } 173 | 174 | 175 | 176 | 177 | 178 | 179 | #stripe 180 | STRIPE_SECRET_KEY = 'sk_test_wg8FOAYcX0GVYDwBDGN6YBA900ZrFMGbOl' 181 | STRIPE_PUBLISHABLE_KEY = 'pk_test_moebTzwREoSuQmQpWYNqJJ8w0031fdJlIb' -------------------------------------------------------------------------------- /src/djangobase/urls.py: -------------------------------------------------------------------------------- 1 | """djangobase URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.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 | from rest_framework import routers 21 | from products import views as productviews 22 | 23 | 24 | router = routers.DefaultRouter() 25 | router.register('categories', productviews.CategoryView) 26 | router.register('suppliers', productviews.SupplierView) 27 | router.register('products', productviews.ProductView) 28 | router.register('productimages', productviews.ProductImageView) 29 | 30 | #including the models of a different app here to add them to the api easily 31 | from cart import views as cartviews 32 | router.register('cart', cartviews.CartViewSet) 33 | router.register('cartitem', cartviews.CartItemViewSet) 34 | router.register('checkoutdetails', cartviews.CheckoutDetailsViewSet) 35 | 36 | 37 | 38 | urlpatterns = [ 39 | path('admin/', admin.site.urls), 40 | path('', include('products.urls')), 41 | path('accounts/', include('accounts.urls')), 42 | path('cart/', include('cart.urls')), 43 | path('api/', include(router.urls)) 44 | ]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 45 | -------------------------------------------------------------------------------- /src/djangobase/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djangobase project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangobase.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /src/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == '__main__': 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangobase.settings') 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /src/media/images/products/amdryzen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/amdryzen.jpg -------------------------------------------------------------------------------- /src/media/images/products/amdryzen_os8lQqg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/amdryzen_os8lQqg.jpg -------------------------------------------------------------------------------- /src/media/images/products/craft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/craft.png -------------------------------------------------------------------------------- /src/media/images/products/dell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/dell.jpg -------------------------------------------------------------------------------- /src/media/images/products/dell_EcKwBkR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/dell_EcKwBkR.jpg -------------------------------------------------------------------------------- /src/media/images/products/dell_EcKwBkR_2F5kFTg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/dell_EcKwBkR_2F5kFTg.jpg -------------------------------------------------------------------------------- /src/media/images/products/download.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/download.jpg -------------------------------------------------------------------------------- /src/media/images/products/download_FP4TC6M.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/download_FP4TC6M.jpg -------------------------------------------------------------------------------- /src/media/images/products/freesyncMonitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/freesyncMonitor.jpg -------------------------------------------------------------------------------- /src/media/images/products/freesyncMonitor_HpeZe5S.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/freesyncMonitor_HpeZe5S.jpg -------------------------------------------------------------------------------- /src/media/images/products/hard_drive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/hard_drive.jpg -------------------------------------------------------------------------------- /src/media/images/products/ibm_keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/ibm_keyboard.png -------------------------------------------------------------------------------- /src/media/images/products/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/images.jpg -------------------------------------------------------------------------------- /src/media/images/products/images_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/images_1.jpg -------------------------------------------------------------------------------- /src/media/images/products/model_o.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/model_o.jpg -------------------------------------------------------------------------------- /src/media/images/products/monitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/monitor.jpg -------------------------------------------------------------------------------- /src/media/images/products/monitor_QeSctlX.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/monitor_QeSctlX.jpg -------------------------------------------------------------------------------- /src/media/images/products/monitor_RLxIcQV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/monitor_RLxIcQV.jpg -------------------------------------------------------------------------------- /src/media/images/products/monitor_iuwEmNm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/monitor_iuwEmNm.jpg -------------------------------------------------------------------------------- /src/media/images/products/mouse_basic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/mouse_basic.jpg -------------------------------------------------------------------------------- /src/media/images/products/ryzen.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/ryzen.webp -------------------------------------------------------------------------------- /src/media/images/products/ssd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/media/images/products/ssd.jpg -------------------------------------------------------------------------------- /src/products/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__init__.py -------------------------------------------------------------------------------- /src/products/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/apps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/apps.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/serializers.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/serializers.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/utils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/utils.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/__pycache__/views.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/__pycache__/views.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from .models import Product, Category, ProductImage, Supplier 5 | 6 | admin.site.register(Supplier) 7 | admin.site.register(Category) 8 | admin.site.register(Product) 9 | admin.site.register(ProductImage) 10 | -------------------------------------------------------------------------------- /src/products/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProductsConfig(AppConfig): 5 | name = 'products' 6 | -------------------------------------------------------------------------------- /src/products/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-06-10 19:14 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Category', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('name', models.CharField(max_length=20, unique=True)), 20 | ('slug', models.SlugField(max_length=20, unique=True)), 21 | ('description', models.TextField(blank=True, null=True)), 22 | ('image_url', models.ImageField(blank=True, null=True, upload_to='images/categorys')), 23 | ('tags', models.CharField(blank=True, help_text='SEO keywords', max_length=100, null=True)), 24 | ('display_order', models.IntegerField(default=0)), 25 | ('is_active', models.BooleanField(default=True)), 26 | ('is_expended', models.BooleanField(default=False, help_text='Catergory will always shown expended')), 27 | ('updated_by', models.CharField(max_length=100)), 28 | ('updated_on', models.DateTimeField(auto_now=True)), 29 | ('created_on', models.DateTimeField(auto_now_add=True)), 30 | ('created_by', models.CharField(max_length=100)), 31 | ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sub_categories', to='products.Category')), 32 | ], 33 | options={ 34 | 'verbose_name_plural': 'Categories', 35 | 'ordering': ('display_order', 'id'), 36 | }, 37 | ), 38 | migrations.CreateModel( 39 | name='Product', 40 | fields=[ 41 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 42 | ('title', models.CharField(max_length=250)), 43 | ('description', models.TextField(blank=True, max_length=800, null=True)), 44 | ('current_price', models.DecimalField(decimal_places=2, max_digits=9)), 45 | ('base_price', models.DecimalField(decimal_places=2, max_digits=9)), 46 | ('cost', models.DecimalField(decimal_places=2, default=0, max_digits=9)), 47 | ('quantity', models.IntegerField()), 48 | ('tags', models.CharField(blank=True, help_text='keywords to help with searching and SEO', max_length=250, null=True)), 49 | ('weight', models.FloatField(default=0)), 50 | ('length', models.FloatField(default=0)), 51 | ('width', models.FloatField(default=0)), 52 | ('height', models.FloatField(default=0)), 53 | ('updated_by', models.CharField(max_length=100)), 54 | ('updated_on', models.DateTimeField(auto_now=True)), 55 | ('created_on', models.DateTimeField(auto_now_add=True)), 56 | ('created_by', models.CharField(max_length=100)), 57 | ('catagory', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='products.Category')), 58 | ], 59 | ), 60 | migrations.CreateModel( 61 | name='Supplier', 62 | fields=[ 63 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 64 | ('company_name', models.CharField(max_length=40)), 65 | ('description', models.CharField(max_length=1600)), 66 | ('contact_email', models.CharField(max_length=100)), 67 | ('phone_number', models.IntegerField()), 68 | ('full_address', models.CharField(max_length=200)), 69 | ('other_contact', models.CharField(blank=True, max_length=200, null=True)), 70 | ('updated_by', models.CharField(max_length=100)), 71 | ('updated_on', models.DateTimeField(auto_now=True)), 72 | ('created_on', models.DateTimeField(auto_now_add=True)), 73 | ('created_by', models.CharField(max_length=100)), 74 | ], 75 | ), 76 | migrations.CreateModel( 77 | name='ProductImage', 78 | fields=[ 79 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 80 | ('display_order', models.IntegerField(default=0)), 81 | ('image_url', models.ImageField(upload_to='images/products')), 82 | ('updated_by', models.CharField(max_length=100)), 83 | ('updated_on', models.DateTimeField(auto_now=True)), 84 | ('created_on', models.DateTimeField(auto_now_add=True)), 85 | ('created_by', models.CharField(max_length=100)), 86 | ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.Product')), 87 | ], 88 | ), 89 | migrations.AddField( 90 | model_name='product', 91 | name='supplier', 92 | field=models.ForeignKey(default='pepega', on_delete=django.db.models.deletion.CASCADE, to='products.Supplier'), 93 | ), 94 | ] 95 | -------------------------------------------------------------------------------- /src/products/migrations/0002_remove_supplier_other_contact.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-06-10 19:16 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='supplier', 15 | name='other_contact', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /src/products/migrations/0003_auto_20190610_1519.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-06-10 19:19 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0002_remove_supplier_other_contact'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='product', 15 | old_name='supplier', 16 | new_name='_supplier', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/migrations/0004_auto_20190610_1521.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-06-10 19:21 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0003_auto_20190610_1519'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='product', 15 | old_name='_supplier', 16 | new_name='product_supplier', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/migrations/0005_auto_20191113_0458.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-11-13 12:58 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0004_auto_20190610_1521'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='category', 15 | options={'ordering': ('display_order', 'id')}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /src/products/migrations/0006_auto_20191113_0459.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-11-13 12:59 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0005_auto_20191113_0458'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='category', 15 | name='image_url', 16 | field=models.ImageField(blank=True, null=True, upload_to='static/images/categorys'), 17 | ), 18 | migrations.AlterField( 19 | model_name='productimage', 20 | name='image_url', 21 | field=models.ImageField(upload_to='static/images/products'), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /src/products/migrations/0007_remove_productimage_display_order.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-11-20 01:14 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0006_auto_20191113_0459'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='productimage', 15 | name='display_order', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /src/products/migrations/0008_auto_20191205_1323.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-12-05 21:23 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0007_remove_productimage_display_order'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='product', 15 | old_name='catagory', 16 | new_name='category', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/migrations/0009_productimage_main_picture.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-12-11 05:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0008_auto_20191205_1323'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='productimage', 15 | name='main_picture', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/migrations/0010_auto_20191230_1805.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.1 on 2019-12-31 02:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0009_productimage_main_picture'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='category', 15 | name='image_url', 16 | field=models.ImageField(blank=True, null=True, upload_to='images/categories'), 17 | ), 18 | migrations.AlterField( 19 | model_name='productimage', 20 | name='image_url', 21 | field=models.ImageField(upload_to='images/products'), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /src/products/migrations/0011_product_featured.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-01-28 11:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('products', '0010_auto_20191230_1805'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='product', 15 | name='featured', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/migrations/0012_auto_20201028_2346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.9 on 2020-10-29 06:46 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('products', '0011_product_featured'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='product', 16 | name='category', 17 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='products.Category'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /src/products/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__init__.py -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0001_initial.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0001_initial.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0002_remove_supplier_other_contact.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0002_remove_supplier_other_contact.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0003_auto_20190610_1519.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0003_auto_20190610_1519.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0004_auto_20190610_1521.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0004_auto_20190610_1521.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0005_auto_20191113_0458.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0005_auto_20191113_0458.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0006_auto_20191113_0459.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0006_auto_20191113_0459.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0007_remove_productimage_display_order.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0007_remove_productimage_display_order.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0008_auto_20191205_1323.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0008_auto_20191205_1323.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0009_productimage_main_picture.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0009_productimage_main_picture.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0010_auto_20191230_1805.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0010_auto_20191230_1805.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0011_product_featured.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0011_product_featured.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/0012_auto_20201028_2346.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/0012_auto_20201028_2346.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.db.models import Min 3 | from tools.data_structures import Tree 4 | 5 | # Create your models here. 6 | 7 | class Supplier(models.Model): 8 | company_name = models.CharField(max_length=40) 9 | description = models.CharField(max_length=1600) 10 | contact_email = models.CharField(max_length=100) 11 | phone_number = models.IntegerField() 12 | full_address = models.CharField(max_length=200) 13 | updated_by = models.CharField(max_length=100) 14 | updated_on = models.DateTimeField(auto_now=True) 15 | created_on = models.DateTimeField(auto_now_add=True) 16 | created_by = models.CharField(max_length=100) 17 | 18 | def __str__(self): 19 | return self.company_name 20 | 21 | 22 | 23 | class Category(models.Model): 24 | name = models.CharField(max_length=20, unique=True) 25 | slug = models.SlugField(max_length=20, unique=True)#delete this 26 | description = models.TextField(null=True, blank=True) 27 | image_url = models.ImageField(upload_to='images/categories',null=True, blank=True) 28 | parent = models.ForeignKey('self', related_name='sub_categories', null=True, blank=True, on_delete=models.CASCADE) 29 | tags = models.CharField(max_length=100, null=True, blank=True, help_text='SEO keywords') 30 | display_order = models.IntegerField(default=0) 31 | is_active = models.BooleanField(default=True) 32 | is_expended = models.BooleanField(default=False, help_text='Catergory will always shown expended') #delete this 33 | updated_by = models.CharField(max_length=100) 34 | updated_on = models.DateTimeField(auto_now=True) 35 | created_on = models.DateTimeField(auto_now_add=True) 36 | created_by = models.CharField(max_length=100) 37 | 38 | class Meta: 39 | ordering = ('display_order', 'id',) 40 | 41 | def __init__(self, *args, **kwargs): 42 | super(Category, self).__init__(*args, **kwargs) 43 | self.sub_categories_list = None 44 | 45 | def __str__(self): 46 | return self.name 47 | 48 | @classmethod 49 | def get_all_categories(cls): 50 | return cls.objects.filter(is_active = True) 51 | 52 | @classmethod 53 | def update_sub_category_lists(cls): 54 | all_categories = cls.get_all_categories() 55 | for single_category in all_categories: 56 | sub_categories = [] 57 | for one_category in all_categories: 58 | if one_category.parent_id == single_category.id: 59 | sub_categories.append(one_category) 60 | single_category.sub_categories_list = sub_categories 61 | return all_categories 62 | 63 | 64 | @staticmethod 65 | def find_main_categories(categories): 66 | # find value of lowest display order 67 | min_display_order = 324234 68 | for category in categories: 69 | if category.display_order < min_display_order: 70 | min_display_order = category.display_order 71 | # find and then return main categories 72 | main_categories = [] 73 | for category in categories: 74 | if category.display_order == min_display_order: 75 | main_categories.append(category) 76 | return main_categories 77 | 78 | # maybe refactor this abomination later? 79 | def get_all_sub_categories(self): 80 | all_categories = self.update_sub_category_lists() 81 | for cat in all_categories: 82 | if cat.id == self.id: 83 | category = cat 84 | break 85 | 86 | def traverse_tree(category): 87 | if category.sub_categories_list != None: 88 | for sub_category in category.sub_categories_list: 89 | traverse_tree(sub_category) 90 | yield sub_category 91 | generator_with_sub_categories = traverse_tree(category) 92 | 93 | list_of_all_sub_categories = [] 94 | for x in generator_with_sub_categories: 95 | list_of_all_sub_categories.append(x) 96 | return list_of_all_sub_categories 97 | 98 | 99 | 100 | 101 | class Product(models.Model): 102 | title = models.CharField(max_length=250) 103 | description = models.TextField(max_length=800, null=True, blank=True) 104 | category = models.ForeignKey(Category,null=True, on_delete=models.SET_NULL)########################################################################## 105 | product_supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, default='pepega')################################################################# 106 | current_price = models.DecimalField(max_digits=9,decimal_places=2) 107 | base_price = models.DecimalField(max_digits=9,decimal_places=2) 108 | cost = models.DecimalField(max_digits=9,decimal_places=2,default=0) 109 | quantity = models.IntegerField() 110 | tags = models.CharField(max_length=250, null=True, blank=True, help_text='keywords to help with searching and SEO') 111 | weight = models.FloatField(default=0) 112 | length = models.FloatField(default=0) 113 | width = models.FloatField(default=0) 114 | height = models.FloatField(default=0) 115 | # this is a new field im adding for featured products that go on the home page on the slider 116 | featured = models.BooleanField(default=False) 117 | updated_by = models.CharField(max_length=100) 118 | updated_on = models.DateTimeField(auto_now=True) 119 | created_on = models.DateTimeField(auto_now_add=True) 120 | created_by = models.CharField(max_length=100) 121 | 122 | 123 | def __str__(self): 124 | return self.title 125 | 126 | 127 | # def return_all_child_categories(self): 128 | # return self.category.get_all_sub_categories() 129 | 130 | @classmethod 131 | def get_all_products(cls): 132 | return cls.objects.filter(featured=False) 133 | 134 | @classmethod 135 | def get_products_by_category_id(cls, category_id): 136 | return cls.objects.filter(category_id = category_id) 137 | 138 | 139 | @classmethod 140 | def get_products_from_list_of_categories(cls, list_of_category_and_all_its_sub_categories): 141 | products = [] 142 | for single_category in list_of_category_and_all_its_sub_categories: 143 | product = list(cls.objects.filter(category = single_category)) 144 | products = products + product 145 | return products 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | class ProductImage(models.Model): 158 | product = models.ForeignKey(Product, on_delete=models.CASCADE)############################################ 159 | image_url = models.ImageField(upload_to='images/products') 160 | main_picture = models.BooleanField(default=False) 161 | updated_by = models.CharField(max_length=100) 162 | updated_on = models.DateTimeField(auto_now=True) 163 | created_on = models.DateTimeField(auto_now_add=True) 164 | created_by = models.CharField(max_length=100) 165 | 166 | def __str__(self): 167 | return self.product.title 168 | 169 | @classmethod 170 | def find_product_images(cls, product_id): 171 | return cls.objects.filter(product_id = product_id, main_picture = False) 172 | 173 | @classmethod 174 | def find_main_product_image(cls, product_id): 175 | return cls.objects.get(product_id = product_id, main_picture = True) 176 | 177 | @classmethod 178 | def find_all_product_images(cls, product_id): 179 | return cls.objects.filter(product_id = product_id) -------------------------------------------------------------------------------- /src/products/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from .models import Category, Supplier, Product, ProductImage 3 | 4 | class SupplierSerializer(serializers.HyperlinkedModelSerializer): 5 | class Meta: 6 | model = Supplier 7 | fields = ('id', 'company_name', 'description', 'contact_email', 'phone_number', 'full_address', 'updated_by', 'updated_on', 'created_on', 'created_by' ) 8 | 9 | 10 | class CategorySerializer(serializers.HyperlinkedModelSerializer): 11 | 12 | class Meta: 13 | model = Category 14 | fields = ( 'id', 'url', 'name', 'slug', 'description', 'image_url', 'parent', 'tags', 'display_order', 'is_active', 'updated_by', 'updated_on', 'created_on', 'created_by' ) 15 | 16 | class ProductSerializer(serializers.HyperlinkedModelSerializer): 17 | 18 | 19 | class Meta: 20 | model = Product 21 | fields = ( 'id', 'title', 'description', 'category', 'product_supplier', 'current_price', 'base_price', 'cost', 'quantity', 'tags', 'weight', 'length', 'width', 'height', 'featured', 'updated_by', 'updated_on', 'created_on', 'created_by' ) 22 | 23 | class ProductImageSerializer(serializers.HyperlinkedModelSerializer): 24 | 25 | class Meta: 26 | model = ProductImage 27 | fields = ( 'id', 'product', 'image_url', 'main_picture', 'updated_by', 'updated_on', 'created_on', 'created_by') 28 | 29 | -------------------------------------------------------------------------------- /src/products/templates/products/components/categories.html: -------------------------------------------------------------------------------- 1 | {% for category in main_categories %} 2 | {% include "products/components/category_recursion.html" %} 3 | {% endfor %} -------------------------------------------------------------------------------- /src/products/templates/products/components/category_recursion.html: -------------------------------------------------------------------------------- 1 |
  • 2 | {% if category.sub_categories_list != empty_list %} 3 | 4 | 7 | 12 | 13 | {% else %} 14 | {{category}} 15 | {% endif %} 16 |
  • -------------------------------------------------------------------------------- /src/products/templates/products/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | 3 | {% block before_container %} 4 |
    5 |
    6 |
    7 |
    8 | 9 |
    10 |
    11 |
    12 | {% endblock before_container %} 13 | 14 | 15 | 16 | {% block content %} 17 | 18 | {% comment %} here we load the categories {% endcomment %} 19 |
    20 | 21 |
    22 |
    23 |
    24 |
    25 | Catalog 26 |
    27 |
      28 | {%include "products/components/categories.html" %} 29 |
    30 |
    31 |
    32 | 33 | 34 |
    35 | {% comment %} here we have a slideshow of featured products {% endcomment %} 36 |


    37 | {% if featured_products %} 38 | 39 | 40 | 41 |
    42 | 43 |
    44 |
    45 |
    46 |
    47 | {% endif %} 48 | 49 | 50 | 51 | 52 | {% comment %} here we load products in card decks {% endcomment %} 53 |
    54 | {% if products_and_carddeck_checker != empty_list %} 55 | {% for product, carddeck in products_and_carddeck_checker%} 56 | {% if carddeck == 'first' %} 57 |
    58 |
    59 |
    60 |
    61 | 62 | {{product}} 63 | 64 |
    65 | {% for product_image in product_images %} 66 | {% if product_image.product == product and product_image.main_picture == True%} 67 | 68 | 69 | 70 |
    71 |

    CDN$ {{product.current_price}}

    72 | {% endif %} 73 | {% endfor %} 74 |

    {{product.description}}

    75 |
    76 |
    77 | {% endif %} 78 | {% if carddeck == True %} 79 |
    80 |
    81 |
    82 |
    83 |
    84 |
    85 | 86 | {{product}} 87 | 88 |
    89 | {% for product_image in product_images %} 90 | {% if product_image.product == product and product_image.main_picture == True%} 91 | 92 | 93 | 94 |
    95 |

    CDN$ {{product.current_price}}

    96 | {% endif %} 97 | {% endfor %} 98 |

    {{product.description}}

    99 |
    100 |
    101 | {% endif %} 102 | {% if carddeck == False %} 103 |
    104 |
    105 |
    106 | 107 | {{product}} 108 | 109 |
    110 | {% for product_image in product_images %} 111 | {% if product_image.product == product and product_image.main_picture == True%} 112 | 113 | 114 | 115 |
    116 |

    CDN$ {{product.current_price}}

    117 | {% endif %} 118 | {% endfor %} 119 |

    {{product.description}}

    120 |
    121 |
    122 | {% endif %} 123 | {% endfor %} 124 |
    125 | {% else %} 126 | could not find any items for the following specificed search keywords: {{ search_string }} 127 | {% endif %} 128 |
    129 |
    130 |
    131 | 132 | 133 | 134 | {% endblock content %} 135 | 136 | 137 | 138 | {% comment %} this isnt working i think its because i forced it by making seperate card classes {% endcomment %} 139 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /src/products/templates/products/product.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | 3 | {% block base_head %} 4 | 12 | {% endblock %} 13 | 14 | 15 | 16 | 17 | {% block content %} 18 | 19 |

    {{product}}

    20 | 21 |
    22 | 23 | {% comment %} put details here, desciprion, cost etc {% endcomment %} 24 |

    {{product.description}}

    25 | CDN${{product.current_price}} 26 | 27 | 37 |
    38 | 39 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | {% comment %} rest of the photos {% endcomment %} 51 | {% if other_images %} 52 |

    more images

    53 | {% for image in other_images %} 54 | 55 |

    56 | {%endfor%} 57 | {% endif %} 58 | 59 | {% endblock content %} 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/products/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/products/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from . import views 3 | from rest_framework import routers 4 | 5 | 6 | 7 | 8 | 9 | app_name = 'products' 10 | urlpatterns = [ 11 | path('', views.BaseLoader.as_view(), name='home'), 12 | path('category/search//', views.BaseLoader.as_view(), name='filter'), 13 | path('category/search/$', views.product_search, name='product_search'), 14 | path('api/session/', views.SessionAccess.as_view(), name='xd123'), 15 | path('api/get_url/', views.get_url, name='get_url_from_django'), 16 | path('product//', views.product_page, name='product_page'), 17 | 18 | ] 19 | -------------------------------------------------------------------------------- /src/products/utils/__pycache__/model_string_search.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/products/utils/__pycache__/model_string_search.cpython-37.pyc -------------------------------------------------------------------------------- /src/products/utils/model_string_search.py: -------------------------------------------------------------------------------- 1 | ######################################## 2 | #########product searching############## 3 | ######################################## 4 | from django.db.models import Q 5 | import re 6 | from products.models import Product 7 | 8 | def normalize_query(query_string, 9 | findterms=re.compile(r'"([^"]+)"|(\S+)').findall, 10 | normspace=re.compile(r'\s{2,}').sub): 11 | 12 | ''' 13 | Splits the query string in invidual keywords, getting rid of unecessary spaces and grouping quoted words together. 14 | Example: 15 | >>> normalize_query(' some random words "with quotes " and spaces') 16 | ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] 17 | ''' 18 | 19 | return [normspace(' ',(t[0] or t[1]).strip()) for t in findterms(query_string)] 20 | 21 | 22 | 23 | def get_query(query_string, search_fields): 24 | 25 | ''' 26 | Returns a query, that is a combination of Q objects. 27 | That combination aims to search keywords within a model by testing the given search fields. 28 | ''' 29 | 30 | query = None # Query to search for every search term 31 | terms = normalize_query(query_string) 32 | for term in terms: 33 | or_query = None # Query to search for a given term in each field 34 | for field_name in search_fields: 35 | q = Q(**{"%s__icontains" % field_name: term}) 36 | if or_query is None: 37 | or_query = q 38 | else: 39 | or_query = or_query | q 40 | if query is None: 41 | query = or_query 42 | else: 43 | query = query | or_query 44 | return query 45 | 46 | def search_for_something(request): 47 | query_string = '' 48 | found_entries = None 49 | 50 | if ('search_string' in request.GET) and request.GET['search_string'].strip(): 51 | query_string = request.GET['search_string'] 52 | entry_query = get_query(query_string, ['description', 'tags', 'title']) 53 | found_entries = Product.objects.filter(entry_query) 54 | 55 | return found_entries 56 | #################################################### 57 | ################# end of product searching functions######################## 58 | ##################################################################### -------------------------------------------------------------------------------- /src/products/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.views import View 3 | from products.models import Category, Supplier, Product, ProductImage 4 | import os 5 | from rest_framework import viewsets 6 | from .serializers import CategorySerializer, SupplierSerializer, ProductSerializer, ProductImageSerializer 7 | from django.http import HttpRequest, HttpResponse, HttpResponseNotFound, Http404 8 | from django.urls import reverse 9 | from cart.models import Cart 10 | from cart.utils.cart_management import CartManager 11 | from products.utils.model_string_search import search_for_something 12 | import urllib 13 | 14 | class BaseLoader(View): 15 | # load main page with products based on selected category 16 | def get(self, request, filter = ''): 17 | self.all_categories = Category.update_sub_category_lists() 18 | self.categories = Category.find_main_categories(self.all_categories) 19 | 20 | # here we use the filter to load the products accordingly! 21 | if filter != '': 22 | try: 23 | self.category_from_filter = Category.objects.get(name = filter) 24 | except: 25 | return HttpResponseNotFound("category not available") 26 | self.list_of_all_categories_from_filter = Category.get_all_sub_categories(self.category_from_filter) 27 | self.list_of_all_categories_from_filter.append(self.category_from_filter) 28 | self.all_products = Product.get_products_from_list_of_categories(self.list_of_all_categories_from_filter) 29 | else: 30 | self.all_products = Product.get_all_products() 31 | 32 | # update the descripton of the product 33 | for product in self.all_products: 34 | if len(product.description) > 80: 35 | product.description = product.description[:80] + '...' 36 | 37 | #now we find all the images we need for each product 38 | self.all_product_images = [] 39 | for product in self.all_products: 40 | img = list(ProductImage.find_all_product_images(product.id)) 41 | self.all_product_images += img 42 | 43 | # here we zip the product data with another list that has values to help the template determine when it should start a new card-deck as apposed to card 44 | card_deck_update_check = [] 45 | i= 0 46 | for product in self.all_products: 47 | if i==0: 48 | card_deck_update_check.append('first') 49 | elif i%3: 50 | card_deck_update_check.append(False) 51 | else: 52 | card_deck_update_check.append(True) 53 | i += 1 54 | products_and_carddeck_checker = zip(self.all_products, card_deck_update_check) 55 | 56 | if filter == '': 57 | self.featured_products = Product.objects.filter(featured=True) 58 | 59 | self.featured_product_images = [] 60 | for featured_product in self.featured_products: 61 | img = list(ProductImage.find_all_product_images(featured_product.id)) 62 | self.featured_product_images += img 63 | # this should be to load the homepage, so give featured products and catalog data featured_products 64 | return render(request, 'products/home.html', {'main_categories':self.categories, 'all_categories':self.all_categories, 'products':self.all_products, 'products_and_carddeck_checker':products_and_carddeck_checker, 'product_images':self.all_product_images, 'empty_list':[], 'featured_products':self.featured_products, 'featured_product_images':self.featured_product_images }) 65 | return render(request, 'products/home.html', {'main_categories':self.categories, 'all_categories':self.all_categories, 'products':self.all_products, 'products_and_carddeck_checker':products_and_carddeck_checker, 'product_images':self.all_product_images, 'empty_list':[] }) 66 | 67 | 68 | 69 | 70 | def product_page(request, product_id): 71 | # get cart data 72 | cart_manager = CartManager(request) 73 | # creating the urls needed by the template to make its request to the api 74 | urls_cart = request.build_absolute_uri('/api/cart/' + urllib.parse.quote(str(cart_manager.cart.id)) + '/') 75 | urls_product = request.build_absolute_uri('/api/products/' + urllib.parse.quote(str(product_id)) + '/') 76 | 77 | if request.user.is_authenticated: 78 | username = request.user.get_username() 79 | else: 80 | username = '' 81 | 82 | #find product and give it to template 83 | main_product = Product.objects.get(id = product_id) 84 | main_image = ProductImage.find_main_product_image(product_id) 85 | other_images = ProductImage.find_product_images(product_id) 86 | 87 | 88 | return render(request, 'products/product.html', {'product':main_product, 'main_image':main_image, 'other_images':other_images, 'cart':cart_manager.cart, 'urls_cart':urls_cart, 'urls_product':urls_product, 'username':username}) 89 | 90 | 91 | def product_search(request): 92 | all_categories = Category.update_sub_category_lists() 93 | categories = Category.find_main_categories(all_categories) 94 | 95 | # this function here uses whats in the search bar and uses that string to find all products related to it, the search results are not ordered in anyway, its random, which should be changed 96 | found_products = search_for_something(request) 97 | 98 | if found_products: 99 | for product in found_products: 100 | if len(product.description) > 80: 101 | product.description = product.description[:80] + '...' 102 | 103 | 104 | # here we zip the product data with another list that has values to help the template determine when it should start a new card-deck as apposed to card 105 | products_and_carddeck_checker = [] 106 | if found_products: 107 | card_deck_update_check = [] 108 | i= 0 109 | for product in found_products: 110 | if i==0: 111 | card_deck_update_check.append('first') 112 | elif i%3: 113 | card_deck_update_check.append(False) 114 | else: 115 | card_deck_update_check.append(True) 116 | i += 1 117 | products_and_carddeck_checker = zip(found_products, card_deck_update_check) 118 | 119 | 120 | all_product_images = [] 121 | if found_products: 122 | for product in found_products: 123 | img = list(ProductImage.find_all_product_images(product.id)) 124 | all_product_images += img 125 | 126 | search_string = request.GET['search_string'] 127 | return render(request, 'products/home.html', {'main_categories':categories, 'all_categories':all_categories, 'products':found_products, 'products_and_carddeck_checker':products_and_carddeck_checker, 'product_images':all_product_images, 'empty_list':[], 'search_string':search_string }) 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | #these are for setting up the api for all the models using the django rest framework 146 | class SupplierView(viewsets.ModelViewSet): 147 | queryset = Supplier.objects.all() 148 | serializer_class = SupplierSerializer 149 | 150 | class CategoryView(viewsets.ModelViewSet): 151 | queryset = Category.objects.all() 152 | serializer_class = CategorySerializer 153 | 154 | class ProductView(viewsets.ModelViewSet): 155 | queryset = Product.objects.all() 156 | serializer_class = ProductSerializer 157 | 158 | class ProductImageView(viewsets.ModelViewSet): 159 | queryset = ProductImage.objects.all() 160 | serializer_class = ProductImageSerializer 161 | 162 | 163 | 164 | 165 | # simple session read write api 166 | class SessionAccess(View): 167 | def get(self, request): 168 | index = request.GET['index'] 169 | if index in request.session: 170 | return HttpResponse(request.session[index]) 171 | else: 172 | return HttpResponse(False) 173 | 174 | 175 | def post(self, request): 176 | index = request.POST['index'] 177 | value = request.POST['value'] 178 | request.session[index] = value 179 | return HttpResponse(request.session[index]) 180 | 181 | 182 | 183 | 184 | # api -> featured product + featured product images, title 185 | # notinapi -> urll 'products:product_page' 186 | 187 | #simple api request that takes in app name, path url name, and returns the full url, its like being able to do {{ url 'appName:urlName' 'variable'}} 188 | def get_url(request): 189 | app_and_url_name = request.GET['app_and_url_name'] 190 | if request.GET['url_arg']: 191 | url_arg = request.GET['url_arg'] 192 | url = reverse(app_and_url_name, args=[url_arg]) 193 | else: 194 | url = reverse(app_and_url_name) 195 | return HttpResponse(url) 196 | 197 | -------------------------------------------------------------------------------- /src/static/base/css/index.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .fade-enter-active, .fade-leave-active { 4 | transition: opacity .5s; 5 | } 6 | .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { 7 | opacity: 0; 8 | } 9 | h5 { 10 | color:red 11 | } 12 | 13 | p { 14 | color: #2f5687; 15 | 16 | } -------------------------------------------------------------------------------- /src/static/base/imgs/cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/static/base/imgs/cpu.png -------------------------------------------------------------------------------- /src/static/base/imgs/shopping-cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/static/base/imgs/shopping-cart.png -------------------------------------------------------------------------------- /src/static/base/imgs/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/static/base/imgs/user.png -------------------------------------------------------------------------------- /src/templates/base/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | {% load render_bundle from webpack_loader %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% block title %} 16 | eCommerce Django Vue 17 | {% endblock %} 18 | 19 | 20 | {% block base_head %} 21 | {% endblock %} 22 | 23 | {% block styles %} 24 | {% endblock %} 25 | 26 | 27 |
    28 | 29 | {% include 'base/header.html' %} 30 | 31 | {% block before_container %} 32 | {% endblock %} 33 | 34 |
    35 | {% block content %} 36 | {% endblock %} 37 | 38 |
    39 | {% include 'base/footer.html' %} 40 |
    41 | {% render_bundle 'main' %} 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/templates/base/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |










    4 |
    5 | 6 | 7 |
    8 | 9 | 10 |
    11 | 12 | 13 |
    14 | 15 | 16 |
    17 |

    DISCLAIMER: please note this site is ment as a demo, its not a real store, i dont own any of the products or brands on here and nothing will actaully be shipped, stripe (the integrated payment system) is in test mode, so real cards will be declined

    18 | 19 |
    20 |
    21 |
    During checkout use the numbers on the right to advance through the checkout process: 22 |
    23 |
    24 |

    visa card number: 42 42 42 42 42 42 42 42 25 |
    CVC: Any 3 digits 26 |
    date: Any future date 27 |
    28 |
    29 |
    check out the rest api page 30 |
    31 | 32 | 33 |
    34 | 35 |
    36 | 37 | 38 |
    39 | 40 | 41 | 42 |
    43 | 44 | 45 |
    46 | 47 | 48 | 49 | 51 | 52 | 53 |
    54 | -------------------------------------------------------------------------------- /src/templates/base/header.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | -------------------------------------------------------------------------------- /src/templates/base/navigation_old.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__init__.py -------------------------------------------------------------------------------- /src/tools/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/__pycache__/apps.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__pycache__/apps.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/__pycache__/data_structures.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__pycache__/data_structures.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/tools/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ToolsConfig(AppConfig): 5 | name = 'tools' 6 | -------------------------------------------------------------------------------- /src/tools/data_structures.py: -------------------------------------------------------------------------------- 1 | class Tree(): 2 | class Node(): 3 | def __init__(self, value, parent=None): 4 | self._value = value 5 | self._parent = parent 6 | self._children = [] 7 | 8 | 9 | def __init__(self, value): 10 | self._root = self.Node(value) 11 | 12 | def add_child(self, parent_node, child_node_value): 13 | self._node = self.Node(child_node_value, parent_node) 14 | parent_node._children.append(self._node) -------------------------------------------------------------------------------- /src/tools/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/migrations/__init__.py -------------------------------------------------------------------------------- /src/tools/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammadRafik/ecom_django_vue/5d26e67dfbd6bd3825fabdd32959a7921d0d77b0/src/tools/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /src/tools/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/tools/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/tools/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /src/webpack-stats.json: -------------------------------------------------------------------------------- 1 | {"status":"done","chunks":{"main":[{"name":"app.js","path":"/home/ham/Documents/active_dev/ecom_django_vue/src/assets/bundles/app.js"}]}} -------------------------------------------------------------------------------- /todos.txt: -------------------------------------------------------------------------------- 1 | refactor the repetetive and bad code -i did a lot of this, still got more to go tho 2 | 3 | add back button when on product page 4 | 5 | -rename products app to catalog 6 | 7 | when i drag the vuper slides to move them it still registers as a click and opens the page, -temporarily fixed by disabling the drag feature.... xd 8 | 9 | 10 | 11 | 12 | 13 | 14 | the standard data format between frontend and backend should be json 15 | 16 | security, validating and sanitize user inputs!!! should try to do a fuzz test afterwards 17 | 18 | xss, cross site scripting? 19 | 20 | look up and learn about "django template json" 21 | 22 | urlib.parse.quote -------------------------------------------------------------------------------- /webpack-stats.json: -------------------------------------------------------------------------------- 1 | {"status":"done","chunks":{"main":[{"name":"app.js","path":"/home/ham/Documents/ecom_django_vue/src/assets/bundles/app.js"}]},"error":"ModuleBuildError","message":"Module build failed (from ./node_modules/babel-loader/lib/index.js):\nSyntaxError: /home/ham/Documents/ecom_django_vue/src/assets/js/mixins/base_global.js: Identifier 'product_url' has already been declared (32:16)\n\n 30 | \n 31 | let cart_url = document.getElementById('cart_cart_url').value;\n> 32 | let product_url = document.getElementById('cart_product_url').value;\n | ^\n 33 | let quantity = document.getElementById('cart_quantity').value;\n 34 | let updated_by = document.getElementById('cart_updated_by').value;\n 35 | let created_by = document.getElementById('cart_created_by').value;\n at Parser.raise (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:6420:17)\n at ScopeHandler.checkRedeclarationInScope (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:3776:12)\n at ScopeHandler.declareName (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:3742:12)\n at Parser.checkLVal (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8159:22)\n at Parser.parseVarId (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10682:10)\n at Parser.parseVar (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10657:12)\n at Parser.parseVarStatement (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10479:10)\n at Parser.parseStatementContent (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10076:21)\n at Parser.parseStatement (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10009:17)\n at Parser.parseBlockOrModuleBlockBody (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10585:25)\n at Parser.parseBlockBody (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10572:10)\n at Parser.parseBlock (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10556:10)\n at Parser.parseFunctionBody (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9584:24)\n at Parser.parseFunctionBodyAndFinish (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9554:10)\n at withTopicForbiddingContext (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10717:12)\n at Parser.withTopicForbiddingContext (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9884:14)\n at Parser.parseFunction (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:10716:10)\n at Parser.parseFunctionExpression (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9032:17)\n at Parser.parseExprAtom (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8945:21)\n at Parser.parseExprSubscripts (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8556:23)\n at Parser.parseMaybeUnary (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8536:21)\n at Parser.parseExprOps (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8402:23)\n at Parser.parseMaybeConditional (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8375:23)\n at Parser.parseMaybeAssign (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8325:21)\n at Parser.parseObjectProperty (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9441:101)\n at Parser.parseObjPropValue (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9466:101)\n at Parser.parseObjectMember (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9390:10)\n at Parser.parseObj (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9314:25)\n at Parser.parseExprAtom (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8939:28)\n at Parser.parseExprSubscripts (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8556:23)\n at Parser.parseMaybeUnary (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8536:21)\n at Parser.parseExprOps (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8402:23)\n at Parser.parseMaybeConditional (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8375:23)\n at Parser.parseMaybeAssign (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:8325:21)\n at Parser.parseObjectProperty (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9441:101)\n at Parser.parseObjPropValue (/home/ham/Documents/ecom_django_vue/node_modules/@babel/parser/lib/index.js:9466:101)"} -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const BundleTracker = require('webpack-bundle-tracker'); 4 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); 5 | 6 | module.exports = { 7 | context: __dirname, 8 | entry: './src/assets/js/index', 9 | output: { 10 | path: path.resolve('./src/assets/bundles/'), 11 | filename: 'app.js' 12 | }, 13 | 14 | plugins: [ 15 | new BundleTracker({filename: './src/webpack-stats.json'}), 16 | new VueLoaderPlugin(), 17 | ], 18 | 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.js$/, 23 | exclude: /node_modules/, 24 | loader: 'babel-loader', 25 | }, 26 | { 27 | test: /\.vue$/, 28 | loader: 'vue-loader' 29 | }, 30 | { 31 | test: /\.css$/, 32 | use: ['style-loader', 'css-loader'] 33 | }, 34 | ], 35 | }, 36 | resolve: { 37 | alias: {vue: 'vue/dist/vue.min.js'} 38 | }, 39 | 40 | mode: 'production', 41 | 42 | }; 43 | --------------------------------------------------------------------------------