Skip to content
Open
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
// vscode
"editor.codeActionsOnSave": {
"source.organizeImports": true
"source.organizeImports": "explicit"
},
"editor.formatOnSave": true,
"files.eol": "\n",
Expand Down
7 changes: 6 additions & 1 deletion accounts/admin.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# from django.contrib import admin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import User

admin.site.register(User, UserAdmin)
10 changes: 10 additions & 0 deletions accounts/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm

User = get_user_model()


class SignupForm(UserCreationForm):
class Meta:
model = User
fields = ("username", "email")
95 changes: 95 additions & 0 deletions accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Generated by Django 4.2.19 on 2025-02-15 08:18

import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone


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",
),
),
(
"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",
),
),
("first_name", models.CharField(blank=True, max_length=150, verbose_name="first name")),
("last_name", models.CharField(blank=True, max_length=150, verbose_name="last name")),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"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",
),
),
("date_joined", models.DateTimeField(default=django.utils.timezone.now, verbose_name="date joined")),
("email", models.EmailField(max_length=254)),
(
"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={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
]
7 changes: 4 additions & 3 deletions accounts/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# from django.contrib.auth.models import AbstractUser
# from django.db import models
from django.contrib.auth.models import AbstractUser
from django.db import models


# class User(AbstractUser):
class User(AbstractUser):
email = models.EmailField()


# class FriendShip(models.Model):
218 changes: 188 additions & 30 deletions accounts/tests.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,192 @@
# from django.test import TestCase
from django.contrib.auth import SESSION_KEY, get_user_model
from django.test import TestCase
from django.urls import reverse

User = get_user_model()


class TestSignupView(TestCase):
def setUp(self):
self.url = reverse("accounts:signup")

def test_success_get(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "accounts/signup.html")

def test_success_post(self):
valid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "testpassword1",
"password2": "testpassword1",
}
response = self.client.post(self.url, valid_data)
# 1の確認 = tweets/homeにリダイレクトすること
self.assertRedirects(
response,
reverse("tweets:home"),
status_code=302,
target_status_code=200,
)
# 2の確認 = ユーザーが作成されること
self.assertTrue(User.objects.filter(username=valid_data["username"]).exists())
# 3の確認 = ログイン状態になること
self.assertIn(SESSION_KEY, self.client.session)

def test_failure_post_with_empty_form(self):
invalid_data = {
"username": "",
"email": "",
"password1": "",
"password2": "",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(User.objects.filter(username=invalid_data["email"]).exists())
self.assertFalse(User.objects.filter(username=invalid_data["password1"]).exists())
self.assertFalse(User.objects.filter(username=invalid_data["password2"]).exists())

self.assertFalse(form.is_valid())

self.assertIn("このフィールドは必須です。", form.errors["username"])
self.assertIn("このフィールドは必須です。", form.errors["email"])
self.assertIn("このフィールドは必須です。", form.errors["password1"])
self.assertIn("このフィールドは必須です。", form.errors["password2"])

def test_failure_post_with_empty_username(self):
invalid_data = {
"username": "",
"email": "test@test.com",
"password1": "testpassword",
"password2": "testpassword",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このフィールドは必須です。", form.errors["username"])

def test_failure_post_with_empty_email(self):
invalid_data = {
"username": "testuser",
"email": "",
"password1": "testpassword",
"password2": "testpassword",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このフィールドは必須です。", form.errors["email"])

def test_failure_post_with_empty_password(self):
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "",
"password2": "",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このフィールドは必須です。", form.errors["password1"])
self.assertIn("このフィールドは必須です。", form.errors["password2"])

def test_failure_post_with_duplicated_user(self):
User.objects.create_user(username="testuser", password="testpassword")
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "testpassword",
"password2": "testpassword",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertTrue(User.objects.filter(username=invalid_data["username"]).count() == 1)
self.assertFalse(form.is_valid())
self.assertIn("同じユーザー名が既に登録済みです。", form.errors["username"])

def test_failure_post_with_invalid_email(self):
invalid_data = {
"username": "testuser",
"email": "test1",
"password1": "testpassword",
"password2": "testpassword",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("有効なメールアドレスを入力してください。", form.errors["email"])

def test_failure_post_with_too_short_password(self):
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "test",
"password2": "test",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このパスワードは短すぎます。最低 8 文字以上必要です。", form.errors["password2"])

def test_failure_post_with_password_similar_to_username(self):
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "testuser",
"password2": "testuser",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このパスワードは ユーザー名 と似すぎています。", form.errors["password2"])

def test_failure_post_with_only_numbers_password(self):
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "11111111",
"password2": "11111111",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("このパスワードは数字しか使われていません。", form.errors["password2"])

def test_failure_post_with_mismatch_password(self):
invalid_data = {
"username": "testuser",
"email": "test@test.com",
"password1": "testpassword",
"password2": "testpassward",
}
response = self.client.post(self.url, invalid_data)
form = response.context["form"]
self.assertEqual(response.status_code, 200)
self.assertFalse(User.objects.filter(username=invalid_data["username"]).exists())
self.assertFalse(form.is_valid())
self.assertIn("確認用パスワードが一致しません。", form.errors["password2"])


# class TestLoginView(TestCase):


# class TestSignupView(TestCase):
# def test_success_get(self):

# def test_success_post(self):

# def test_failure_post_with_empty_form(self):

# def test_failure_post_with_empty_username(self):

# def test_failure_post_with_empty_email(self):

# def test_failure_post_with_empty_password(self):

# def test_failure_post_with_duplicated_user(self):

# def test_failure_post_with_invalid_email(self):

# def test_failure_post_with_too_short_password(self):

# def test_failure_post_with_password_similar_to_username(self):

# def test_failure_post_with_only_numbers_password(self):

# def test_failure_post_with_mismatch_password(self):


# class TestLoginView(TestCase):
# def test_success_get(self):

# def test_success_post(self):
Expand All @@ -36,7 +195,6 @@

# def test_failure_post_with_empty_password(self):


# class TestLogoutView(TestCase):
# def test_success_post(self):

Expand Down
6 changes: 3 additions & 3 deletions accounts/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# from django.contrib.auth import views as auth_views
# from django.urls import path
from django.urls import path

# from . import views
from . import views

app_name = "accounts"

urlpatterns = [
# path('signup/', views.SignupView.as_view(), name='signup'),
path("signup/", views.SignupView.as_view(), name="signup"),
# path('login/', auth_views.LoginView.as_view(), name='login'),
# path('logout/', auth_views.LogoutView.as_view(), name='logout'),
# path('<str:username>/', views.UserProfileView.as_view(), name='user_profile'),
Expand Down
Loading