From 574a4e76ccec7deb440e8e8a47d7a9e35cadeb8c Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Sat, 30 Jan 2021 21:49:26 -0500
Subject: [PATCH 1/5] feat(backend): added gunicorn to deps

---
 backend/Pipfile      |  4 +++
 backend/Pipfile.lock | 71 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/backend/Pipfile b/backend/Pipfile
index f732aeb..c562d01 100644
--- a/backend/Pipfile
+++ b/backend/Pipfile
@@ -11,6 +11,10 @@ djangorestframework = "*"
 python-dotenv = "*"
 psycopg2 = "*"
 robin-stocks = "*"
+django-cors-headers = "*"
+pillow = "*"
+djangorestframework-jwt = "*"
+gunicorn = "*"
 
 [requires]
 python_version = "3.8"
diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock
index b2a439b..20ac214 100644
--- a/backend/Pipfile.lock
+++ b/backend/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "512cec129202578daefb819a6bf109831ef31164fad71ade999b9699e8c59402"
+            "sha256": "408f67696e25dce5ccaf2d231898d55d2e9de2758ecd96631cfe7532ca9cf8b9"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -47,6 +47,14 @@
             "index": "pypi",
             "version": "==3.1.5"
         },
+        "django-cors-headers": {
+            "hashes": [
+                "sha256:1ac2b1213de75a251e2ba04448da15f99bcfcbe164288ae6b5ff929dc49b372f",
+                "sha256:96069c4aaacace786a34ee7894ff680780ec2644e4268b31181044410fecd12e"
+            ],
+            "index": "pypi",
+            "version": "==3.7.0"
+        },
         "djangorestframework": {
             "hashes": [
                 "sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7",
@@ -55,6 +63,22 @@
             "index": "pypi",
             "version": "==3.12.2"
         },
+        "djangorestframework-jwt": {
+            "hashes": [
+                "sha256:5efe33032f3a4518a300dc51a51c92145ad95fb6f4b272e5aa24701db67936a7",
+                "sha256:ab15dfbbe535eede8e2e53adaf52ef0cf018ee27dbfad10cbc4cbec2ab63d38c"
+            ],
+            "index": "pypi",
+            "version": "==1.11.0"
+        },
+        "gunicorn": {
+            "hashes": [
+                "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
+                "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"
+            ],
+            "index": "pypi",
+            "version": "==20.0.4"
+        },
         "idna": {
             "hashes": [
                 "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
@@ -63,6 +87,44 @@
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
             "version": "==2.10"
         },
+        "pillow": {
+            "hashes": [
+                "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6",
+                "sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded",
+                "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865",
+                "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174",
+                "sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032",
+                "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a",
+                "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e",
+                "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378",
+                "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17",
+                "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c",
+                "sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913",
+                "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7",
+                "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0",
+                "sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820",
+                "sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba",
+                "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2",
+                "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b",
+                "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9",
+                "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234",
+                "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d",
+                "sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5",
+                "sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206",
+                "sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9",
+                "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8",
+                "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59",
+                "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d",
+                "sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7",
+                "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a",
+                "sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0",
+                "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b",
+                "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d",
+                "sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae"
+            ],
+            "index": "pypi",
+            "version": "==8.1.0"
+        },
         "psycopg2": {
             "hashes": [
                 "sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301",
@@ -84,6 +146,13 @@
             "index": "pypi",
             "version": "==2.8.6"
         },
+        "pyjwt": {
+            "hashes": [
+                "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e",
+                "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"
+            ],
+            "version": "==1.7.1"
+        },
         "pyotp": {
             "hashes": [
                 "sha256:2a54d393aff3a244b566d78d597c9cb42e91b3b12f3169cec89d9dfff1c9c5bc",

From e4e1a605c84a50b5e7b94c0db43699034965600e Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Sat, 30 Jan 2021 23:24:24 -0500
Subject: [PATCH 2/5] feat(backend): finished backend

---
 backend/api/migrations/0001_initial.py        | 59 +++++++++++++++++++
 .../api/migrations/0002_auto_20210130_2301.py | 43 ++++++++++++++
 backend/api/models.py                         | 38 ++++++++----
 backend/api/serializers.py                    | 51 +++++++++++++++-
 backend/api/urls.py                           | 12 +++-
 backend/api/views.py                          | 52 +++++++++++++++-
 backend/config/settings.py                    |  3 +
 backend/config/urls.py                        |  9 ++-
 8 files changed, 247 insertions(+), 20 deletions(-)
 create mode 100644 backend/api/migrations/0001_initial.py
 create mode 100644 backend/api/migrations/0002_auto_20210130_2301.py

diff --git a/backend/api/migrations/0001_initial.py b/backend/api/migrations/0001_initial.py
new file mode 100644
index 0000000..634aca6
--- /dev/null
+++ b/backend/api/migrations/0001_initial.py
@@ -0,0 +1,59 @@
+# Generated by Django 3.1.5 on 2021-01-30 20:48
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Charity',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('ein', models.CharField(blank=True, max_length=50, null=True)),
+                ('name', models.CharField(blank=True, max_length=50, null=True)),
+                ('sub_name', models.CharField(blank=True, max_length=50, null=True)),
+                ('city', models.CharField(blank=True, max_length=20, null=True)),
+                ('state', models.CharField(blank=True, max_length=2, null=True)),
+            ],
+            options={
+                'verbose_name_plural': 'Charities',
+            },
+        ),
+        migrations.CreateModel(
+            name='Profile',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('nickname', models.CharField(blank=True, max_length=20, null=True)),
+                ('profile_pic', models.ImageField(default='default.jpg', upload_to='profile_pics')),
+                ('percentage', models.DecimalField(decimal_places=2, max_digits=3)),
+                ('charity', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='api.charity')),
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'verbose_name_plural': 'Profiles',
+            },
+        ),
+        migrations.CreateModel(
+            name='Stock',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('ticker', models.CharField(blank=True, max_length=5, null=True)),
+                ('buy_price', models.DecimalField(decimal_places=2, max_digits=9)),
+                ('quantity', models.DecimalField(decimal_places=2, max_digits=9)),
+                ('uuid', models.UUIDField(editable=False, unique=True)),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stock', to='api.profile')),
+            ],
+            options={
+                'verbose_name_plural': 'Stocks',
+            },
+        ),
+    ]
diff --git a/backend/api/migrations/0002_auto_20210130_2301.py b/backend/api/migrations/0002_auto_20210130_2301.py
new file mode 100644
index 0000000..a96f7a4
--- /dev/null
+++ b/backend/api/migrations/0002_auto_20210130_2301.py
@@ -0,0 +1,43 @@
+# Generated by Django 3.1.5 on 2021-01-30 23:01
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='charity',
+            name='id',
+        ),
+        migrations.RemoveField(
+            model_name='stock',
+            name='id',
+        ),
+        migrations.AlterField(
+            model_name='charity',
+            name='ein',
+            field=models.CharField(max_length=50, primary_key=True, serialize=False),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='profile',
+            name='percentage',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=3, null=True),
+        ),
+        migrations.AlterField(
+            model_name='stock',
+            name='user',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stocks', to='api.profile'),
+        ),
+        migrations.AlterField(
+            model_name='stock',
+            name='uuid',
+            field=models.UUIDField(primary_key=True, serialize=False, unique=True),
+        ),
+    ]
diff --git a/backend/api/models.py b/backend/api/models.py
index 49b02d5..d4c706f 100644
--- a/backend/api/models.py
+++ b/backend/api/models.py
@@ -1,13 +1,29 @@
+from django.contrib.auth.models import User
 from django.db import models
 
