diff --git a/anfisa_for_friends/anfisa_for_friends/settings.py b/anfisa_for_friends/anfisa_for_friends/settings.py
index a8c9efe0..ca1b7d6a 100644
--- a/anfisa_for_friends/anfisa_for_friends/settings.py
+++ b/anfisa_for_friends/anfisa_for_friends/settings.py
@@ -9,6 +9,8 @@
ALLOWED_HOSTS = []
INSTALLED_APPS = [
+ 'users.apps.UsersConfig',
+ 'statistic.apps.StatisticConfig',
'homepage.apps.HomepageConfig',
'ice_cream.apps.IceCreamConfig',
'about.apps.AboutConfig',
@@ -94,3 +96,9 @@
]
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
+AUTH_USER_MODEL = 'users.CustomUser'
+
+LOGIN_URL = 'users:login'
+LOGOUT_URL = 'users:logout'
+LOGIN_REDIRECT_URL = 'homepage:index'
diff --git a/anfisa_for_friends/anfisa_for_friends/urls.py b/anfisa_for_friends/anfisa_for_friends/urls.py
index 08c8ba7e..21867092 100644
--- a/anfisa_for_friends/anfisa_for_friends/urls.py
+++ b/anfisa_for_friends/anfisa_for_friends/urls.py
@@ -5,5 +5,7 @@
path('', include('homepage.urls', namespace='homepage')),
path('about/', include('about.urls', namespace='about')),
path('ice_cream/', include('ice_cream.urls', namespace='ice_cream')),
+ path('statistic/', include('statistic.urls', namespace='statistic')),
+ path('auth/', include('users.urls', namespace='users')),
path('admin/', admin.site.urls),
]
diff --git a/anfisa_for_friends/static_dev/img/image-holder.png b/anfisa_for_friends/static_dev/img/image-holder.png
new file mode 100644
index 00000000..55e7e4d2
Binary files /dev/null and b/anfisa_for_friends/static_dev/img/image-holder.png differ
diff --git a/anfisa_for_friends/statistic/__init__.py b/anfisa_for_friends/statistic/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/anfisa_for_friends/statistic/admin.py b/anfisa_for_friends/statistic/admin.py
new file mode 100644
index 00000000..8c38f3f3
--- /dev/null
+++ b/anfisa_for_friends/statistic/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/anfisa_for_friends/statistic/apps.py b/anfisa_for_friends/statistic/apps.py
new file mode 100644
index 00000000..a38a6cc0
--- /dev/null
+++ b/anfisa_for_friends/statistic/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class StatisticConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'statistic'
diff --git a/anfisa_for_friends/statistic/migrations/__init__.py b/anfisa_for_friends/statistic/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/anfisa_for_friends/statistic/models.py b/anfisa_for_friends/statistic/models.py
new file mode 100644
index 00000000..71a83623
--- /dev/null
+++ b/anfisa_for_friends/statistic/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/anfisa_for_friends/statistic/tests.py b/anfisa_for_friends/statistic/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/anfisa_for_friends/statistic/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/anfisa_for_friends/statistic/urls.py b/anfisa_for_friends/statistic/urls.py
new file mode 100644
index 00000000..02f2f6ae
--- /dev/null
+++ b/anfisa_for_friends/statistic/urls.py
@@ -0,0 +1,10 @@
+from django.urls import path
+
+from . import views
+
+app_name = 'statistic'
+
+urlpatterns = [
+ path('google/', views.google_search, name='google_search'),
+ path('yandex/', views.yandex_search, name='yandex_search'),
+]
diff --git a/anfisa_for_friends/statistic/views.py b/anfisa_for_friends/statistic/views.py
new file mode 100644
index 00000000..2cb68c6e
--- /dev/null
+++ b/anfisa_for_friends/statistic/views.py
@@ -0,0 +1,9 @@
+from django.http import HttpResponse
+
+
+def google_search(request):
+ return HttpResponse('Это станица для поисковой системы Google')
+
+
+def yandex_search(request):
+ return HttpResponse('Это станица для поисковой системы Yandex')
diff --git a/anfisa_for_friends/templates/about/description.html b/anfisa_for_friends/templates/about/description.html
index 373d14cf..37b2f5ba 100644
--- a/anfisa_for_friends/templates/about/description.html
+++ b/anfisa_for_friends/templates/about/description.html
@@ -1,7 +1,10 @@
{% extends "base.html" %}
{% block title %}
- Анфиса для друзей. Описание проекта
+ Анфиса для друзей. О проекте
{% endblock %}
{% block content %}
-
Описание проекта
+ О проекте
+
+ Каталог экзотических сортов мороженого.
+
{% endblock %}
diff --git a/anfisa_for_friends/templates/base.html b/anfisa_for_friends/templates/base.html
index 6219c7a6..9a61e2d6 100644
--- a/anfisa_for_friends/templates/base.html
+++ b/anfisa_for_friends/templates/base.html
@@ -10,9 +10,11 @@
{% include "includes/header.html" %}
-
+
+
{% block content %}
{% endblock %}
+
{% include "includes/footer.html" %}
diff --git a/anfisa_for_friends/templates/homepage/index.html b/anfisa_for_friends/templates/homepage/index.html
index 3d2191c0..059f0f48 100644
--- a/anfisa_for_friends/templates/homepage/index.html
+++ b/anfisa_for_friends/templates/homepage/index.html
@@ -3,5 +3,5 @@
Анфиса для друзей. Главная
{% endblock %}
{% block content %}
- Главная страница
+ Главная страница
{% endblock %}
diff --git a/anfisa_for_friends/templates/ice_cream/detail.html b/anfisa_for_friends/templates/ice_cream/detail.html
index a6af384c..97ce7694 100644
--- a/anfisa_for_friends/templates/ice_cream/detail.html
+++ b/anfisa_for_friends/templates/ice_cream/detail.html
@@ -1,10 +1,21 @@
{% extends "base.html" %}
+{% load static %}
{% block title %}
- Анфиса для друзей. Подробное описание мороженого
+ Анфиса для друзей. {{ ice_cream.title }}
{% endblock %}
{% block content %}
- Подробное описание мороженого
- {{ ice_cream.title }}
- {{ ice_cream.description }}
+ {{ ice_cream.title }}
+
+
+
Описание
+
{{ ice_cream.description }}
+
+
+

