Skip to content

Commit a809df7

Browse files
committed
Uploading files
0 parents  commit a809df7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+779
-0
lines changed

authentication/__init__.py

Whitespace-only changes.
165 Bytes
Binary file not shown.
730 Bytes
Binary file not shown.
460 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
349 Bytes
Binary file not shown.
1.46 KB
Binary file not shown.

authentication/admin.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from django.contrib import admin
2+
from .models import User
3+
4+
5+
class UserAdmin(admin.ModelAdmin):
6+
list_fields = ['fullname', 'email', 'is_staff']
7+
search_field = ['fullname', 'email']
8+
filter_fields = ['last_login']
9+
10+
class Meta:
11+
model = User
12+
13+
14+
admin.site.register(User, UserAdmin)

authentication/apps.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class AuthenticationConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'authentication'
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 3.2.9 on 2021-12-11 21:24
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
initial = True
9+
10+
dependencies = [
11+
('auth', '0012_alter_user_first_name_max_length'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='User',
17+
fields=[
18+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('password', models.CharField(max_length=128, verbose_name='password')),
20+
('fullname', models.CharField(blank=True, max_length=250, null=True)),
21+
('email', models.EmailField(max_length=254, unique=True)),
22+
('is_active', models.BooleanField(default=True)),
23+
('is_staff', models.BooleanField(default=False)),
24+
('is_superuser', models.BooleanField(default=False)),
25+
('last_login', models.DateTimeField(blank=True, null=True)),
26+
('date_joined', models.DateTimeField(auto_now_add=True)),
27+
('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')),
28+
('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')),
29+
],
30+
options={
31+
'abstract': False,
32+
},
33+
),
34+
]

authentication/migrations/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.

authentication/models.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from django.db import models
2+
from django.contrib.auth.models import BaseUserManager, PermissionsMixin, AbstractBaseUser
3+
from django.utils import timezone
4+
from rest_framework_simplejwt.tokens import RefreshToken
5+
6+
class BaseUser(BaseUserManager):
7+
def _create_user(self, email, password, is_staff, is_superuser, **kwargs):
8+
if not email:
9+
raise ValueError('User must have email address')
10+
now = timezone.now()
11+
email = self.normalize_email(email)
12+
user = self.model(
13+
email = email,
14+
is_staff = is_staff,
15+
is_superuser=is_superuser,
16+
last_login = now,
17+
date_joined=now,
18+
**kwargs
19+
)
20+
user.set_password(password)
21+
user.save(using=self._db)
22+
return user
23+
24+
#---create normal user
25+
def create_user(self, email=None, password=None, **kwargs):
26+
return self._create_user(email, password, False, False, **kwargs)
27+
28+
#---create superuser
29+
def create_superuser(self, email, password, **kwargs):
30+
user = self._create_user(email, password, True, True, **kwargs)
31+
user.save(using=self._db)
32+
return user
33+
34+
35+
36+
##---user model
37+
class User(PermissionsMixin, AbstractBaseUser):
38+
fullname=models.CharField(max_length=250, null=True, blank=True)
39+
email= models.EmailField(unique=True)
40+
is_active=models.BooleanField(default=True)
41+
is_staff=models.BooleanField(default=False)
42+
is_superuser=models.BooleanField(default=False)
43+
last_login = models.DateTimeField(null=True, blank=True)
44+
date_joined = models.DateTimeField(auto_now_add=True)
45+
objects = BaseUser()
46+
USERNAME_FIELD = 'email'
47+
EMAIL_FIELD = 'email'
48+
REQUIRED_FIELDS = []
49+
50+
def get_absolute_url(self):
51+
return "/users/%i/" % (self.pk)
52+
53+
def get_email(self):
54+
return self.email
55+
56+
@property
57+
def tokens(self):
58+
refresh = RefreshToken.for_user(self)
59+
60+
return {
61+
'refresh': str(refresh),
62+
'access': str(refresh.access_token),
63+
}