+from PIL import Image
+
 # Create your models here.
 
+class Charity (models.Model):
+    ein = models.CharField(primary_key=True, max_length=50)
+    name = models.CharField(max_length=50, blank=True, null=True)
+    sub_name = models.CharField(max_length=50, blank=True, null=True)
+    city = models.CharField(max_length=20, blank=True, null=True)
+    state = models.CharField(max_length=2, blank=True, null=True)
+
+    class Meta:
+        verbose_name_plural = "Charities"
+
+    def __str__(self):
+        return self.name
+
 class Profile (models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE)
+    charity = models.OneToOneField(Charity, blank=True, null=True, on_delete=models.DO_NOTHING)
     nickname = models.CharField(max_length=20, blank=True, null=True)
     profile_pic = models.ImageField(default='default.jpg', upload_to='profile_pics')
-    charity = models.OneToOneField(Charity, blank=True, null=True)
-    percentage = models.DecimalField(max_digits=3, decimal_places=2)
+    percentage = models.DecimalField(max_digits=3, decimal_places=2, blank=True, null=True)
 
     def __str__(self):
         return f'{self.user.username}\'s profile'
@@ -22,22 +38,18 @@ class Profile (models.Model):
             img.thumbnail(size)
             img.save(self.profile_pic.path)
 
