feat(backend): added database models and API views

This commit is contained in:
Rushil Umaretiya 2022-04-16 21:04:25 -04:00
parent 495cbfc407
commit acba7b111d
17 changed files with 434 additions and 10 deletions

16
server/Pipfile Normal file
View File

@ -0,0 +1,16 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
django = "*"
gunicorn = "*"
python-dotenv = "*"
djangorestframework = "*"
django-cors-headers = "*"
[dev-packages]
[requires]
python_version = "3.9"

92
server/Pipfile.lock generated Normal file
View File

@ -0,0 +1,92 @@
{
"_meta": {
"hash": {
"sha256": "6b09e5def16da359280b38cfa9690ef7fb07897b5befd3c0f5b16de35d664690"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"asgiref": {
"hashes": [
"sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0",
"sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"
],
"markers": "python_version >= '3.7'",
"version": "==3.5.0"
},
"django": {
"hashes": [
"sha256:07c8638e7a7f548dc0acaaa7825d84b7bd42b10e8d22268b3d572946f1e9b687",
"sha256:4e8177858524417563cc0430f29ea249946d831eacb0068a1455686587df40b5"
],
"index": "pypi",
"version": "==4.0.4"
},
"django-cors-headers": {
"hashes": [
"sha256:a22be2befd4069c4fc174f11cf067351df5c061a3a5f94a01650b4e928b0372b",
"sha256:eb98389bf7a2afc5d374806af4a9149697e3a6955b5a2dc2bf049f7d33647456"
],
"index": "pypi",
"version": "==3.11.0"
},
"djangorestframework": {
"hashes": [
"sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee",
"sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa"
],
"index": "pypi",
"version": "==3.13.1"
},
"gunicorn": {
"hashes": [
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
"sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
],
"index": "pypi",
"version": "==20.1.0"
},
"python-dotenv": {
"hashes": [
"sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f",
"sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"
],
"index": "pypi",
"version": "==0.20.0"
},
"pytz": {
"hashes": [
"sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7",
"sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"
],
"version": "==2022.1"
},
"sqlparse": {
"hashes": [
"sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
"sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
],
"markers": "python_version >= '3.5'",
"version": "==0.4.2"
},
"tzdata": {
"hashes": [
"sha256:238e70234214138ed7b4e8a0fab0e5e13872edab3be586ab8198c407620e2ab9",
"sha256:8b536a8ec63dc0751342b3984193a3118f8fca2afe25752bb9b7fffd398552d3"
],
"markers": "sys_platform == 'win32'",
"version": "==2022.1"
}
},
"develop": {}
}

0
server/api/__init__.py Normal file
View File

9
server/api/admin.py Normal file
View File

@ -0,0 +1,9 @@
from django.contrib import admin
from . import models
# Register your models here.
admin.site.register(models.Consumer)
admin.site.register(models.Foundation)
admin.site.register(models.Wallet)
admin.site.register(models.FoundationOrder)

6
server/api/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'

View File

@ -0,0 +1,67 @@
# Generated by Django 4.0.4 on 2022-04-16 20:35
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='Consumer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('access_token', models.CharField(max_length=100)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name_plural': 'Consumers',
},
),
migrations.CreateModel(
name='Foundation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField()),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name_plural': 'Foundations',
},
),
migrations.CreateModel(
name='Wallet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('address', models.CharField(max_length=100)),
],
options={
'verbose_name_plural': 'Wallets',
},
),
migrations.CreateModel(
name='FoundationOrder',
fields=[
('price', models.DecimalField(decimal_places=2, max_digits=9)),
('uuid', models.UUIDField(primary_key=True, serialize=False, unique=True)),
('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='foundation_orders', to='api.consumer')),
('foundation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='foundation_orders', to='api.foundation')),
],
options={
'verbose_name_plural': 'Foundation Orders',
},
),
migrations.AddField(
model_name='foundation',
name='wallet',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='api.wallet'),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0.4 on 2022-04-16 20:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='consumer',
name='wallet',
field=models.OneToOneField(default=None, on_delete=django.db.models.deletion.CASCADE, to='api.wallet'),
preserve_default=False,
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.0.4 on 2022-04-16 21:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0002_consumer_wallet'),
]
operations = [
migrations.AlterField(
model_name='consumer',
name='wallet',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='api.wallet'),
),
]

View File

50
server/api/models.py Normal file
View File