authentication/serializers.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from rest_framework import serializers
2+
from .models import User
3+
4+
5+
6+
class ResgisterSerializer(serializers.ModelSerializer):
7+
password = serializers.CharField(max_length=40, min_length=8, write_only=True)
8+
class Meta:
9+
model = User
10+
fields = ('fullname', 'email', 'password')
11+
12+
def validate(self, attrs):
13+
email = attrs.get('email', '')
14+
if User.objects.filter(email=email).exists():
15+
raise ValueError({'email', ('Email already taken, Please try again')})
16+
return attrs
17+
18+
def perform_create(self, validata):
19+
return User.objects.create_user(**validata)
20+
21+
22+
23+
class LoginSerializer(serializers.ModelSerializer):
24+
password = serializers.CharField(max_length=40, write_only=True)
25+
class Meta:
26+
model = User
27+
fields = ('fullname', 'email', 'password', 'tokens')
28+
read_only_fields = ['fullname', 'tokens']

authentication/tests.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

authentication/urls.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.urls import path
2+
from .views import *
3+
4+
5+
urlpatterns = [
6+
path('register', ResgisterApiView.as_view(), name="register"),
7+
path('login', LoginApiView.as_view(), name="login"),
8+
]

authentication/views.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from django.shortcuts import render
2+
from .models import User
3+
from .serializers import *
4+
from django.contrib.auth import authenticate
5+
from rest_framework import generics, permissions, status, response
6+
7+
8+
9+
class ResgisterApiView(generics.GenericAPIView):
10+
serializer_class = ResgisterSerializer
11+
12+
def post(self, request):
13+
serializer = self.serializer_class(data=request.data)
14+
if serializer.is_valid():
15+
serializer.save()
16+
return response.Response(serializer.data, status=status.HTTP_201_CREATED)
17+
return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
18+
19+
20+
21+
class LoginApiView(generics.GenericAPIView):
22+
serializer_class = LoginSerializer
23+
24+
def post(self, request):
25+
email = request.data.get('email', None)
26+
password = request.data.get('password', None)
27+
28+
user = authenticate(email=email, password=password)
29+
if user:
30+
serializer = self.serializer_class(user)
31+
return response.Response(serializer.data, status=status.HTTP_200_OK)
32+
return response.Response({'message': 'Invalid Credentail'}, status=status.HTTP_401_UNAUTHORIZED)

db.sqlite3

172 KB
Binary file not shown.

expenses/__init__.py

Whitespace-only changes.
159 Bytes
Binary file not shown.
200 Bytes
Binary file not shown.
442 Bytes
Binary file not shown.
1.41 KB
Binary file not shown.
976 Bytes
Binary file not shown.
506 Bytes
Binary file not shown.
2.4 KB
Binary file not shown.

expenses/admin.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

expenses/apps.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ExpensesConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'expenses'

expenses/migrations/0001_initial.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Generated by Django 3.2.9 on 2021-12-12 00:08
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='Category',
19+
fields=[
20+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21+
('title', models.CharField(max_length=250)),
22+
],
23+
),
24+
migrations.CreateModel(
25+
name='Expense',
26+
fields=[
27+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
28+
('amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=10)),
29+
('description', models.TextField(blank=True, null=True)),
30+
('date', models.DateField(blank=True, null=True)),
31+
('created_on', models.DateTimeField(auto_now_add=True)),
32+
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='expenses.category')),
33+
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
34+
],
35+
),
36+
]
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 3.2.9 on 2021-12-12 00:13
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12+
('expenses', '0001_initial'),
13+
]
14+
15+
operations = [
16+
migrations.AddField(
17+
model_name='category',
18+
name='owner',
19+
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='authentication.user'),
20+
preserve_default=False,
21+
),
22+
]

expenses/migrations/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.