-class Charity (models.Model):
-    ein = models.CharField(max_length=50, blank=True, null=True)
-    name = models.CharField(max_length=50, blank=True, null=True)
-    sub_name = models.CharField(max_length=50, blank=True, null=True)
-    city = models.CharField(max_length=20, blank=True, null=True)
-    state = models.CharField(max_length=2, blank=True, null=True)
-
-    def __str__(self):
-        return self.name
+    class Meta:
+        verbose_name_plural = "Profiles"
 
 class Stock (models.Model):
-    user = models.ForeignKey(Profile, related_name='stock', on_delete=models.CASCADE)
+    user = models.ForeignKey(Profile, related_name='stocks', on_delete=models.CASCADE)
     ticker = models.CharField(max_length=5, blank=True, null=True)
     buy_price = models.DecimalField(max_digits=9, decimal_places=2)
     quantity = models.DecimalField(max_digits=9, decimal_places=2)
-    uuid = models.UUIDField(editable=False, unique=True)
+    uuid = models.UUIDField(primary_key=True, unique=True)
+
+    class Meta:
+        verbose_name_plural = "Stocks"
 
     def __str__(self):
         return f'{self.user.user.username}\'s Stock: {self.ticker} @ {self.buy_price}'
diff --git a/backend/api/serializers.py b/backend/api/serializers.py
index 82197b8..a59e9e4 100644
--- a/backend/api/serializers.py
+++ b/backend/api/serializers.py
@@ -1,7 +1,56 @@
 from rest_framework import serializers
+from django.contrib.auth.models import User
 from . import models
 
 class UserSerializer(serializers.ModelSerializer):
     class Meta:
         model = User
-        fields = ('username', 'email', 'first_name', 'last_name')
\ No newline at end of file
+        fields = ('username', 'email', 'first_name', 'last_name')
+
+class UserCreateSerializer(serializers.ModelSerializer):
+    password = serializers.CharField(write_only=True)
+
+    def create(self, validated_data):
+        print("I WAS CALLED!")
+        user = User.objects.create(
+            username = validated_data['username'],
+            email = validated_data['email'],
+            first_name = validated_data['first_name'],
+            last_name = validated_data['last_name']
+        )
+
+        user.set_password(validated_data['password'])
+        user.save()
+
+        profile = models.Profile.objects.create(user=user)
+        profile.save()
+
+        return user
+
+    class Meta:
+        model = User
+        fields = ('username', 'password', 'email', 'first_name', 'last_name')
+
+class StockSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.Stock
+        fields = ('ticker', 'buy_price', 'quantity', 'uuid')
+
+class StockCreateSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.Stock
+        fields = ('user', 'ticker', 'buy_price', 'quantity', 'uuid')
+
+class CharitySerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.Charity
+        fields = ('ein', 'name', 'sub_name', 'city', 'state')
+
+class ProfileSerializer(serializers.ModelSerializer):
+    user = UserSerializer()
+    charity = CharitySerializer()
+    stocks = StockSerializer(many=True)
+    
+    class Meta:
+        model = models.Profile
+        fields = ('user', 'charity', 'nickname', 'profile_pic', 'percentage', 'stocks')
diff --git a/backend/api/urls.py b/backend/api/urls.py
index d9d8136..77177e7 100644
--- a/backend/api/urls.py
+++ b/backend/api/urls.py
@@ -1,8 +1,16 @@
 from rest_framework_jwt.views import obtain_jwt_token
 