@ -0,0 +1,50 @@
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Wallet (models.Model):
address = models.CharField(max_length=100)
def __str__(self):
return self.address[0:4]
# return f'{self.consumer.user.username}\'s wallet'
class Meta:
verbose_name_plural = "Wallets"
class Consumer (models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
wallet = models.OneToOneField(Wallet, null=True, blank=True, on_delete=models.CASCADE)
access_token = models.CharField(max_length=100)
def __str__(self):
return f'{self.user.username}\'s profile'
class Meta:
verbose_name_plural = "Consumers"
class Foundation (models.Model):
wallet = models.OneToOneField(Wallet, on_delete=models.CASCADE)
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.TextField()
def __str__(self):
return f'{self.user.username}\'s foundation'
class Meta:
verbose_name_plural = "Foundations"
class FoundationOrder (models.Model):
consumer = models.ForeignKey(Consumer, related_name='foundation_orders', on_delete=models.CASCADE)
foundation = models.ForeignKey(Foundation, related_name='foundation_orders', on_delete=models.CASCADE)
price = models.DecimalField(max_digits=9, decimal_places=2)
uuid = models.UUIDField(primary_key=True, unique=True)
class Meta:
verbose_name_plural = "Foundation Orders"
def __str__(self):
return f'{self.consumer.user.username}\'s Order to {self.foundation.name} for {self.price}'

62
server/api/serializers.py Normal file
View File

@ -0,0 +1,62 @@
from operator import mod
from django.contrib.auth.models import User
from rest_framework import serializers
from . import models
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name')
class ConsumerCreateSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
user.set_password(validated_data['password'])
user.save()
consumer = models.Consumer.objects.create(user=user)
consumer.save()
return user
class Meta:
model = models.User
fields = ('username', 'password', 'email', 'first_name', 'last_name')
class FoundationSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = models.Foundation
fields = ('user', 'name', 'description')
class ConsumerOrderSerializer(serializers.ModelSerializer):
foundation = FoundationSerializer()
class Meta:
model = models.FoundationOrder
fields = ('price', 'uuid', 'foundation')
class ConsumerSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = models.Consumer
fields = ('user', 'access_token', 'foundation_orders')
class FoundationOrderSerializer(serializers.ModelSerializer):
consumer = ConsumerSerializer()
class Meta:
model = models.FoundationOrder
fields = ('price', 'uuid', 'consumer')
class FoundationOrderCreateSerializer(serializers.ModelSerializer):
class Meta:
model = models.FoundationOrder
fields = ('price', 'uuid', 'foundation')

3
server/api/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

10
server/api/urls.py Normal file
View File

@ -0,0 +1,10 @@
from django.urls import path
from . import views
urlpatterns = [
path('profile/create', views.ConsumerCreate.as_view()),
path('profile/', views.ConsumerDetail.as_view()),
path('foundation/', views.FoundationViewSet.as_view({'get': 'list', 'post': 'create'})),
path('foundation/<int:pk>/', views.FoundationViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

38
server/api/views.py Normal file
View File

@ -0,0 +1,38 @@
from django.shortcuts import render
from .models import *
from .serializers import *
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
# Create your views here.
class FoundationViewSet(ModelViewSet):
queryset = models.Foundation.objects.all()
serializer_class = FoundationSerializer
class ConsumerOrderViewSet(ModelViewSet):
queryset = ''
serializerClass = ConsumerOrderSerializer
def list(self, request, *args, **kwargs):
queryset = request.user.consumer.foundation_orders.all()
serializer = ConsumerOrderSerializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class ConsumerCreate(CreateAPIView):
model = User
permission_classes = [permissions.AllowAny]
serializer_class = ConsumerCreateSerializer
class ConsumerDetail(APIView):
def get(self, request, format=None):
profile = request.user.consumer
serializer = ConsumerSerializer(profile)
return Response(serializer.data, status=status.HTTP_200_OK)

View File

@ -0,0 +1,2 @@
SECRET_KEY=notsosecret
DEBUG=True

View File

@ -12,6 +12,10 @@ https://docs.djangoproject.com/en/4.0/ref/settings/
from pathlib import Path
import os
from dotenv import load_dotenv
load_dotenv()
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@ -20,26 +24,36 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-ioum!dn#uh5t3yn_15j)4qtjp6wyl24-xx*mv6d1kl&wk_-mx1'
SECRET_KEY = str(os.getenv('SECRET_KEY'))
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DEBUG = str(os.getenv("DEBUG")).lower() == "true"
ALLOWED_HOSTS = []
if DEBUG:
ALLOWED_HOSTS = ["*"]
else:
ALLOWED_HOSTS = ["api.roundedapp.tech"]
# Application definition
INSTALLED_APPS = [
'api',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
@ -68,17 +82,30 @@ TEMPLATES = [
]
WSGI_APPLICATION = 'config.wsgi.application'
CORS_ORIGIN_ALLOW_ALL=True
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
if DEBUG:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'rounded',
'USER': 'rounded',
'PASSWORD': 'rounded',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Password validation
@ -116,6 +143,8 @@ USE_TZ = True
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

View File

@ -14,8 +14,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
]