Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change_2 #7

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions acme_project/acme_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

DEBUG = True

ALLOWED_HOSTS = []
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
# Когда проект будет опубликован и станет доступен для пользователей,
# в этот список нужно будет добавить адреса домена, где он будет размещён,
# например 'acme.not' и 'www.acme.not'
]

INSTALLED_APPS = [
'django.contrib.admin',
Expand All @@ -17,6 +23,9 @@
'django.contrib.staticfiles',
'birthday.apps.BirthdayConfig',
'pages.apps.PagesConfig',
'core.apps.CoreConfig',
'django_bootstrap5',
'debug_toolbar',
]

MIDDLEWARE = [
Expand All @@ -27,6 +36,7 @@
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
]

ROOT_URLCONF = 'acme_project.urls'
Expand Down Expand Up @@ -79,10 +89,27 @@

USE_I18N = True

USE_L10N = True
USE_L10N = False

USE_TZ = True

STATIC_URL = '/static/'

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

MEDIA_ROOT = BASE_DIR / 'media'

# Подключаем бэкенд filebased.EmailBackend:
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
# Указываем директорию, в которую будут сохраняться файлы писем:
EMAIL_FILE_PATH = BASE_DIR / 'sent_emails'

LOGIN_REDIRECT_URL = 'pages:homepage'

LOGIN_URL = 'login'

CSRF_FAILURE_VIEW = 'core.views.csrf_failure'

INTERNAL_IPS = [
'127.0.0.1',
]
30 changes: 29 additions & 1 deletion acme_project/acme_project/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
# Импорт классов для регистрации пользователя.
from django.contrib.auth.forms import UserCreationForm
from django.views.generic.edit import CreateView
# Импортируем настройки проекта.
from django.conf import settings
# Импортируем функцию, позволяющую серверу разработки отдавать файлы.
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
from django.urls import include, path, reverse_lazy

handler404 = 'core.views.page_not_found'
handler403 = 'core.views.csrf_failure'


urlpatterns = [
path('', include('pages.urls')),
path('admin/', admin.site.urls),
path('birthday/', include('birthday.urls')),
# Подключаем urls.py приложения для работы с пользователями.
path('auth/', include('django.contrib.auth.urls')),
path(
'auth/registration/',
CreateView.as_view(
template_name='registration/registration_form.html',
form_class=UserCreationForm,
success_url=reverse_lazy('pages:homepage'),
),
name='registration',
),
]
if settings.DEBUG:
import debug_toolbar
# Добавить к списку urlpatterns список адресов из приложения debug_toolbar:
urlpatterns += (path('__debug__/', include(debug_toolbar.urls)),)
# В конце добавляем к списку вызов функции static.
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
7 changes: 7 additions & 0 deletions acme_project/birthday/admin.py
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
from django.contrib import admin

from .models import Birthday, Tag, Congratulation


admin.site.register(Birthday)
admin.site.register(Tag)
admin.site.register(Congratulation)
60 changes: 60 additions & 0 deletions acme_project/birthday/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from django import forms
# Импортируем класс ошибки валидации
from django.core.exceptions import ValidationError
# Импорт функции для отправки почты.
from django.core.mail import send_mail

from .models import Birthday, Congratulation

# Множество с именами участников Ливерпульской четвёрки.
BEATLES = {'Джон Леннон', 'Пол Маккартни', 'Джордж Харрисон', 'Ринго Старр'}


class BirthdayForm(forms.ModelForm):

# Все настройки задаём в подклассе Meta.
class Meta:
# Указываем модель, на основе которой должна строиться форма.
model = Birthday
# Указываем, что надо отобразить все поля кроме автора.
exclude = ('author',)
# Все настройки задаём в подклассе Meta.
widgets = {
'birthday': forms.DateInput(attrs={'type': 'date'})
}

def clean_first_name(self):
# Получаем значение имени из словаря очищенных данных.
first_name = self.cleaned_data['first_name']
# Разбиваем полученную строку по пробелам
# и возвращаем только первое имя.
return first_name.split()[0]

def clean(self):
# Вызов родительского метода clean для constraints в модели Birthday:
super().clean()
# А это уже код текущего метода clean:
# Получаем имя и фамилию из очищенных полей формы.
first_name = self.cleaned_data['first_name']
last_name = self.cleaned_data['last_name']
# Проверяем вхождение сочетания имени и фамилии во множество имён.
if f'{first_name} {last_name}' in BEATLES:
# Отправляем письмо, если кто-то представляется
# именем одного из участников Beatles.
send_mail(
subject='Another Beatles member',
message=f'{first_name} {last_name} пытался опубликовать запись!',
from_email='[email protected]',
recipient_list=['[email protected]'],
fail_silently=True,
)
raise ValidationError(
'Мы тоже любим Битлз, но введите, пожалуйста, настоящее имя!'
)


class CongratulationForm(forms.ModelForm):