expenses/models.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.db import models
2+
from authentication.models import User
3+
4+
class Category(models.Model):
5+
owner = models.ForeignKey(to=User, on_delete=models.CASCADE)
6+
title = models.CharField(max_length=250)
7+
8+
def __str__(self):
9+
return self.title
10+
11+
12+
class Expense(models.Model):
13+
category = models.ForeignKey(Category, on_delete=models.CASCADE)
14+
amount = models.DecimalField(max_digits=10, default=0.00, decimal_places=2)
15+
description = models.TextField(null=True, blank=True)
16+
owner = models.ForeignKey(to=User, on_delete=models.CASCADE)
17+
date = models.DateField(null=True, blank=True)
18+
created_on = models.DateTimeField(auto_now_add=True)
19+
20+
class Meta:
21+
ordering: ['-date']
22+
23+
def __str__(self):
24+
return str(self.owner)

expenses/serializers.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from rest_framework import serializers
2+
from .models import *
3+
4+
5+
class CategorySerializer(serializers.ModelSerializer):
6+
class Meta:
7+
model = Category
8+
fields = '__all__'
9+
read_only_fields = ['id', 'owner']
10+
11+
12+
class ExpenseSerializer(serializers.ModelSerializer):
13+
class Meta:
14+
model = Expense
15+
fields = '__all__'
16+
read_only_fields = ['id', 'owner', 'created_on']

expenses/tests.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

expenses/urls.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django.urls import path
2+
from .views import *
3+
4+
5+
urlpatterns = [
6+
path('category/', CategoryListView.as_view(), name="category"),
7+
path('category-detail/<int:id>/', CategoryDetailView.as_view(), name="category-detail"),
8+
path('', ExpenseListView.as_view(), name="expense"),
9+
path('<int:pk>', ExpenseDetailView.as_view(), name="expense-detail"),
10+
]

expenses/views.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from django.shortcuts import render
2+
from .models import Category, Expense
3+
from .serializers import CategorySerializer, ExpenseSerializer
4+
from rest_framework import generics, permissions
5+
from django_filters.rest_framework import DjangoFilterBackend
6+
7+
8+
9+
class CategoryListView(generics.ListCreateAPIView):
10+
serializer_class = CategorySerializer
11+
permission_classes = (permissions.IsAuthenticated,)
12+
queryset = Category.objects.all()
13+
14+
def perform_create(self, serializer):
15+
return serializer.save(owner=self.request.user)
16+
17+
def get_queryset(self):
18+
return self.queryset.filter(owner=self.request.user)
19+
20+
21+
class CategoryDetailView(generics.RetrieveUpdateDestroyAPIView):
22+
serializer_class = CategorySerializer
23+
permission_classes = (permissions.IsAuthenticated,)
24+
queryset = Category.objects.all()
25+
26+
def perform_create(self, serializer):
27+
return serializer.save(owner=self.request.user)
28+
29+
def get_queryset(self):
30+
return self.queryset.filter(owner=self.request.user)
31+
32+
33+
34+
35+
class ExpenseListView(generics.ListCreateAPIView):
36+
serializer_class = ExpenseSerializer
37+
permission_classes = (permissions.IsAuthenticated,)
38+
queryset = Expense.objects.all()
39+
filter_backends = [DjangoFilterBackend]
40+
filterset_fields = ['category']
41+
42+
def perform_create(self, serializer):
43+
return serializer.save(owner=self.request.user)
44+
45+
def get_queryset(self):
46+
return self.queryset.filter(owner=self.request.user)
47+
48+
49+
class ExpenseDetailView(generics.RetrieveUpdateDestroyAPIView):
50+
serializer_class = ExpenseSerializer
51+
permission_classes = (permissions.IsAuthenticated,)
52+
queryset = Expense.objects.all()
53+
54+
def perform_create(self, serializer):
55+
return serializer.save(owner=self.request.user)
56+
57+
def get_queryset(self):
58+
return self.queryset.filter(owner=self.request.user)

expensesapi/__init__.py

Whitespace-only changes.
162 Bytes
Binary file not shown.
3.13 KB
Binary file not shown.
1.19 KB
Binary file not shown.
573 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)