+
+
{% endblock %}
-
\ No newline at end of file
diff --git a/anfisa_for_friends/templates/ice_cream/list.html b/anfisa_for_friends/templates/ice_cream/list.html
index 65f098c2..17701bed 100644
--- a/anfisa_for_friends/templates/ice_cream/list.html
+++ b/anfisa_for_friends/templates/ice_cream/list.html
@@ -1,19 +1,33 @@
{% extends "base.html" %}
+{% load static %}
{% block title %}
Анфиса для друзей. Каталог мороженого
{% endblock %}
{% block content %}
- Каталог мороженого
-
-{% endblock %}
\ No newline at end of file
+ Каталог мороженого
+
+ {% for ice_cream in ice_cream_list %}
+
+
+
+

+
+
{{ ice_cream.title }}
+
+ {{ ice_cream.description|truncatewords:10 }}
+
+
+ Подробнее -->
+
+
+
+
+ {% endfor %}
+
+{% endblock %}
diff --git a/anfisa_for_friends/templates/includes/footer.html b/anfisa_for_friends/templates/includes/footer.html
index 2d3af22c..ef9f1777 100644
--- a/anfisa_for_friends/templates/includes/footer.html
+++ b/anfisa_for_friends/templates/includes/footer.html
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/anfisa_for_friends/templates/includes/header.html b/anfisa_for_friends/templates/includes/header.html
index 66520481..9c3a5a75 100644
--- a/anfisa_for_friends/templates/includes/header.html
+++ b/anfisa_for_friends/templates/includes/header.html
@@ -1,17 +1,63 @@
{% load static %}
+{% with request.resolver_match.view_name as view_name %}
-
-
\ No newline at end of file
+
+{% endwith %}
\ No newline at end of file
diff --git a/anfisa_for_friends/templates/users/login.html b/anfisa_for_friends/templates/users/login.html
new file mode 100644
index 00000000..b72cb73c
--- /dev/null
+++ b/anfisa_for_friends/templates/users/login.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block title %}
+ Login
+{% endblock %}
+
+{% block content %}
+ Login
+
+{% endblock %}
diff --git a/anfisa_for_friends/templates/users/signup.html b/anfisa_for_friends/templates/users/signup.html
new file mode 100644
index 00000000..87cfda74
--- /dev/null
+++ b/anfisa_for_friends/templates/users/signup.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block title %}
+ Sign Up
+{% endblock %}
+
+{% block content %}
+ Sign Up
+
+{% endblock %}
diff --git a/anfisa_for_friends/users/__init__.py b/anfisa_for_friends/users/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/anfisa_for_friends/users/admin.py b/anfisa_for_friends/users/admin.py
new file mode 100644
index 00000000..8c38f3f3
--- /dev/null
+++ b/anfisa_for_friends/users/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/anfisa_for_friends/users/apps.py b/anfisa_for_friends/users/apps.py
new file mode 100644
index 00000000..72b14010
--- /dev/null
+++ b/anfisa_for_friends/users/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class UsersConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'users'
diff --git a/anfisa_for_friends/users/forms.py b/anfisa_for_friends/users/forms.py
new file mode 100644
index 00000000..1497be95
--- /dev/null
+++ b/anfisa_for_friends/users/forms.py
@@ -0,0 +1,8 @@
+from django.contrib.auth.forms import UserCreationForm
+from .models import CustomUser
+
+
+class CustomUserCreationForm(UserCreationForm):
+ class Meta(UserCreationForm.Meta):
+ model = CustomUser
+ fields = ('email',)
diff --git a/anfisa_for_friends/users/migrations/0001_initial.py b/anfisa_for_friends/users/migrations/0001_initial.py
new file mode 100644
index 00000000..de8b109a
--- /dev/null
+++ b/anfisa_for_friends/users/migrations/0001_initial.py
@@ -0,0 +1,42 @@
+# Generated by Django 3.2.16 on 2025-09-04 06:17
+
+import django.contrib.auth.models
+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='CustomUser',
+ 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')),
+ ('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, unique=True, verbose_name='email address')),
+ ('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()),
+ ],
+ ),
+ ]
diff --git a/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py b/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py
new file mode 100644
index 00000000..d02af45e
--- /dev/null
+++ b/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2025-09-04 06:34
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterModelManagers(
+ name='customuser',
+ managers=[
+ ],
+ ),
+ ]
diff --git a/anfisa_for_friends/users/migrations/__init__.py b/anfisa_for_friends/users/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/anfisa_for_friends/users/models.py b/anfisa_for_friends/users/models.py
new file mode 100644
index 00000000..dd970979
--- /dev/null
+++ b/anfisa_for_friends/users/models.py
@@ -0,0 +1,48 @@
+from django.contrib.auth.models import AbstractUser, BaseUserManager
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+
+class CustomUserManager(BaseUserManager):
+ """
+ Custom user model manager where email is the unique identifiers
+ for authentication instead of usernames.
+ """
+ def create_user(self, email, password, **extra_fields):
+ """
+ Create and save a User with the given email and password.
+ """
+ if not email:
+ raise ValueError(_('The Email must be set'))
+ email = self.normalize_email(email)
+ user = self.model(email=email, **extra_fields)
+ user.set_password(password)
+ user.save()
+ return user
+
+ def create_superuser(self, email, password, **extra_fields):
+ """
+ Create and save a SuperUser with the given email and password.
+ """
+ extra_fields.setdefault('is_staff', True)
+ extra_fields.setdefault('is_superuser', True)
+ extra_fields.setdefault('is_active', True)
+
+ if extra_fields.get('is_staff') is not True:
+ raise ValueError(_('Superuser must have is_staff=True.'))
+ if extra_fields.get('is_superuser') is not True:
+ raise ValueError(_('Superuser must have is_superuser=True.'))
+ return self.create_user(email, password, **extra_fields)
+
+
+class CustomUser(AbstractUser):
+ username = None
+ email = models.EmailField(_('email address'), unique=True)
+
+ USERNAME_FIELD = 'email'
+ REQUIRED_FIELDS = []
+
+ objects = CustomUserManager()
+
+ def __str__(self):
+ return self.email
diff --git a/anfisa_for_friends/users/tests.py b/anfisa_for_friends/users/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/anfisa_for_friends/users/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/anfisa_for_friends/users/urls.py b/anfisa_for_friends/users/urls.py
new file mode 100644
index 00000000..c4242ec9
--- /dev/null
+++ b/anfisa_for_friends/users/urls.py
@@ -0,0 +1,10 @@
+from django.urls import path
+from . import views
+
+app_name = 'users'
+
+urlpatterns = [
+ path('signup/', views.SignUpView.as_view(), name='signup'),
+ path('login/', views.CustomLoginView.as_view(), name='login'),
+ path('logout/', views.CustomLogoutView.as_view(), name='logout'),
+]
diff --git a/anfisa_for_friends/users/views.py b/anfisa_for_friends/users/views.py
new file mode 100644
index 00000000..e5e1c64f
--- /dev/null
+++ b/anfisa_for_friends/users/views.py
@@ -0,0 +1,21 @@
+from django.views.generic.edit import CreateView
+from django.contrib.auth.views import LoginView, LogoutView
+from django.urls import reverse_lazy
+
+from django.contrib.auth.forms import AuthenticationForm
+from .forms import CustomUserCreationForm
+
+
+class SignUpView(CreateView):
+ form_class = CustomUserCreationForm
+ success_url = reverse_lazy('homepage:index')
+ template_name = 'users/signup.html'
+
+
+class CustomLoginView(LoginView):
+ form_class = AuthenticationForm
+ template_name = 'users/login.html'
+
+
+class CustomLogoutView(LogoutView):
+ next_page = reverse_lazy('homepage:index')