From 3fefe48875b0d851327cb2e4f8185f054c92bc4a Mon Sep 17 00:00:00 2001 From: Andrew4Coding <andrewdevitoaryo@gmail.com> Date: Tue, 25 Mar 2025 20:36:23 +0800 Subject: [PATCH] fix: user model and admin model --- main/settings.py | 8 +-- main/urls.py | 2 +- user/admin.py | 30 --------- user/forms.py | 49 --------------- user/migrations/0001_initial.py | 51 ---------------- ...n_alter_extendeduser_deskripsi_and_more.py | 61 ------------------- ...admin_is_staff_simpleadmin_is_superuser.py | 23 ------- user/migrations/0004_delete_simpleadmin.py | 16 ----- user/tests.py | 3 - user/views.py | 53 ---------------- {user => user_profile}/__init__.py | 0 user_profile/admin.py | 4 ++ {user => user_profile}/apps.py | 4 +- user_profile/forms.py | 39 ++++++++++++ user_profile/migrations/0001_initial.py | 33 ++++++++++ {user => user_profile}/migrations/__init__.py | 0 {user => user_profile}/models.py | 20 +----- {user => user_profile}/templates/login.html | 0 .../templates/register.html | 13 +++- {user => user_profile}/urls.py | 0 user_profile/views.py | 45 ++++++++++++++ {user => user_profile}/widgets.py | 0 22 files changed, 142 insertions(+), 312 deletions(-) delete mode 100644 user/admin.py delete mode 100644 user/forms.py delete mode 100644 user/migrations/0001_initial.py delete mode 100644 user/migrations/0002_simpleadmin_alter_extendeduser_deskripsi_and_more.py delete mode 100644 user/migrations/0003_simpleadmin_is_staff_simpleadmin_is_superuser.py delete mode 100644 user/migrations/0004_delete_simpleadmin.py delete mode 100644 user/tests.py delete mode 100644 user/views.py rename {user => user_profile}/__init__.py (100%) create mode 100644 user_profile/admin.py rename {user => user_profile}/apps.py (60%) create mode 100644 user_profile/forms.py create mode 100644 user_profile/migrations/0001_initial.py rename {user => user_profile}/migrations/__init__.py (100%) rename {user => user_profile}/models.py (84%) rename {user => user_profile}/templates/login.html (100%) rename {user => user_profile}/templates/register.html (79%) rename {user => user_profile}/urls.py (100%) create mode 100644 user_profile/views.py rename {user => user_profile}/widgets.py (100%) diff --git a/main/settings.py b/main/settings.py index baace99..3c07063 100644 --- a/main/settings.py +++ b/main/settings.py @@ -42,7 +42,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'user' + 'user_profile' ] MIDDLEWARE = [ @@ -83,7 +83,7 @@ import dotenv env = dotenv.dotenv_values() -IS_PROD = env.get('IS_PROD', False) +IS_PROD = False DATABASES = { 'default': { @@ -140,6 +140,4 @@ STATICFILES_DIRS = [ ] -STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') - -AUTH_USER_MODEL = 'user.ExtendedUser' \ No newline at end of file +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') \ No newline at end of file diff --git a/main/urls.py b/main/urls.py index 8894dec..b28f40f 100644 --- a/main/urls.py +++ b/main/urls.py @@ -21,5 +21,5 @@ from .views import show_home urlpatterns = [ path('admin/', admin.site.urls), path("", show_home, name="home"), - path('user/', include('user.urls')), + path('user/', include('user_profile.urls')), ] diff --git a/user/admin.py b/user/admin.py deleted file mode 100644 index c0dfc75..0000000 --- a/user/admin.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.contrib import admin -from django.contrib.auth.admin import UserAdmin -from .models import ExtendedUser - -class ExtendedUserAdmin(UserAdmin): - # Define the fields to display in the admin list view - list_display = ("username", "email", "fullname", "kategori_produk", "is_staff", "is_active") - search_fields = ("username", "email", "fullname", "nomor_hp") - list_filter = ("is_staff", "is_active", "kategori_produk") - - # Define the fieldsets for updating users in the admin panel - fieldsets = ( - (None, {"fields": ("username", "email", "password")}), - ("Personal Info", {"fields": ("fullname", "tanggal_lahir", "nomor_hp", "url_blog", "deskripsi")}), - ("Permissions", {"fields": ("is_active", "is_staff", "is_superuser", "groups", "user_permissions")}), - ("Additional Info", {"fields": ("id_penjual", "kategori_produk")}), - ) - - # Define the fieldsets for creating a new user - add_fieldsets = ( - (None, { - "classes": ("wide",), - "fields": ("username", "email", "password1", "password2", "fullname", "kategori_produk"), - }), - ) - - ordering = ("username",) - -# Register the custom user model -admin.site.register(ExtendedUser, ExtendedUserAdmin) diff --git a/user/forms.py b/user/forms.py deleted file mode 100644 index f4471b2..0000000 --- a/user/forms.py +++ /dev/null @@ -1,49 +0,0 @@ -from django import forms -from django.contrib.auth.forms import UserCreationForm -from .models import ExtendedUser -from django.contrib.auth.forms import AuthenticationForm -from django.forms.widgets import PasswordInput, TextInput - - -class ExtendedUserForm(UserCreationForm): - class Meta: - model = ExtendedUser - fields = [ - "username", - "email", - "password1", - "password2", - "fullname", - "tanggal_lahir", - "nomor_hp", - "url_blog", - "deskripsi", - "id_penjual", - "kategori_produk", - ] - - labels = { - "username": "Username", - "email": "Email", - "password1": "Password", - "password2": "Confirm Password", - "fullname": "Full Name", - "tanggal_lahir": "Date of Birth", - "nomor_hp": "Phone Number", - "url_blog": "Blog URL", - "deskripsi": "Description", - "id_penjual": "Seller ID", - "kategori_produk": "Product Category", - } - - tanggal_lahir = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'})) - -class ExtendedUserLoginForm(AuthenticationForm): - username = forms.CharField( - widget=TextInput(attrs={"class": "w-full px-3 py-2 border rounded-md", "placeholder": "Username"}), - label="Username" - ) - password = forms.CharField( - widget=PasswordInput(attrs={"class": "w-full px-3 py-2 border rounded-md", "placeholder": "Password"}), - label="Password" - ) diff --git a/user/migrations/0001_initial.py b/user/migrations/0001_initial.py deleted file mode 100644 index 9eed135..0000000 --- a/user/migrations/0001_initial.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 5.1.7 on 2025-03-17 06:16 - -import django.contrib.auth.models -import django.contrib.auth.validators -import django.utils.timezone -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='ExtendedUser', - 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')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), - ('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')), - ('fullname', models.CharField(max_length=100)), - ('tanggal_lahir', models.DateField()), - ('nomor_hp', models.CharField(max_length=15)), - ('url_blog', models.CharField(max_length=255)), - ('deskripsi', models.TextField()), - ('id_penjual', models.IntegerField()), - ('kategori_produk', models.CharField(choices=[('Elektronik', 'Elektronik'), ('Fashion', 'Fashion'), ('Furnitur', 'Furnitur'), ('Obat', 'Obat'), ('Kecantikan', 'Kecantikan')], max_length=50)), - ('groups', models.ManyToManyField(blank=True, related_name='extendeduser_groups', to='auth.group')), - ('user_permissions', models.ManyToManyField(blank=True, related_name='extendeduser_permissions', to='auth.permission')), - ], - options={ - 'verbose_name': 'user', - 'verbose_name_plural': 'users', - 'abstract': False, - }, - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], - ), - ] diff --git a/user/migrations/0002_simpleadmin_alter_extendeduser_deskripsi_and_more.py b/user/migrations/0002_simpleadmin_alter_extendeduser_deskripsi_and_more.py deleted file mode 100644 index 9c80a5c..0000000 --- a/user/migrations/0002_simpleadmin_alter_extendeduser_deskripsi_and_more.py +++ /dev/null @@ -1,61 +0,0 @@ -# Generated by Django 5.1.7 on 2025-03-17 08:07 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='SimpleAdmin', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('username', models.CharField(max_length=150, unique=True)), - ('password', models.CharField(max_length=128)), - ], - options={ - 'abstract': False, - }, - ), - migrations.AlterField( - model_name='extendeduser', - name='deskripsi', - field=models.TextField(validators=[django.core.validators.MinLengthValidator(5), django.core.validators.MaxLengthValidator(1000)]), - ), - migrations.AlterField( - model_name='extendeduser', - name='email', - field=models.CharField(max_length=255, validators=[django.core.validators.EmailValidator(message='Email harus sesuai dengan format email.')]), - ), - migrations.AlterField( - model_name='extendeduser', - name='fullname', - field=models.CharField(max_length=255, validators=[django.core.validators.RegexValidator(message='Nama hanya boleh berisi huruf, angka, dan karakter (., _, -).', regex='^[a-zA-Z0-9._-]+$')]), - ), - migrations.AlterField( - model_name='extendeduser', - name='nomor_hp', - field=models.CharField(max_length=15, validators=[django.core.validators.RegexValidator(message='Nomor HP harus dalam format (kode negara - nomor telepon) dengan panjang minimal 8 dan maksimal 15. Contoh: 62123456, bukan +62123456 dan 62-12345.', regex='^62\\d{6,13}$')]), - ), - migrations.AlterField( - model_name='extendeduser', - name='password', - field=models.CharField(max_length=255, validators=[django.core.validators.MinLengthValidator(8), django.core.validators.RegexValidator(message='Password harus berisi huruf, angka, dan karakter spesial dengan panjang minimal 8.', regex='^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$')]), - ), - migrations.AlterField( - model_name='extendeduser', - name='tanggal_lahir', - field=models.DateField(validators=[django.core.validators.RegexValidator(message='Tanggal lahir harus dalam format YYYY-MM-DD.', regex='^\\d{4}-\\d{2}-\\d{2}$')]), - ), - migrations.AlterField( - model_name='extendeduser', - name='url_blog', - field=models.CharField(max_length=255, validators=[django.core.validators.URLValidator(message='URL Blog harus sesuai dengan format URL.')]), - ), - ] diff --git a/user/migrations/0003_simpleadmin_is_staff_simpleadmin_is_superuser.py b/user/migrations/0003_simpleadmin_is_staff_simpleadmin_is_superuser.py deleted file mode 100644 index 0ba56c0..0000000 --- a/user/migrations/0003_simpleadmin_is_staff_simpleadmin_is_superuser.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 5.1.7 on 2025-03-17 08:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0002_simpleadmin_alter_extendeduser_deskripsi_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='simpleadmin', - name='is_staff', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='simpleadmin', - name='is_superuser', - field=models.BooleanField(default=True), - ), - ] diff --git a/user/migrations/0004_delete_simpleadmin.py b/user/migrations/0004_delete_simpleadmin.py deleted file mode 100644 index 66f39de..0000000 --- a/user/migrations/0004_delete_simpleadmin.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 5.1.7 on 2025-03-17 08:20 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0003_simpleadmin_is_staff_simpleadmin_is_superuser'), - ] - - operations = [ - migrations.DeleteModel( - name='SimpleAdmin', - ), - ] diff --git a/user/tests.py b/user/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/user/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/user/views.py b/user/views.py deleted file mode 100644 index d8a5728..0000000 --- a/user/views.py +++ /dev/null @@ -1,53 +0,0 @@ -from django.shortcuts import render, redirect -from django.contrib.auth import authenticate, login, logout -from django.contrib import messages -from .forms import ExtendedUserLoginForm - -from .forms import ExtendedUserForm -from django.contrib import messages - -def login_view(request): - if request.user.is_authenticated: - return redirect("home") # Change "home" to your desired redirect URL - - if request.method == "POST": - form = ExtendedUserLoginForm(request, data=request.POST) - - print(form.errors) - - if form.is_valid(): - username = form.cleaned_data["username"] - password = form.cleaned_data["password"] - user = authenticate(request, username=username, password=password) - if user is not None: - login(request, user) - return redirect("home") # Redirect to home/dashboard - else: - messages.error(request, "Invalid username or password") - else: - messages.error(request, "Invalid form submission") - - else: - form = ExtendedUserLoginForm() - - return render(request, "login.html", {"form": form}) - -def register_view(request): - if request.method == "POST": - form = ExtendedUserForm(request.POST) - if form.is_valid() : - print(form.cleaned_data) - form.save() - request.session.flush() - messages.success(request, "Account created successfully. Please log in.") - return redirect("login") # Redirect to login page - else: - messages.error(request, str(form.errors)) - else: - form = ExtendedUserForm() - - return render(request, "register.html", {"form": form}) - -def logout_view(request): - logout(request) - return redirect("home") \ No newline at end of file diff --git a/user/__init__.py b/user_profile/__init__.py similarity index 100% rename from user/__init__.py rename to user_profile/__init__.py diff --git a/user_profile/admin.py b/user_profile/admin.py new file mode 100644 index 0000000..c6a94a9 --- /dev/null +++ b/user_profile/admin.py @@ -0,0 +1,4 @@ +from .models import UserProfile +from django.contrib import admin + +admin.site.register(UserProfile) \ No newline at end of file diff --git a/user/apps.py b/user_profile/apps.py similarity index 60% rename from user/apps.py rename to user_profile/apps.py index 36cce4c..fe0436b 100644 --- a/user/apps.py +++ b/user_profile/apps.py @@ -1,6 +1,6 @@ from django.apps import AppConfig -class UserConfig(AppConfig): +class UserProfileConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' - name = 'user' + name = 'user_profile' diff --git a/user_profile/forms.py b/user_profile/forms.py new file mode 100644 index 0000000..1057559 --- /dev/null +++ b/user_profile/forms.py @@ -0,0 +1,39 @@ +from django import forms +from .models import UserProfile +from django.contrib.auth.models import User + +class UserForm(forms.ModelForm): + password = forms.CharField(widget=forms.PasswordInput) # Hide password input + + class Meta: + model = User + fields = ['username', 'email', 'password'] + +class UserProfileForm(forms.ModelForm): + class Meta: + model = UserProfile + fields = [ + "fullname", + "tanggal_lahir", + "nomor_hp", + "url_blog", + "deskripsi", + "id_penjual", + "kategori_produk", + ] + + labels = { + "fullname": "Full Name", + "tanggal_lahir": "Date of Birth", + "nomor_hp": "Phone Number", + "url_blog": "Blog URL", + "deskripsi": "Description", + "id_penjual": "Seller ID", + "kategori_produk": "Product Category", + } + + tanggal_lahir = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'})) + +class LoginForm(forms.Form): + username = forms.CharField() + password = forms.CharField(widget=forms.PasswordInput) \ No newline at end of file diff --git a/user_profile/migrations/0001_initial.py b/user_profile/migrations/0001_initial.py new file mode 100644 index 0000000..b57e750 --- /dev/null +++ b/user_profile/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 5.1.7 on 2025-03-25 12:23 + +import django.core.validators +import user_profile.models +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='UserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('fullname', models.CharField(max_length=255, validators=[django.core.validators.RegexValidator(message='Nama hanya boleh berisi huruf, angka, dan karakter (., _, -).', regex='^[a-zA-Z0-9._-]+$')])), + ('password', models.CharField(max_length=255, validators=[django.core.validators.MinLengthValidator(8), django.core.validators.RegexValidator(message='Password harus berisi huruf, angka, dan karakter spesial dengan panjang minimal 8.', regex='^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$')])), + ('tanggal_lahir', models.DateField(validators=[django.core.validators.RegexValidator(message='Tanggal lahir harus dalam format YYYY-MM-DD.', regex='^\\d{4}-\\d{2}-\\d{2}$'), user_profile.models.UserProfile.clean_tanggal_lahir])), + ('nomor_hp', models.CharField(max_length=15, validators=[user_profile.models.UserProfile.validate_and_sanitize_phone])), + ('url_blog', models.CharField(max_length=255, validators=[django.core.validators.URLValidator(message='URL Blog harus sesuai dengan format URL.')])), + ('deskripsi', models.TextField(validators=[django.core.validators.MinLengthValidator(5), django.core.validators.MaxLengthValidator(1000)])), + ('id_penjual', models.CharField(max_length=10, validators=[django.core.validators.RegexValidator(message='ID Penjual harus diawali dengan "S-" diikuti oleh 8 angka.', regex='^S-\\d{8}$')])), + ('kategori_produk', models.CharField(choices=[('Elektronik', 'Elektronik'), ('Fashion', 'Fashion'), ('Furnitur', 'Furnitur'), ('Obat', 'Obat'), ('Kecantikan', 'Kecantikan')], max_length=50)), + ('groups', models.ManyToManyField(blank=True, related_name='extendeduser_groups', to='auth.group')), + ('user_permissions', models.ManyToManyField(blank=True, related_name='extendeduser_permissions', to='auth.permission')), + ], + ), + ] diff --git a/user/migrations/__init__.py b/user_profile/migrations/__init__.py similarity index 100% rename from user/migrations/__init__.py rename to user_profile/migrations/__init__.py diff --git a/user/models.py b/user_profile/models.py similarity index 84% rename from user/models.py rename to user_profile/models.py index abc2501..c093c4a 100644 --- a/user/models.py +++ b/user_profile/models.py @@ -1,11 +1,9 @@ from django.db import models -from django.contrib.auth.models import AbstractUser from django.core.validators import RegexValidator, MinLengthValidator, MaxLengthValidator, EmailValidator, URLValidator from django.utils import timezone from django.core.exceptions import ValidationError -class ExtendedUser(AbstractUser): - +class UserProfile(models.Model): def clean_tanggal_lahir(value): age = (timezone.now().date() - value).days / 365.25 print(age) @@ -49,16 +47,7 @@ class ExtendedUser(AbstractUser): ) ] ) - password = models.CharField( - max_length=255, - validators=[ - MinLengthValidator(8), - RegexValidator( - regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$', - message='Password harus berisi huruf, angka, dan karakter spesial dengan panjang minimal 8.' - ) - ] - ) + tanggal_lahir = models.DateField( validators=[ RegexValidator( @@ -74,10 +63,6 @@ class ExtendedUser(AbstractUser): validate_and_sanitize_phone ] ) - email = models.CharField( - max_length=255, - validators=[EmailValidator(message='Email harus sesuai dengan format email.')] - ) url_blog = models.CharField( max_length=255, validators=[URLValidator(message='URL Blog harus sesuai dengan format URL.')] @@ -112,3 +97,4 @@ class ExtendedUser(AbstractUser): related_name="extendeduser_permissions", # Custom related_name blank=True ) + \ No newline at end of file diff --git a/user/templates/login.html b/user_profile/templates/login.html similarity index 100% rename from user/templates/login.html rename to user_profile/templates/login.html diff --git a/user/templates/register.html b/user_profile/templates/register.html similarity index 79% rename from user/templates/register.html rename to user_profile/templates/register.html index d7fc240..226ffea 100644 --- a/user/templates/register.html +++ b/user_profile/templates/register.html @@ -21,7 +21,18 @@ <form method="post" class="space-y-4"> {% csrf_token %} - {% for field in form %} + {% for field in user_form %} + <div> + <label for="{{ field.id_for_label }}" class="block text-sm font-medium text-gray-700">{{ field.label }}</label> + {{ field }} + + {% if field.errors %} + <p class="text-sm text-red-500 mt-1">{{ field.errors.0 }}</p> + {% endif %} + </div> + {% endfor %} + + {% for field in profile_form %} <div> <label for="{{ field.id_for_label }}" class="block text-sm font-medium text-gray-700">{{ field.label }}</label> {{ field }} diff --git a/user/urls.py b/user_profile/urls.py similarity index 100% rename from user/urls.py rename to user_profile/urls.py diff --git a/user_profile/views.py b/user_profile/views.py new file mode 100644 index 0000000..3e7a7a3 --- /dev/null +++ b/user_profile/views.py @@ -0,0 +1,45 @@ +from django.shortcuts import render, redirect +from django.contrib.auth import login, logout + +from .forms import UserProfileForm, UserForm +from django.contrib.auth.forms import AuthenticationForm + +def login_view(request): + if request.method == "POST": + form = AuthenticationForm(request, data=request.POST) + if form.is_valid(): + user = form.get_user() + login(request, user) + return redirect('home') # Change 'home' to your desired redirect page + else: + form = AuthenticationForm() + + return render(request, 'login.html', {'form': form}) + +def register_view(request): + if request.method == "POST": + user_form = UserForm(request.POST) + profile_form = UserProfileForm(request.POST, request.FILES) + + if user_form.is_valid() and profile_form.is_valid(): + user = user_form.save(commit=False) + user.set_password(user_form.cleaned_data['password']) # Hash password + user.save() + + # Create UserProfile linked to the user + profile = profile_form.save(commit=False) + profile.user = user + profile.save() + + login(request, user) # Log in the user + return redirect("home") # Redirect to a dashboard or home page + + else: + user_form = UserForm() + profile_form = UserProfileForm() + + return render(request, "register.html", {"user_form": user_form, "profile_form": profile_form}) + +def logout_view(request): + logout(request) + return redirect("home") \ No newline at end of file diff --git a/user/widgets.py b/user_profile/widgets.py similarity index 100% rename from user/widgets.py rename to user_profile/widgets.py -- GitLab