-from django.urls import path
 from . import views
 
+from django.urls import path, include
+from rest_framework.routers import DefaultRouter
+
 urlpatterns = [
-    path('token/', obtain_jwt_token)
+    path('charity/<int:pk>', views.CharityViewSet.as_view({'get': 'retrieve'})),
+    path('charity', views.CharityViewSet.as_view({'get': 'list', 'post': 'create'})),
+    path('stock/<uuid:pk>', views.StockViewSet.as_view({'get': 'retrieve'})),
+    path('stock', views.StockViewSet.as_view({'get': 'list', 'post': 'create'})),
+    path('profile/create', views.UserProfileCreate.as_view()),
+    path('profile', views.UserProfileDetail.as_view()),
+    path('token', obtain_jwt_token)
 ]
diff --git a/backend/api/views.py b/backend/api/views.py
index 91ea44a..35896bc 100644
--- a/backend/api/views.py
+++ b/backend/api/views.py
@@ -1,3 +1,51 @@
-from django.shortcuts import render
+from django.shortcuts import render, get_object_or_404
+from django.http import QueryDict
 
-# Create your views here.
+from rest_framework import status, permissions
+from rest_framework.views import APIView
+from rest_framework.viewsets import ModelViewSet
+from rest_framework.generics import CreateAPIView
+from rest_framework.response import Response
+
+from .models import *
+from .serializers import *
+
+class CharityViewSet(ModelViewSet):
+    queryset = models.Charity.objects.all()
+    serializer_class = CharitySerializer
+
+class StockViewSet(ModelViewSet):
+    queryset = ''
+    serializer_class = StockSerializer
+
+    def list(self, request, *args, **kwargs):
+        queryset = request.user.profile.stocks.all()
+        serializer = StockSerializer(queryset, many=True)
+        return Response(serializer.data, status=status.HTTP_200_OK)
+
+    def retrieve(self, request, pk=None, *args, **kwargs):
+        queryset = request.user.profile.stocks.filter(uuid=pk)
+        if queryset.count() != 1:
+            return Response({"message": "Stock not found."}, status=status.HTTP_404_NOT_FOUND)
+        serializer = StockSerializer(queryset.first())
+        return Response(serializer.data, status=status.HTTP_200_OK)
+    
+
+    def create(self, request, *args, **kwargs):
+        data = QueryDict.copy(request.data)
+        data.update({'user': request.user})
+        serializer = StockCreateSerializer(data=request.data)
+        serializer.is_valid(raise_exception=True)
+        serializer.save()
+        return Response(serializer.data, status=status.HTTP_200_OK)
+
+class UserProfileDetail(APIView):
+    def get(self, request, format=None):
+        profile = request.user.profile
+        serializer = ProfileSerializer(profile)
+        return Response(serializer.data, status=status.HTTP_200_OK)
+
+class UserProfileCreate(CreateAPIView):
+    model = User
+    permission_classes = [permissions.AllowAny]
+    serializer_class = UserCreateSerializer
\ No newline at end of file
diff --git a/backend/config/settings.py b/backend/config/settings.py
index 1bd9a1b..bdfc8ec 100644
--- a/backend/config/settings.py
+++ b/backend/config/settings.py
@@ -153,3 +153,6 @@ USE_TZ = True
 # https://docs.djangoproject.com/en/3.1/howto/static-files/
 
 STATIC_URL = '/static/'