class Meta:
model = Congratulation
fields = ('text',)
23 changes: 23 additions & 0 deletions acme_project/birthday/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.16 on 2024-10-23 06:30

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Birthday',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first_name', models.CharField(max_length=20, verbose_name='Имя')),
('last_name', models.CharField(blank=True, help_text='Необязательное поле', max_length=20, verbose_name='Фамилия')),
('birthday', models.DateField(verbose_name='Дата рождения')),
],
),
]
28 changes: 28 additions & 0 deletions acme_project/birthday/migrations/0002_auto_20241028_1714.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.2.16 on 2024-10-28 10:14

import birthday.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('birthday', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='birthday',
name='image',
field=models.ImageField(blank=True, upload_to='birthdays_images', verbose_name='Фото'),
),
migrations.AlterField(
model_name='birthday',
name='birthday',
field=models.DateField(validators=[birthday.validators.real_age], verbose_name='Дата рождения'),
),
migrations.AddConstraint(
model_name='birthday',
constraint=models.UniqueConstraint(fields=('first_name', 'last_name', 'birthday'), name='Unique person constraint'),
),
]
21 changes: 21 additions & 0 deletions acme_project/birthday/migrations/0003_birthday_author.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.2.16 on 2024-11-03 05:15

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('birthday', '0002_auto_20241028_1714'),
]

operations = [
migrations.AddField(
model_name='birthday',
name='author',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Автор записи'),
),
]
29 changes: 29 additions & 0 deletions acme_project/birthday/migrations/0004_congratulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 3.2.16 on 2024-11-03 15:53

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('birthday', '0003_birthday_author'),
]

operations = [
migrations.CreateModel(
name='Congratulation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField(verbose_name='Текст поздравления')),
('created_at', models.DateTimeField(auto_now_add=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('birthday', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='congratulations', to='birthday.birthday')),
],
options={
'ordering': ('created_at',),
},
),
]
25 changes: 25 additions & 0 deletions acme_project/birthday/migrations/0005_auto_20241104_1924.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.2.16 on 2024-11-04 12:24

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('birthday', '0004_congratulation'),
]

operations = [
migrations.CreateModel(
name='Tag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tag', models.CharField(max_length=20, verbose_name='Тег')),
],
),
migrations.AddField(
model_name='birthday',
name='tags',
field=models.ManyToManyField(blank=True, help_text='Удерживайте Ctrl для выбора нескольких вариантов', to='birthday.Tag', verbose_name='Теги'),
),
]
61 changes: 61 additions & 0 deletions acme_project/birthday/models.py
Original file line number Diff line number Diff line change
@@ -1 +1,62 @@
from django.db import models
# Импортируем функцию reverse() для получения ссылки на объект.
from django.urls import reverse
from django.contrib.auth import get_user_model

# Импортируется функция-валидатор.
from .validators import real_age

# Да, именно так всегда и ссылаемся на модель пользователя!
User = get_user_model()


class Tag(models.Model):
tag = models.CharField('Тег', max_length=20)

# Переопределяем метод:
def __str__(self):
return self.tag


class Birthday(models.Model):
first_name = models.CharField('Имя', max_length=20)
last_name = models.CharField(
'Фамилия', blank=True, help_text='Необязательное поле', max_length=20
)
birthday = models.DateField('Дата рождения', validators=(real_age,))
image = models.ImageField('Фото', upload_to='birthdays_images', blank=True)
author = models.ForeignKey(
User, verbose_name='Автор записи', on_delete=models.CASCADE, null=True
)
tags = models.ManyToManyField(
Tag,
verbose_name='Теги',
blank=True,
help_text='Удерживайте Ctrl для выбора нескольких вариантов'
)

class Meta:
constraints = (
models.UniqueConstraint(
fields=('first_name', 'last_name', 'birthday'),
name='Unique person constraint',
),
)

def get_absolute_url(self):
# С помощью функции reverse() возвращаем URL объекта.
return reverse('birthday:detail', kwargs={'pk': self.pk})


class Congratulation(models.Model):
text = models.TextField('Текст поздравления')
birthday = models.ForeignKey(
Birthday,
on_delete=models.CASCADE,
related_name='congratulations',
)
created_at = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)

class Meta:
ordering = ('created_at',)
8 changes: 7 additions & 1 deletion acme_project/birthday/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@
app_name = 'birthday'

urlpatterns = [
path('', views.birthday, name='create'),
path('login_only/', views.simple_view),
path('', views.BirthdayCreateView.as_view(), name='create'),
path('list/', views.BirthdayListView.as_view(), name='list'),
path('<int:pk>/', views.BirthdayDetailView.as_view(), name='detail'),
path('<int:pk>/edit/', views.BirthdayUpdateView.as_view(), name='edit'),
path('<int:pk>/comment/', views.add_comment, name='add_comment'),
path('<int:pk>/delete/', views.BirthdayDeleteView.as_view(), name='delete')
]
Loading