├── auctions
├── __init__.py
├── migrations
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── 0001_initial.cpython-38.pyc
│ │ ├── 0002_auto_20200902_0116.cpython-38.pyc
│ │ ├── 0003_auto_20200902_0117.cpython-38.pyc
│ │ ├── 0004_auto_20200902_0121.cpython-38.pyc
│ │ └── 0002_remove_bidding_auction.cpython-38.pyc
│ ├── 0002_remove_bidding_auction.py
│ ├── 0002_auto_20200902_0116.py
│ ├── 0004_auto_20200902_0121.py
│ ├── 0003_auto_20200902_0117.py
│ ├── 0002_auto_20200911_0907.py
│ └── 0001_initial.py
├── tests.py
├── apps.py
├── __pycache__
│ ├── admin.cpython-38.pyc
│ ├── forms.cpython-38.pyc
│ ├── models.cpython-38.pyc
│ ├── urls.cpython-38.pyc
│ ├── views.cpython-38.pyc
│ └── __init__.cpython-38.pyc
├── static
│ └── auctions
│ │ ├── categories.css
│ │ ├── create.css
│ │ ├── login.css
│ │ └── styles.css
├── templates
│ └── auctions
│ │ ├── winner.html
│ │ ├── create.html
│ │ ├── categories.html
│ │ ├── login.html
│ │ ├── register.html
│ │ ├── allclosed.html
│ │ ├── closed.html
│ │ ├── index.html
│ │ ├── categorylistings.html
│ │ ├── layout.html
│ │ ├── watchlist.html
│ │ └── listing.html
├── admin.py
├── urls.py
├── forms.py
├── models.py
└── views.py
├── commerce
├── __init__.py
├── __pycache__
│ ├── urls.cpython-38.pyc
│ ├── wsgi.cpython-38.pyc
│ ├── __init__.cpython-38.pyc
│ └── settings.cpython-38.pyc
├── asgi.py
├── wsgi.py
├── urls.py
└── settings.py
├── .gitignore
├── Procfile
├── db.sqlite3
├── requirements.txt
├── README.md
└── manage.py
/auctions/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/commerce/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/auctions/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | auctions/__pycache__
2 | commerce/__pycache__
3 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | release: python manage.py migrate
2 | web: gunicorn Project2.wsgi
3 |
--------------------------------------------------------------------------------
/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/db.sqlite3
--------------------------------------------------------------------------------
/auctions/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/auctions/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AuctionsConfig(AppConfig):
5 | name = 'auctions'
6 |
--------------------------------------------------------------------------------
/auctions/__pycache__/admin.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/admin.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/__pycache__/forms.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/forms.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/__pycache__/models.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/models.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/__pycache__/views.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/views.cpython-38.pyc
--------------------------------------------------------------------------------
/commerce/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/commerce/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/commerce/__pycache__/wsgi.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/commerce/__pycache__/wsgi.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/commerce/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/commerce/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/commerce/__pycache__/settings.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/commerce/__pycache__/settings.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/0001_initial.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/0001_initial.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/0002_auto_20200902_0116.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/0002_auto_20200902_0116.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/0003_auto_20200902_0117.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/0003_auto_20200902_0117.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/0004_auto_20200902_0121.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/0004_auto_20200902_0121.cpython-38.pyc
--------------------------------------------------------------------------------
/auctions/migrations/__pycache__/0002_remove_bidding_auction.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/algaringo/e-commerce-website/HEAD/auctions/migrations/__pycache__/0002_remove_bidding_auction.cpython-38.pyc
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.2.10
2 | dj-database-url==0.5.0
3 | Django==3.1
4 | django-crispy-forms==1.9.2
5 | django-filter==2.3.0
6 | django-heroku==0.3.1
7 | django-widget-tweaks==1.4.8
8 | gunicorn==20.0.4
9 | psycopg2==2.8.6
10 | pytz==2020.1
11 | sqlparse==0.3.1
12 | whitenoise==5.2.0
13 |
--------------------------------------------------------------------------------
/auctions/migrations/0002_remove_bidding_auction.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-08-31 10:46
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('auctions', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='bidding',
15 | name='auction',
16 | ),
17 | ]
18 |
--------------------------------------------------------------------------------
/commerce/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for commerce project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commerce.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/commerce/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for commerce project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commerce.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/auctions/migrations/0002_auto_20200902_0116.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-09-01 17:16
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('auctions', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='bidding',
15 | name='bidprice',
16 | field=models.DecimalField(decimal_places=2, max_digits=15),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/auctions/migrations/0004_auto_20200902_0121.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-09-01 17:21
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('auctions', '0003_auto_20200902_0117'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='listing',
15 | name='startingbids',
16 | field=models.DecimalField(decimal_places=2, max_digits=15),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/auctions/static/auctions/categories.css:
--------------------------------------------------------------------------------
1 | .btn-squared-default
2 | {
3 | width: 30% !important;
4 | height: 30% !important;
5 | font-size: 10px;
6 | }
7 |
8 | .btn-squared-default:hover
9 | {
10 | border: 3px solid white;
11 | font-weight: 800;
12 | }
13 |
14 | .btn-squared-default-plain
15 | {
16 | width: 30% !important;
17 | height: 30% !important;
18 | font-size: 10px;
19 | }
20 |
21 | .btn-squared-default-plain:hover
22 | {
23 | border: 0px solid white;
24 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # e-commerce-website | [Sample Run](https://www.youtube.com/watch?v=_beRba3eHRg&t=93s)
2 |
3 | E-commerce auction site that allows users to post auction listings, place bids on listings, comment on those listings, and add listings to a “watchlist.”
4 | Using Python with Django framework, SQLite as database and Bootstrap4 for responsive design.
5 |
6 |
Installation
7 |
8 | Create Database
9 | ```
10 | python manage.py migrate
11 | ```
12 | Run Server
13 | ```
14 | python manage.py runserver
15 | ```
16 | Visit
17 | ```
18 | 127.0.0.1:8000
19 | ```
20 |
--------------------------------------------------------------------------------
/auctions/migrations/0003_auto_20200902_0117.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-09-01 17:17
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('auctions', '0002_auto_20200902_0116'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='listing',
15 | name='price',
16 | field=models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commerce.settings')
9 | try:
10 | from django.core.management import execute_from_command_line
11 | except ImportError as exc:
12 | raise ImportError(
13 | "Couldn't import Django. Are you sure it's installed and "
14 | "available on your PYTHONPATH environment variable? Did you "
15 | "forget to activate a virtual environment?"
16 | ) from exc
17 | execute_from_command_line(sys.argv)
18 |
19 |
20 | if __name__ == '__main__':
21 | main()
22 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/winner.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
Summary for {{ name }}
7 |
8 | - Listed by: {{closebidlist.lister}}
9 | {% if closebidlist.bidder == user.username %}
10 | - Highest Bidder: {{closebidlist.bidder}} (Owner of the bid)
11 | {% else %}
12 | - Highest Bidder: {{closebidlist.bidder}}
13 | {% endif %}
14 | - Final Bid: ${{closebidlist.finalbid}}
15 |
16 |
17 |
18 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/migrations/0002_auto_20200911_0907.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-09-11 01:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('auctions', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='category',
15 | name='name',
16 | field=models.CharField(blank=True, max_length=20, null=True),
17 | ),
18 | migrations.AlterField(
19 | model_name='listing',
20 | name='category',
21 | field=models.CharField(blank=True, default='', max_length=50, null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/commerce/urls.py:
--------------------------------------------------------------------------------
1 | """commerce URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import include, path
18 |
19 | urlpatterns = [
20 | path("admin/", admin.site.urls),
21 | path("", include("auctions.urls"))
22 | ]
--------------------------------------------------------------------------------
/auctions/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Listing, Bidding, Watchlist, Closebid, Comment, Category
3 |
4 | # Register your models here.
5 |
6 | class ListingAdmin(admin.ModelAdmin):
7 | list_display = ("__str__", "productnames")
8 |
9 | class BiddingAdmin(admin.ModelAdmin):
10 | list_display = ("__str__", "bidprice")
11 |
12 | class WatchlistAdmin(admin.ModelAdmin):
13 | list_display = ("__str__", "watcher")
14 |
15 | class ClosebidAdmin(admin.ModelAdmin):
16 | list_display = ("__str__", "lister")
17 |
18 | class CommentAdmin(admin.ModelAdmin):
19 | list_display = ("__str__", "user")
20 |
21 | class CategoryAdmin(admin.ModelAdmin):
22 | list_display = ("__str__", "name")
23 |
24 | admin.site.register(Listing, ListingAdmin)
25 | admin.site.register(Bidding, BiddingAdmin)
26 | admin.site.register(Watchlist, WatchlistAdmin)
27 | admin.site.register(Closebid, ClosebidAdmin)
28 | admin.site.register(Comment, CommentAdmin)
29 | admin.site.register(Category, CategoryAdmin)
--------------------------------------------------------------------------------
/auctions/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from django.conf.urls import url, include
3 |
4 | from . import views
5 |
6 | urlpatterns = [
7 | path("", views.index, name="index"),
8 | path("login", views.login_view, name="login"),
9 | path("logout", views.logout_view, name="logout"),
10 | path("register", views.register, name="register"),
11 | path("create", views.createlisting, name="create"),
12 | path("category", views.category, name="category"),
13 | path("listing/", views.listingpage, name="listingpage"),
14 | path("listing//addwatch",views.addwatch,name="addwatch"),
15 | path("listing//removewatch",views.removewatch,name="removewatch"),
16 | path("listing//bid",views.bid,name="bid"),
17 | path("listing//closebid",views.closebid,name="closebid"),
18 | path("watchlist", views.watchlist, name="watchlist"),
19 | path("listing//closed", views.closed, name="closed"),
20 | path("comment/", views.comment, name="comment"),
21 | path("category", views.category, name="category"),
22 | path("category/", views.categorylistings, name="categorylistings"),
23 | path("listing/closed", views.allclosed, name="allclosed"),
24 | ]
25 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/create.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 | {% load crispy_forms_tags %}
3 |
4 | {% block body %}
5 |
6 |
7 | Create Listings
8 |
29 |
30 |
31 |
32 | {% endblock %}
33 |
34 |
--------------------------------------------------------------------------------
/auctions/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from .models import Listing, Bidding, Comment, Category
3 |
4 | CATEGORY = Category.objects.all().values_list('name', 'name')
5 | CATEGORY1 = {
6 | ('', '')
7 | }
8 |
9 | categories = []
10 |
11 | for item in CATEGORY:
12 | categories.append(item)
13 | for item in CATEGORY1:
14 | categories.append(item)
15 |
16 | class ListingForm(forms.ModelForm):
17 | class Meta:
18 | model = Listing
19 | labels = {
20 | 'productnames' : 'Productname',
21 | 'descriptions' : 'Description',
22 | 'startingbids' : 'Starting Bids',
23 | 'images' : 'Image URL',
24 | 'category' : 'Category'
25 | }
26 | fields = [
27 | 'productnames',
28 | 'descriptions',
29 | 'startingbids',
30 | 'images',
31 | 'category'
32 | ]
33 | widgets = {
34 | 'category': forms.Select(choices=categories, attrs={'class': 'form-control'})
35 | }
36 |
37 |
38 | class BiddingForm(forms.ModelForm):
39 | class Meta:
40 | model = Bidding
41 | labels = {
42 | 'bidprice' : ''
43 | }
44 | fields = [
45 | 'bidprice'
46 | ]
47 |
48 | class CommentForm(forms.ModelForm):
49 | class Meta:
50 | model = Comment
51 | labels = {
52 | 'comment' : ''
53 | }
54 | fields = [
55 | 'comment'
56 | ]
57 |
58 |
59 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/categories.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 | {% for item in object %}
20 |
24 | {% endfor %}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/templates/auctions/login.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
8 |
9 |
10 |

11 |
12 |
13 |
14 |
15 |
Sign into your account
16 |
17 | {% if message %}
18 |
{{ message }}
19 | {% endif %}
20 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/templates/auctions/register.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Register
13 |
14 | {% if message %}
15 |
{{ message }}
16 | {% endif %}
17 |
18 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/templates/auctions/allclosed.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
8 |
CLOSED LISTINGS
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {% for object in closedlist %}
20 |
21 |
22 |
23 |
24 | {% if object.images %}
25 |
26 |
27 |
28 | {% else %}
29 |
30 |
31 |
32 | {% endif %}
33 |
38 |
39 |
40 |
41 | {% empty %}
42 |
No closed listings yet. View Active Listings.
43 | {% endfor %}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/static/auctions/create.css:
--------------------------------------------------------------------------------
1 |
2 | .get-in-touch {
3 | max-width: 800px;
4 | margin: 50px auto;
5 | position: relative;
6 |
7 | }
8 | .get-in-touch .title {
9 | text-align: center;
10 | text-transform: uppercase;
11 | letter-spacing: 3px;
12 | font-size: 3.2em;
13 | line-height: 48px;
14 | padding-bottom: 48px;
15 | color: #5543ca;
16 | background: #5543ca;
17 | background: -moz-linear-gradient(left,#f4524d 0%,#5543ca 100%) !important;
18 | background: -webkit-linear-gradient(left,#f4524d 0%,#5543ca 100%) !important;
19 | background: linear-gradient(to right,#f4524d 0%,#5543ca 100%) !important;
20 | -webkit-background-clip: text !important;
21 | -webkit-text-fill-color: transparent !important;
22 | }
23 |
24 | .contact-form .form-field {
25 | position: relative;
26 | margin: 32px 0;
27 | }
28 | .contact-form .input-text {
29 | display: block;
30 | width: 100%;
31 | height: 36px;
32 | border-width: 0 0 2px 0;
33 | border-color: #5543ca;
34 | font-size: 18px;
35 | line-height: 26px;
36 | font-weight: 400;
37 | }
38 | .contact-form .input-text:focus {
39 | outline: none;
40 | }
41 | .contact-form .input-text:focus + .label,
42 | .contact-form .input-text.not-empty + .label {
43 | -webkit-transform: translateY(-24px);
44 | transform: translateY(-24px);
45 | }
46 | .contact-form .label {
47 | position: absolute;
48 | left: 20px;
49 | bottom: 11px;
50 | font-size: 18px;
51 | line-height: 26px;
52 | font-weight: 400;
53 | color: #5543ca;
54 | cursor: text;
55 | transition: -webkit-transform .2s ease-in-out;
56 | transition: transform .2s ease-in-out;
57 | transition: transform .2s ease-in-out,
58 | -webkit-transform .2s ease-in-out;
59 | }
60 | .contact-form .submit-btn {
61 | display: inline-block;
62 | background-color: #000;
63 | background-image: linear-gradient(125deg,#a72879,#064497);
64 | color: #fff;
65 | text-transform: uppercase;
66 | letter-spacing: 2px;
67 | font-size: 16px;
68 | padding: 8px 16px;
69 | border: none;
70 | width:200px;
71 | cursor: pointer;
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/closed.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 | {% block body %}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {% if object.images %}
11 |

12 | {% else %}
13 |

14 | {% endif %}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {% if object.bidder == user.username %}
23 |
24 |
25 | CONGRATULATIONS! You won this bid!
26 |
27 | {% else %}
28 |
29 |
30 | BETTER LUCK NEXT TIME! You lost this bid.
31 |
32 | {% endif %}
33 |
34 |
35 |
Details for {{ object.productnames }}:
36 |
37 |
38 | - Highest Bidder:
39 | - {{ object.bidder }}
40 |
41 | - Final Bid:
42 | - ${{ object.finalbid }}
43 |
44 | - Listed by:
45 | - {{ object.lister }}
46 |
47 | - Checkout other Listings!
48 |
49 |
50 |
51 |
52 |
53 | {% endblock %}
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/index.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 | {% load static %}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {% for object in object %}
15 |
16 |
17 | {% if object.images %}
18 |
19 |
20 |
21 | {% else %}
22 |
23 |
24 |
25 | {% endif %}
26 |
27 |
{{ object.productnames }}
28 |
Current Bid: ${{ object.startingbids }}
29 |
30 | {{ object.descriptions }}
31 |
32 |
36 |
37 |
38 | {% endfor %}
39 |
40 |
41 |
42 | {% endblock %}
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/categorylistings.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
{{ cats }}
8 |
9 |
10 |
11 |
12 |
13 |
14 | {% if category_posts %}
15 |
16 |
17 | {% for object in category_posts %}
18 |
19 |
20 | {% if object.images %}
21 |
22 |
23 |
24 | {% else %}
25 |
26 |
27 |
28 | {% endif %}
29 |
30 |
{{ object.productnames }}
31 |
Current Bid: ${{ object.startingbids }}
32 |
33 | {{ object.descriptions }}
34 |
35 |
39 |
40 |
41 | {% endfor %}
42 |
43 |
44 | {% else %}
45 |
46 |
47 |
48 |
49 |
50 |
51 | {% endif %}
52 |
53 |
54 |
55 |
56 |
57 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/models.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import AbstractUser
2 | from django.db import models
3 | from django import forms
4 | from django.utils.timezone import now
5 |
6 | # CATEGORY = (
7 | # ('fashion', 'fashion'),
8 | # ('toys', 'toys'),
9 | # ('electronics', 'electronics'),
10 | # ('home', 'home'),
11 | # ('sports', 'sports'),
12 | # ('pets', 'pets'),
13 | # ('baby', 'baby'),
14 | # ('grocery','grocery'),
15 | # ('entertainment','entertainment'),
16 | # )
17 |
18 | class User(AbstractUser):
19 | pass
20 |
21 | class Category(models.Model):
22 | name = models.CharField(max_length=20, null=True, blank=True)
23 |
24 | def __str__(self):
25 | return self.name
26 |
27 | class Listing(models.Model):
28 | productnames = models.CharField(max_length=20)
29 | descriptions = models.TextField(max_length=500)
30 | startingbids = models.DecimalField(max_digits=15, decimal_places=2)
31 | images = models.URLField(blank=True, null=True)
32 | category = models.CharField(max_length=50, blank=True, null=True, default="")
33 | lister = models.CharField(max_length=50, blank=True, null=True)
34 | created = models.DateTimeField(default=now, editable=False)
35 |
36 | def __str__(self):
37 | return self.productnames
38 |
39 | class Bidding(models.Model):
40 | bidder = models.CharField(max_length=50, blank=True, null=True)
41 | bidprice = models.DecimalField(max_digits=15, decimal_places=2)
42 | listingid = models.IntegerField()
43 |
44 | def __str__(self):
45 | return f"{self.listingid}"
46 |
47 | class Watchlist(models.Model):
48 | productnames = models.CharField(max_length=20)
49 | images = models.URLField(blank=True, null=True)
50 | finalbid = models.DecimalField(max_digits=15, decimal_places=2)
51 | lister = models.CharField(max_length=50, blank=True, null=True)
52 | watcher = models.CharField(max_length=50, blank=True, null=True)
53 | listingid = models.IntegerField()
54 |
55 | def __str__(self):
56 | return f"{self.listingid}"
57 |
58 | class Closebid(models.Model):
59 | productnames = models.CharField(max_length=20)
60 | images = models.URLField(blank=True, null=True)
61 | lister = models.CharField(max_length=64, blank=True, null=True)
62 | bidder = models.CharField(max_length=64, blank=True, null=True)
63 | listingid = models.IntegerField()
64 | category = models.CharField(max_length=50, blank=True, null=True)
65 | finalbid = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
66 |
67 | def __str__(self):
68 | return f"{self.listingid}"
69 |
70 | class Comment(models.Model):
71 | user = models.CharField(max_length=64, blank=True, null=True)
72 | time = models.DateTimeField(default=now, editable=False)
73 | comment = models.CharField(max_length=30)
74 | listingid = models.IntegerField()
75 |
76 | def __str__(self):
77 | return f"{self.listingid}"
78 |
79 |
--------------------------------------------------------------------------------
/auctions/static/auctions/login.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Karla", sans-serif;
3 | min-height: 100vh; }
4 |
5 | .brand-wrapper {
6 | margin-bottom: 19px; }
7 | .brand-wrapper .logo {
8 | height: 37px; }
9 |
10 | .underlineHover:after {
11 | display: block;
12 | left: 0;
13 | bottom: -10px;
14 | width: 0;
15 | height: 2px;
16 | background-color: #56baed;
17 | content: "";
18 | transition: width 0.2s;
19 | }
20 |
21 | .underlineHover:hover {
22 | color: #0d0d0d;
23 | }
24 |
25 | .underlineHover:hover:after{
26 | width: 50%;
27 | }
28 |
29 | .login-card {
30 | border: 0;
31 | border-radius: 27.5px;
32 | box-shadow: 0 10px 30px 0 rgba(172, 168, 168, 0.43);
33 | overflow: hidden; }
34 | .login-card-img {
35 | border-radius: 0;
36 | position: absolute;
37 | width: 100%;
38 | height: 100%;
39 | -o-object-fit: cover;
40 | object-fit: cover; }
41 | .login-card .card-body {
42 | padding: 85px 60px 60px; }
43 | @media (max-width: 422px) {
44 | .login-card .card-body {
45 | padding: 35px 24px; } }
46 | .login-card-description {
47 | font-size: 25px;
48 | color: #000;
49 | font-weight: normal;
50 | margin-bottom: 23px; }
51 | .login-card form {
52 | max-width: 326px; }
53 | .login-card .form-control {
54 | border: 1px solid #d5dae2;
55 | padding: 15px 25px;
56 | margin-bottom: 20px;
57 | min-height: 45px;
58 | font-size: 13px;
59 | line-height: 15;
60 | font-weight: normal; }
61 | .login-card .form-control::-webkit-input-placeholder {
62 | color: #919aa3; }
63 | .login-card .form-control::-moz-placeholder {
64 | color: #919aa3; }
65 | .login-card .form-control:-ms-input-placeholder {
66 | color: #919aa3; }
67 | .login-card .form-control::-ms-input-placeholder {
68 | color: #919aa3; }
69 | .login-card .form-control::placeholder {
70 | color: #919aa3; }
71 | .login-card .login-btn {
72 | padding: 13px 20px 12px;
73 | background-color: #000;
74 | border-radius: 4px;
75 | font-size: 17px;
76 | font-weight: bold;
77 | line-height: 20px;
78 | color: #fff;
79 | margin-bottom: 24px; }
80 | .login-card .login-btn:hover {
81 | border: 1px solid #000;
82 | background-color: transparent;
83 | color: #000; }
84 | .login-card .forgot-password-link {
85 | font-size: 14px;
86 | color: #919aa3;
87 | margin-bottom: 12px; }
88 | .login-card-footer-text {
89 | font-size: 16px;
90 | color: #0d2366;
91 | margin-bottom: 60px; }
92 | @media (max-width: 767px) {
93 | .login-card-footer-text {
94 | margin-bottom: 24px; } }
95 | .login-card-footer-nav a {
96 | font-size: 14px;
97 | color: #919aa3; }
98 |
99 | /*# sourceMappingURL=login.css.map */
100 |
--------------------------------------------------------------------------------
/auctions/static/auctions/styles.css:
--------------------------------------------------------------------------------
1 | .mdl-grid {
2 | max-width: 600px;
3 | }
4 | .mdl-card__media {
5 | margin: 0;
6 | }
7 | .mdl-card__media > img {
8 | max-width: 100%;
9 | }
10 | .mdl-card__actions {
11 | display: flex;
12 | box-sizing:border-box;
13 | align-items: center;
14 | }
15 | .mdl-card__actions > .mdl-button--icon {
16 | margin-right: 3px;
17 | margin-left: 3px;
18 | }
19 |
20 | span.text {
21 | display: block;
22 | width: 100px;
23 | overflow: hidden;
24 | white-space: nowrap;
25 | text-overflow: ellipsis;
26 | }
27 | .comments-details button.btn.dropdown-toggle,
28 | .comments-details .total-comments {
29 | font-size: 18px;
30 | font-weight: 500;
31 | color: #5e5e5e;
32 | }
33 | .comments-details {
34 | padding: 15px 15px;
35 | }
36 | .comments .comments .dropdown,
37 | .comments .dropup {
38 | position: relative;
39 | }
40 | .comments button {
41 | background-color: transparent;
42 | border: none;
43 | }
44 | .comments .comment-box {
45 | width: 100%;
46 | float: left;
47 | height: 100%;
48 | background-color: #FAFAFA;
49 | padding: 10px 10px 10px;
50 | margin-bottom: 15px;
51 | border-radius: 5px;
52 | border: 1px solid #ddd;
53 | }
54 | .comments .add-comment {
55 | background-color: transparent;
56 | border: none;
57 | position: relative;
58 | margin-bottom: 50px;
59 | }
60 | .comments .commenter-pic {
61 | width: 50px;
62 | height: 50px;
63 | display: inline-block;
64 | border-radius: 100%;
65 | border: 2px solid #fff;
66 | overflow: hidden;
67 | background-color: #fff;
68 | }
69 | .comments .add-comment .commenter-name {
70 | width: 100%;
71 | padding-left: 75px;
72 | position: absolute;
73 | top: 20px;
74 | left: 0px;
75 | }
76 | .comments .add-comment input {
77 | border-top: 0px;
78 | border-bottom: 1px solid #ccc;
79 | border-left: 0px;
80 | border-right: 0px;
81 | outline: 0px;
82 | box-shadow: none;
83 | border-radius: 0;
84 | width: 100%;
85 | padding: 0;
86 | font-weight: normal;
87 | }
88 | .comments .add-comment input:focus {
89 | border-color: #03a9f4;
90 | border-width: 2px;
91 | }
92 | .comments .add-comment button[type=submit] {
93 | background-color: #03a9f4;
94 | color: #fff;
95 | margin-right: 0px;
96 | }
97 | .comments .add-comment button {
98 | background-color: #f5f5f5;
99 | margin: 10px 5px;
100 | font-size: 14px;
101 | text-transform: uppercase;
102 | float: right;
103 | }
104 | .comments .commenter-name .comment-time {
105 | font-weight: normal;
106 | margin-left: 8px;
107 | font-size: 15px;
108 | }
109 | .comments p.comment-txt {
110 | font-size: 15px;
111 | border-bottom: 1px solid #ddd;
112 | padding: 0px 0px 15px;
113 | }
114 | .comments .commenter-name {
115 | display: inline-block;
116 | position: relative;
117 | top: -20px;
118 | left: 10px;
119 | font-size: 16px;
120 | font-weight: bold;
121 | }
122 | .comments .comment-meta {
123 | font-size: 14px;
124 | color: #333;
125 | padding: 2px 5px 0px;
126 | line-height: 20px;
127 | float: right;
128 | }
129 | .comments .reply-box {
130 | display: none;
131 | }
132 | .comments .replied {
133 | background-color: #fff;
134 | width: 95%;
135 | float: right;
136 | margin-top: 15px;
137 | }
138 |
139 | /*======Responsive CSS=======*/
140 | @media (max-width: 767px){
141 | .comments .commenter-name {
142 | font-size: 13px;
143 | top: -5px;
144 | }
145 | .comments .commenter-pic {
146 | width: 40px;
147 | height: 40px;
148 | }
149 | .comments .commenter-name a{
150 | display: block;
151 | }
152 | .comments .commenter-name .comment-time{
153 | display: block;
154 | margin-left: 0px;
155 | }
156 | }
--------------------------------------------------------------------------------
/commerce/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for commerce project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.0.2.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.0/ref/settings/
11 | """
12 | import django_heroku
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/3.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'auctions',
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | 'widget_tweaks',
42 | 'crispy_forms'
43 | ]
44 |
45 | CRISPY_TEMPLATE_PACK = 'bootstrap4'
46 |
47 | MIDDLEWARE = [
48 | 'django.middleware.security.SecurityMiddleware',
49 | 'django.contrib.sessions.middleware.SessionMiddleware',
50 | 'django.middleware.common.CommonMiddleware',
51 | 'django.middleware.csrf.CsrfViewMiddleware',
52 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
53 | 'django.contrib.messages.middleware.MessageMiddleware',
54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
55 | ]
56 |
57 | ROOT_URLCONF = 'commerce.urls'
58 |
59 | TEMPLATES = [
60 | {
61 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
62 | 'DIRS': [],
63 | 'APP_DIRS': True,
64 | 'OPTIONS': {
65 | 'context_processors': [
66 | 'django.template.context_processors.debug',
67 | 'django.template.context_processors.request',
68 | 'django.contrib.auth.context_processors.auth',
69 | 'django.contrib.messages.context_processors.messages',
70 | ],
71 | },
72 | },
73 | ]
74 |
75 | WSGI_APPLICATION = 'commerce.wsgi.application'
76 |
77 |
78 | # Database
79 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
80 |
81 | DATABASES = {
82 | 'default': {
83 | 'ENGINE': 'django.db.backends.sqlite3',
84 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
85 | }
86 | }
87 |
88 | AUTH_USER_MODEL = 'auctions.User'
89 |
90 | # Password validation
91 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
92 |
93 | AUTH_PASSWORD_VALIDATORS = [
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
99 | },
100 | {
101 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
102 | },
103 | {
104 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
105 | },
106 | ]
107 |
108 |
109 | # Internationalization
110 | # https://docs.djangoproject.com/en/3.0/topics/i18n/
111 |
112 | LANGUAGE_CODE = 'en-us'
113 |
114 | TIME_ZONE = 'UTC'
115 |
116 | USE_I18N = True
117 |
118 | USE_L10N = True
119 |
120 | USE_TZ = True
121 |
122 |
123 | # Static files (CSS, JavaScript, Images)
124 | # https://docs.djangoproject.com/en/3.0/howto/static-files/
125 |
126 | PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
127 | STATIC_URL = '/static/'
128 | STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
129 |
130 |
131 | # Activate Django-Heroku.
132 | django_heroku.settings(locals())
133 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/layout.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 | {% block title %}Auctions{% endblock %}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
75 |
76 |
77 | {% block body %}
78 | {% endblock %}
79 |
80 |
81 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/watchlist.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
8 |
WATCHLIST
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | BIDS WON ({{ bidwincount }})
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | {% for object in closedbid %}
30 |
31 |
32 |
33 |
34 | {% if object.images %}
35 |
36 |
37 |
38 | {% else %}
39 |
40 |
41 |
42 | {% endif %}
43 |
48 |
49 |
50 |
51 | {% empty %}
52 |
You haven't won any bids yet. Start bidding now!
53 | {% endfor %}
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | WATCHLIST
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | {% for object in object %}
82 |
83 |
104 |
105 | {% empty %}
106 |
107 |
108 | No active listings on your watchlist.
109 |
110 | {% endfor %}
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | {% endblock %}
--------------------------------------------------------------------------------
/auctions/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1 on 2020-09-08 19:34
2 |
3 | import django.contrib.auth.models
4 | import django.contrib.auth.validators
5 | from django.db import migrations, models
6 | import django.utils.timezone
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | initial = True
12 |
13 | dependencies = [
14 | ('auth', '0012_alter_user_first_name_max_length'),
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='Bidding',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('bidder', models.CharField(blank=True, max_length=50, null=True)),
23 | ('bidprice', models.DecimalField(decimal_places=2, max_digits=15)),
24 | ('listingid', models.IntegerField()),
25 | ],
26 | ),
27 | migrations.CreateModel(
28 | name='Category',
29 | fields=[
30 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31 | ('name', models.CharField(max_length=20)),
32 | ],
33 | ),
34 | migrations.CreateModel(
35 | name='Closebid',
36 | fields=[
37 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
38 | ('productnames', models.CharField(max_length=20)),
39 | ('images', models.URLField(blank=True, null=True)),
40 | ('lister', models.CharField(blank=True, max_length=64, null=True)),
41 | ('bidder', models.CharField(blank=True, max_length=64, null=True)),
42 | ('listingid', models.IntegerField()),
43 | ('category', models.CharField(blank=True, max_length=50, null=True)),
44 | ('finalbid', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True)),
45 | ],
46 | ),
47 | migrations.CreateModel(
48 | name='Comment',
49 | fields=[
50 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
51 | ('user', models.CharField(blank=True, max_length=64, null=True)),
52 | ('time', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
53 | ('comment', models.CharField(max_length=30)),
54 | ('listingid', models.IntegerField()),
55 | ],
56 | ),
57 | migrations.CreateModel(
58 | name='Listing',
59 | fields=[
60 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
61 | ('productnames', models.CharField(max_length=20)),
62 | ('descriptions', models.TextField(max_length=500)),
63 | ('startingbids', models.DecimalField(decimal_places=2, max_digits=15)),
64 | ('images', models.URLField(blank=True, null=True)),
65 | ('category', models.CharField(blank=True, choices=[('FASHION', 'Fashion'), ('TOYS', 'Toys'), ('ELECTRONICS', 'Electronics'), ('HOME', 'Home'), ('BEAUTY & HEALTH', 'Beauty & Health'), ('SPORTS', 'Sports'), ('PETS', 'Pets'), ('BABY', 'Baby'), ('GROCERY', 'Grocery'), ('ENTERTAINMENT', 'Entertainment')], max_length=50, null=True)),
66 | ('lister', models.CharField(blank=True, max_length=50, null=True)),
67 | ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
68 | ],
69 | ),
70 | migrations.CreateModel(
71 | name='Watchlist',
72 | fields=[
73 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
74 | ('productnames', models.CharField(max_length=20)),
75 | ('images', models.URLField(blank=True, null=True)),
76 | ('finalbid', models.DecimalField(decimal_places=2, max_digits=15)),
77 | ('lister', models.CharField(blank=True, max_length=50, null=True)),
78 | ('watcher', models.CharField(blank=True, max_length=50, null=True)),
79 | ('listingid', models.IntegerField()),
80 | ],
81 | ),
82 | migrations.CreateModel(
83 | name='User',
84 | fields=[
85 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
86 | ('password', models.CharField(max_length=128, verbose_name='password')),
87 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
88 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
89 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
90 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
91 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
92 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
93 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
94 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
95 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
96 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
97 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
98 | ],
99 | options={
100 | 'verbose_name': 'user',
101 | 'verbose_name_plural': 'users',
102 | 'abstract': False,
103 | },
104 | managers=[
105 | ('objects', django.contrib.auth.models.UserManager()),
106 | ],
107 | ),
108 | ]
109 |
--------------------------------------------------------------------------------
/auctions/templates/auctions/listing.html:
--------------------------------------------------------------------------------
1 | {% extends "auctions/layout.html" %}
2 | {% load crispy_forms_tags %}
3 | {% block body %}
4 | {% load static %}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {% if object.images %}
16 |

17 | {% else %}
18 |

19 | {% endif %}
20 |
21 |
31 |
32 |
33 |
90 |
91 |
92 |
93 |
94 |
{{ object.productnames }}
95 |
96 |
97 |
98 |
99 |
100 | - Current Price:
101 | - ${{ object.startingbids }}
102 |
103 | - Number of Bids:
104 | {% if bidcount is 0 %} - No bids yet
105 | {% else %} - {{ bidcount }}
{% endif %}
106 |
107 | - Category:
108 | - {{ object.category }}
109 |
110 | - Listed by:
111 | - {{ object.lister }}
112 |
113 | - Date Posted:
114 | - {{ object.created }}
115 |
116 |
117 |
118 | {% if error %}
119 |
120 |
121 | {{error}}
122 |
123 | {% endif %}
124 | {% if success %}
125 |
126 |
127 | {{success}}
128 |
129 | {% endif %}
130 |
131 |
132 | {% if user.username %}
133 |
141 | {% else %}
142 |
143 |
145 |
146 | {% endif %}
147 |
148 |
149 |
150 | {% if user.username %}
151 | {% if added%}
152 |
154 | {% else %}
155 |
157 | {% endif %}
158 | {% endif %}
159 |
160 |
161 |
162 | {% if user.username %}
163 | {% if lister %}
164 |
166 | {% endif %}
167 | {% endif %}
168 |
169 |
170 |
171 |
172 |
173 | {% endblock %}
174 |
--------------------------------------------------------------------------------
/auctions/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import authenticate, login, logout
2 | from django.db import IntegrityError
3 | from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponseBadRequest
4 | from django.shortcuts import render, redirect
5 | from django.urls import reverse
6 | from django import forms
7 | from django.contrib.auth.decorators import login_required
8 | from django.contrib.sessions.models import Session
9 | from datetime import datetime
10 | from django.utils.timezone import now
11 |
12 |
13 | from .models import User, Listing, Bidding, Watchlist, Closebid, Comment, Category
14 |
15 | from .forms import ListingForm, BiddingForm, CommentForm
16 |
17 | def index(request):
18 | listing = Listing.objects.all()
19 | try:
20 | watch = Watchlist.objects.filter(watcher=request.user.username)
21 | watchcount=len(watch)
22 | except:
23 | watchcount=None
24 | return render(request, "auctions/index.html", {
25 | 'object': listing,
26 | 'watchcount': watchcount
27 | })
28 |
29 | @login_required
30 | def createlisting(request):
31 | creator = Listing.objects.all()
32 | form = ListingForm(request.POST or None)
33 | try:
34 | watch = Watchlist.objects.filter(watcher=request.user.username)
35 | watchcount = len(watch)
36 | except:
37 | watchcount = None
38 | if request.method == "POST":
39 | if form.is_valid():
40 | now = datetime.now() #save date created with current timezone
41 | fs = form.save(commit=False)
42 | fs.lister = request.user #save info not listed at forms.py
43 | fs.created = now
44 | fs.save()
45 | return HttpResponseRedirect(reverse('index'))
46 | else:
47 | return render(request, "auctions/create.html", {
48 | 'form': form,
49 | 'creator': creator,
50 | 'watchcount': watchcount
51 | })
52 |
53 | def listingpage(request,id):
54 | listing = Listing.objects.get(id=id)
55 | comment = Comment.objects.filter(listingid=id)
56 | try:
57 | cform = CommentForm(request.POST or None)
58 | bidform = BiddingForm(request.POST or None)
59 | except:
60 | return redirect('index')
61 | if request.user.username:
62 | try:
63 | if Watchlist.objects.get(watcher=request.user.username, listingid=id):
64 | added=True
65 | except:
66 | added = False
67 | try:
68 | watch = Watchlist.objects.filter(watcher=request.user.username)
69 | watchcount=len(watch)
70 | except:
71 | watchcount=None
72 | try:
73 | ccount = Comment.objects.filter(listingid=id)
74 | ccount = len(ccount)
75 | except:
76 | ccount = len(ccount)
77 | try:
78 |
79 | if listing.lister == request.user.username :
80 | lister = True
81 | else:
82 | lister = False
83 | except:
84 | return redirect('index')
85 | else:
86 | ccount = Comment.objects.filter(listingid=id)
87 | ccount = len(ccount)
88 | added = False
89 | lister = False
90 | watchcount = None
91 | try:
92 | bid = Bidding.objects.filter(listingid=id)
93 | bidcount = len(bid)
94 | listing = Listing.objects.get(id=id)
95 | except:
96 | bicount = None
97 | return render(request, "auctions/listing.html", {
98 | 'object': listing,
99 | 'added': added,
100 | 'bidform': bidform,
101 | "watchcount": watchcount,
102 | "error":request.COOKIES.get('error'),
103 | "success":request.COOKIES.get('success'),
104 | "bidcount": bidcount,
105 | "lister": lister,
106 | 'cform': cform,
107 | "comment": comment,
108 | "ccount": ccount
109 | })
110 |
111 | @login_required
112 | def addwatch(request, id):
113 | if request.user.username:
114 | listing = Listing.objects.get(id=id)
115 | watchers = Watchlist(watcher = request.user.username, listingid = id)
116 | watchers.lister = listing.lister
117 | watchers.finalbid = listing.startingbids
118 | watchers.productnames = listing.productnames
119 | watchers.images = listing.images
120 | watchers.save()
121 | return redirect('listingpage', id=id)
122 | else:
123 | return redirect('index')
124 |
125 | @login_required
126 | def removewatch(request,id):
127 | if request.user.username:
128 | try:
129 | Watchlist.objects.filter(listingid=id).delete()
130 | return redirect('listingpage', id=id)
131 | except:
132 | return redirect('listingpage', id=id)
133 | else:
134 | return redirect('index')
135 |
136 | @login_required
137 | def watchlist(request):
138 | try:
139 | watchlist = Watchlist.objects.filter(watcher=request.user.username)
140 | closebid = Closebid.objects.filter(bidder=request.user.username)
141 | watchcount = len(watchlist) #count how many rows in table Watchlist using len()
142 | except:
143 | watchcount = None
144 | try:
145 | bidwincount = Closebid.objects.filter(bidder = request.user.username)
146 | bidwincount = len(bidwincount)
147 | except:
148 | binwincoun = None
149 | try:
150 | if Watchlist.objects.get(listingid=listingid):
151 | closed = True
152 | else:
153 | closed = False
154 | except:
155 | closed = False
156 | return render(request, "auctions/watchlist.html", {
157 | 'object': watchlist,
158 | "watchcount": watchcount,
159 | "closedbid": closebid,
160 | "closed" : closed,
161 | "bidwincount": bidwincount
162 | })
163 |
164 | @login_required
165 | def bid(request, listingid):
166 | current = Listing.objects.get(id=listingid)
167 | current = current.startingbids
168 | bidform = BiddingForm(request.POST or None)
169 | if request.user.username:
170 | bid = float(request.POST.get("bidprice"))
171 | if bid > current:
172 | listing = Listing.objects.get(id=listingid)
173 | listing.startingbids = bid
174 | listing.save()
175 | try:
176 | if Bidding.objects.filter(id=listingid):
177 | bidrow = Bidding.objects.filter(id=listingid)
178 | bidrow.delete()
179 | fs = bidform.save(commit=False)
180 | fs.bidder = request.user.username
181 | fs.listingid = listingid
182 | fs.save()
183 | except:
184 | fs = bidform.save(commit=False)
185 | fs.bidder = request.user
186 | fs.listingid = listingid
187 | fs.save()
188 | response = redirect('listingpage', id=listingid)
189 | response.set_cookie('success','Successful Bid! Your bid is currently the highest bid.', max_age=1)
190 | return response
191 | else:
192 | response = redirect('listingpage', id=listingid)
193 | response.set_cookie('error','Your bid must be higher than the current price!', max_age=1)
194 | return response
195 | else:
196 | return redirect('index')
197 |
198 | @login_required
199 | def closebid(request, listingid):
200 | if request.user.username:
201 | try:
202 | listing = Listing.objects.get(id=listingid)
203 | except:
204 | return redirect('index')
205 | closebid = Closebid()
206 | name = listing.productnames
207 | closebid.lister = listing.lister
208 | closebid.listingid = listingid
209 | closebid.productnames = listing.productnames
210 | closebid.images = listing.images
211 | closebid.category = listing.category
212 | try:
213 | bid = Bidding.objects.get(listingid=listingid,bidprice=listing.startingbids)
214 | closebid.bidder = bid.bidder
215 | closebid.finalbid = bid.bidprice
216 | closebid.save()
217 | bid.delete()
218 | except:
219 | closebid.bidder = listing.lister
220 | closebid.finalbid = listing.startingbids
221 | closebid.save()
222 | try:
223 | if Watchlist.objects.filter(listingid=listingid):
224 | watch = Watchlist.objects.filter(listingid=listingid)
225 | watch.delete()
226 | else:
227 | pass
228 | except:
229 | pass
230 | try:
231 | comment = Comment.objects.filter(listingid=listingid)
232 | comment.delete()
233 | except:
234 | pass
235 | try:
236 | bid = Bid.objects.filter(listingid=listingid)
237 | bid.delete()
238 | except:
239 | pass
240 | try:
241 | closebidlist = Closebid.objects.get(listingid=listingid)
242 | except:
243 | closebid.lister = listing.lister
244 | closebid.bidder = listing.lister
245 | closebid.listingid = listingid
246 | closebid.finalbid = listing.startingbids
247 | closebid.productnames = listing.productnames
248 | closebid.images = listing.images
249 | closebid.category = listing.category
250 | closebid.save()
251 | closebidlist = Closebid.objects.get(listingid=listingid)
252 | listing.delete()
253 | try:
254 | watch = Watchlist.objects.filter(watcher=request.user.username)
255 | watchcount=len(watch)
256 | except:
257 | watchcount = None
258 | return render(request,"auctions/winner.html",{
259 | "closebidlist": closebidlist,
260 | "name": name,
261 | "watchcount":watchcount
262 | })
263 | else:
264 | return redirect('index')
265 |
266 | @login_required
267 | def closed(request, listingid):
268 | closed = Closebid.objects.get(listingid=listingid)
269 | try:
270 | watch = Watchlist.objects.filter(watcher=request.user.username)
271 | watchcount = len(watch)
272 | except:
273 | watchcount = None
274 | return render(request, "auctions/closed.html", {
275 | "object": closed,
276 | "watchcount": watchcount
277 | })
278 |
279 | @login_required
280 | def comment(request, listingid):
281 | if request.method == "POST":
282 | comment = Comment.objects.all()
283 | cform = CommentForm(request.POST or None)
284 | if cform.is_valid():
285 | now = datetime.now()
286 | fs = cform.save(commit=False)
287 | fs.listingid = listingid
288 | fs.user = request.user.username
289 | fs.time = now
290 | fs.save()
291 | return redirect('listingpage', id=listingid)
292 | else:
293 | return redirect('index')
294 |
295 | def category(request):
296 | category = Category.objects.all()
297 | closedbid = Closebid.objects.all()
298 | try:
299 | if Watchlist.objects.get(listingid=listingid):
300 | closed = True
301 | else:
302 | closed = False
303 | except:
304 | closed = False
305 | try:
306 | watch = Watchlist.objects.filter(watcher=request.user.username)
307 | watchcount = len(watch)
308 | except:
309 | watchcount = None
310 | return render(request, "auctions/categories.html", {
311 | "object": category,
312 | "watchcount": watchcount,
313 | "closed": closed,
314 | "closedbid": closedbid
315 | })
316 |
317 | def categorylistings(request, cats):
318 | category_posts = Listing.objects.filter(category=cats)
319 | try:
320 | watch = Watchlist.objects.filter(watcher=request.user.username)
321 | watchcount = len(watch)
322 | except:
323 | watchcount = None
324 | return render(request, 'auctions/categorylistings.html', {
325 | 'cats': cats,
326 | 'category_posts': category_posts,
327 | 'watchcount': watchcount
328 | })
329 |
330 | def allclosed(request):
331 | closedlist = Closebid.objects.all()
332 | try:
333 | watch = Watchlist.objects.filter(watcher=request.user.username)
334 | watchcount = len(watch)
335 | except:
336 | watchcount = None
337 | return render(request, 'auctions/allclosed.html', {
338 | 'closedlist': closedlist,
339 | 'watchcount': watchcount
340 | })
341 |
342 | def login_view(request):
343 | if request.method == "POST":
344 | # Attempt to sign user in
345 | username = request.POST["username"]
346 | password = request.POST["password"]
347 | user = authenticate(request, username=username, password=password)
348 |
349 | # Check if authentication successful
350 | if user is not None:
351 | login(request, user)
352 | return HttpResponseRedirect(reverse("index"))
353 | else:
354 | return render(request, "auctions/login.html", {
355 | "message": "Invalid username and/or password."
356 | })
357 | else:
358 | return render(request, "auctions/login.html")
359 |
360 |
361 | def logout_view(request):
362 | logout(request)
363 | return HttpResponseRedirect(reverse("index"))
364 |
365 |
366 | def register(request):
367 | if request.method == "POST":
368 | username = request.POST["username"]
369 | email = request.POST["email"]
370 |
371 | # Ensure password matches confirmation
372 | password = request.POST["password"]
373 | confirmation = request.POST["confirmation"]
374 | if password != confirmation:
375 | return render(request, "auctions/register.html", {
376 | "message": "Passwords must match."
377 | })
378 |
379 | # Attempt to create new user
380 | try:
381 | user = User.objects.create_user(username, email, password)
382 | user.save()
383 | except IntegrityError:
384 | return render(request, "auctions/register.html", {
385 | "message": "Username already taken."
386 | })
387 | login(request, user)
388 | return HttpResponseRedirect(reverse("index"))
389 | else:
390 | return render(request, "auctions/register.html")
391 |
--------------------------------------------------------------------------------