Skip to content

Commit

Permalink
add swagger document and add new app user
Browse files Browse the repository at this point in the history
  • Loading branch information
romangurung committed Oct 14, 2024
1 parent 6338175 commit 4bf43ec
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 3 deletions.
8 changes: 8 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
'django.contrib.messages',
'django.contrib.staticfiles',
'core',
'rest_framework',
'drf_spectacular'
]

MIDDLEWARE = [
Expand Down Expand Up @@ -128,3 +130,9 @@
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

AUTH_USER_MODEL = 'core.User'

REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'
}
10 changes: 10 additions & 0 deletions app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,19 @@
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView,
)
from django.contrib import admin
from django.urls import path

urlpatterns = [
path('admin/', admin.site.urls),
path('api/schema/', SpectacularAPIView.as_view(), name='api-schema'),
path(
'api/docs/',
SpectacularSwaggerView.as_view(url_name='api-schema'),
name='api-docs',
)
]
43 changes: 42 additions & 1 deletion app/core/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
"""
Django admin customization.
"""
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.utils.translation import gettext_lazy as _
from core import models
class UserAdmin(BaseUserAdmin):
"""Define the admin pages for users."""
ordering = ['id']
list_display = ['email', 'name']
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal Info'), {'fields': ('name',)}),
(
_('Permissions'),
{
'fields': (
'is_active',
'is_staff',
'is_superuser',
)
}
),
(_('Important dates'), {'fields': ('last_login',)}),
)
readonly_fields = ['last_login']
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': (
'email',
'password1',
'password2',
'name',
'is_active',
'is_staff',
'is_superuser',
),
}),
)

# Register your models here.

admin.site.register(models.User, UserAdmin)
33 changes: 33 additions & 0 deletions app/core/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.25 on 2024-10-07 06:39

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]

operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('email', models.EmailField(max_length=255, unique=True)),
('name', models.CharField(max_length=255)),
('is_active', models.BooleanField(default=True)),
('is_staff', models.BooleanField(default=False)),
('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')),
('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')),
],
options={
'abstract': False,
},
),
]
40 changes: 39 additions & 1 deletion app/core/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
"""
Database models.
"""
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin
)

class UserManager(BaseUserManager):
""" Manager for users."""

def create_user(self, email, password=None, **extra_fields):
"""Create, save and return a new user."""
if not email:
raise ValueError('User must have an enail address.')
user = self.model(email=self.normalize_email(email), **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user

def create_superuser(self, email, password):
"""Create and return super user"""
user = self.create_user(email, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user

class User(AbstractBaseUser, PermissionsMixin):
""" User in the system."""
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)

objects = UserManager()

USERNAME_FIELD = 'email'

# Create your models here.
47 changes: 47 additions & 0 deletions app/core/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""
Tests for the Django admin modifications.
"""

from django.test import TestCase
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.test import Client

class AdminSiteTests(TestCase):
"""Tests for Django admin."""

def setUp(self):
"""Create user and client"""
self.client = Client()
self.admin_user = get_user_model().objects.create_superuser(
email='[email protected]',
password='testpass123',
)
self.client.force_login(self.admin_user)
self.user = get_user_model().objects.create_user(
email='[email protected]',
password='testpass123',
name='Test User'
)

def test_users_list(self):
"""Test that users are listed on page."""
url = reverse('admin:core_user_changelist')
res = self.client.get(url)

self.assertContains(res, self.user.name)
self.assertContains(res, self.user.email)

def test_edit_user_page(self):
"""Test the edit user page works."""
url = reverse('admin:core_user_change', args=[self.user.id])
res = self.client.get(url)

self.assertEqual(res.status_code, 200)

def test_create_user_page(self):
"""Test the create user page works."""
url = reverse('admin:core_user_add')
res = self.client.get(url)

self.assertEqual(res.status_code, 200)
46 changes: 46 additions & 0 deletions app/core/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Tests for models.
"""
from django.test import TestCase
from django.contrib.auth import get_user_model

class ModelTests(TestCase):
""" Test models. """

def test_create_user_with_email_successful(self):
"""Test creating a user with an email is successful."""
email = '[email protected]'
password = 'testpass123'
user = get_user_model().objects.create_user(
email=email,
password=password,
)
self.assertEqual(user.email, email)
self.assertTrue(user.check_password(password))

def test_new_user_email_normalized(self):
"""Test email is normalized for new users."""
sample_emails = [
['[email protected]', '[email protected]'],
['[email protected]', '[email protected]'],
['[email protected]', '[email protected]'],
['[email protected]', '[email protected]']
]

for email, expected in sample_emails:
user = get_user_model().objects.create_user(email, 'sample123')
self.assertEqual(user.email, expected)

def test_new_user_without_email_raises_error(self):
"""Test that creating a user without an email raises a ValueError"""
with self.assertRaises(ValueError):
get_user_model().objects.create_user('', 'test123')

def test_create_superuser(self):
"""Test creating a superuser."""
user = get_user_model().objects.create_superuser(
'[email protected]',
'test123'
)
self.assertTrue(user.is_superuser)
self.assertTrue(user.is_staff)
Empty file added app/user/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions app/user/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions app/user/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class UserConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'user'
Empty file added app/user/migrations/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions app/user/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
3 changes: 3 additions & 0 deletions app/user/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
3 changes: 3 additions & 0 deletions app/user/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.shortcuts import render

# Create your views here.
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Django>=3.2.4,<3.3
djangorestframework>=3.12.4,<3.13
psycopg2>=2.8.6,<2.9
psycopg2>=2.8.6,<2.9
drf-spectacular>=0.15.1,<0.16

0 comments on commit 4bf43ec

Please sign in to comment.