+
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
+MEDIA_URL = '/media/'
\ No newline at end of file
diff --git a/backend/config/urls.py b/backend/config/urls.py
index e36fd86..672ec29 100644
--- a/backend/config/urls.py
+++ b/backend/config/urls.py
@@ -13,10 +13,15 @@ Including another URLconf
     1. Import the include() function: from django.urls import include, path
     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
 """
+from django.conf import settings
+from django.conf.urls.static import static
 from django.contrib import admin
-from django.urls import path
+from django.urls import path, include
 
 urlpatterns = [
-    path('', include('api.urls'))
+    path('api/', include('api.urls')),
     path('admin/', admin.site.urls),
 ]
+
+if settings.DEBUG:
+    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file

From 1dc45c62ee2b51ce57b4092bc33d8a66c5b1ec3e Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Sat, 30 Jan 2021 23:43:00 -0500
Subject: [PATCH 3/5] fix(backend): changed debug from string to bool

---
 backend/config/settings.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/backend/config/settings.py b/backend/config/settings.py
index bdfc8ec..66a5893 100644
--- a/backend/config/settings.py
+++ b/backend/config/settings.py
@@ -27,12 +27,12 @@ BASE_DIR = Path(__file__).resolve().parent.parent
 SECRET_KEY = os.getenv("SECRET_KEY")
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = os.getenv("DEBUG")
+DEBUG = os.getenv("DEBUG") == 'True'
 
 if DEBUG:
     ALLOWED_HOSTS = ["*"]
 else:
-    ALLOWED_HOSTS = ["reinvest.online"]
+    ALLOWED_HOSTS = ["api.reinvest.space"]
 
 # Application definition
 
@@ -155,4 +155,4 @@ USE_TZ = True
 STATIC_URL = '/static/'
 
 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
-MEDIA_URL = '/media/'
\ No newline at end of file
+MEDIA_URL = '/media/'

From 94f06aa1a3bedffddb28eaf067203fc46a8c680d Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Sat, 30 Jan 2021 23:49:12 -0500
Subject: [PATCH 4/5] feat(backend): added whitenoise for backend

---
 backend/Pipfile      |  1 +
 backend/Pipfile.lock | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/backend/Pipfile b/backend/Pipfile
index c562d01..e2e96ad 100644
--- a/backend/Pipfile
+++ b/backend/Pipfile
@@ -15,6 +15,7 @@ django-cors-headers = "*"
 pillow = "*"
 djangorestframework-jwt = "*"
 gunicorn = "*"
+whitenoise = "*"
 
 [requires]
 python_version = "3.8"
diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock
index 20ac214..9af40f7 100644
--- a/backend/Pipfile.lock
+++ b/backend/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "408f67696e25dce5ccaf2d231898d55d2e9de2758ecd96631cfe7532ca9cf8b9"
+            "sha256": "cd366320b75b1430efc97f93ca86418b4431990547ddea8eeb3a7f7f35343bc6"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -206,6 +206,14 @@
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
             "version": "==1.26.3"
+        },
+        "whitenoise": {
+            "hashes": [
+                "sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7",
+                "sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d"
+            ],
+            "index": "pypi",
+            "version": "==5.2.0"
         }
     },
     "develop": {}

From ea8f4c74db4b950b06f4874ef8881ab3499cee60 Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Sat, 30 Jan 2021 23:51:25 -0500
Subject: [PATCH 5/5] fix(backend): added STATIC_ROOT to settings.py

---
 backend/config/settings.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/backend/config/settings.py b/backend/config/settings.py
index 66a5893..1549f0e 100644
--- a/backend/config/settings.py
+++ b/backend/config/settings.py
@@ -54,6 +54,7 @@ MIDDLEWARE = [
     'corsheaders.middleware.CorsMiddleware',
 
     'django.middleware.security.SecurityMiddleware',
+    'whitenoise.middleware.WhiteNoiseMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
@@ -62,6 +63,8 @@ MIDDLEWARE = [
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 ]
 
+STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+
 REST_FRAMEWORK = {
     'DEFAULT_PERMISSION_CLASSES': (
         'rest_framework.permissions.IsAuthenticated',
@@ -152,7 +155,7 @@ USE_TZ = True
 # Static files (CSS, JavaScript, Images)
 # https://docs.djangoproject.com/en/3.1/howto/static-files/
 
-STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
 
 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
 MEDIA_URL = '/media/'