Commit 3d88a1b8 authored by Isataev Adlet's avatar Isataev Adlet

Добавил разрешения для менеджера, который может удалять редактировать и…

Добавил разрешения для менеджера, который может удалять редактировать и создавать мероприятия. Также просматривать список участников. Редактировать свои данные может только собственный пользователь. Добавил функцию участия в мероприятии. Если пользователь не заполнил данные, то не может участвовать. Поработал над стилями. Загрузил фикстуры
parent 8b183733
# Проект Speed Dating
Описание проекта
**Функционал выполнен на фреймворке Django, стили использованы Bootstrap**
*ver 1.0*
*Проект предназначен для создания мероприятий в формате Speed Dating*
\ No newline at end of file
from django import forms from django import forms
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User
from accounts.models import Profile from accounts.models import Profile
class RegistrationForm(UserCreationForm): class RegistrationForm(forms.ModelForm):
class Meta(UserCreationForm.Meta): password = forms.CharField(label="Password", required=True, strip=False, widget=forms.PasswordInput)
fields = ["username", "first_name",
"last_name", "email", "password1", "password2"] password_confirm = forms.CharField(label="Confirm Password", required=True, strip=False, widget=forms.PasswordInput)
email = forms.EmailField(label="Email", required=True, widget=forms.EmailInput)
def clean(self):
clean_data = super().clean()
password = clean_data.get("password")
password_confirm = clean_data.get("password_confirm")
first_name = clean_data.get("first_name")
last_name = clean_data.get("last_name")
if not first_name and not last_name:
raise forms.ValidationError("Enter first name or name")
if password and password_confirm and password != password_confirm:
raise forms.ValidationError("Password are not equal")
return clean_data
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class Meta:
model = User
fields = ["username", "first_name", "last_name", "email", "password", "password_confirm"]
class UserChangeForm(forms.ModelForm): class UserChangeForm(forms.ModelForm):
...@@ -19,6 +44,8 @@ class UserChangeForm(forms.ModelForm): ...@@ -19,6 +44,8 @@ class UserChangeForm(forms.ModelForm):
class ProfileChangeForm(forms.ModelForm): class ProfileChangeForm(forms.ModelForm):
birth_date = forms.DateField(widget=forms.TextInput(attrs={'placeholder': 'YYYY-MM-DD'}))
class Meta: class Meta:
model = Profile model = Profile
exclude = ["user"] exclude = ["user"]
......
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
{% block title %}Login{% endblock %} {% block title %}Login{% endblock %}
{% block content %} {% block content %}
<h1>Вход</h1> <div class="mt-5">
<form action="{% url "login" %}" method="post"> <h1>Вход</h1>
<form action="{% url "login" %}" method="post">
{% csrf_token %} {% csrf_token %}
{% if has_error %} {% if has_error %}
<p>Wrong username or password</p> <p>Wrong username or password</p>
...@@ -13,5 +14,7 @@ ...@@ -13,5 +14,7 @@
<p><input type="password" name="password" placeholder="Password"></p> <p><input type="password" name="password" placeholder="Password"></p>
<input type="hidden" name="next" value="{{ request.GET.next }}"> <input type="hidden" name="next" value="{{ request.GET.next }}">
<button>Войти</button> <button>Войти</button>
</form> </form>
</div>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
{% block title %}Register{% endblock %} {% block title %}Register{% endblock %}
{% block content %} {% block content %}
<form action="{% url "register" %}" method="post"> <div class="mt-5">
<form action="{% url "register" %}" method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button class="btn btn-primary">Регистрация</button> <button class="btn btn-primary">Регистрация</button>
</form> </form>
</div>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -3,22 +3,27 @@ ...@@ -3,22 +3,27 @@
{% block title %}User {{ user_obj.username }}{% endblock %} {% block title %}User {{ user_obj.username }}{% endblock %}
{% block content %} {% block content %}
<h1>Профиль {{ user_obj.username }}</h1> <h1 class="mt-5">Профиль {{ user_obj.username }}</h1>
{% ifequal user user_obj %} {% ifequal user user_obj %}
<p> <div class="mt-3 mb-3">
<a href="{% url "edit_profile" user_obj.pk %}"> <a href="{% url "edit_profile" user_obj.pk %}" class="btn btn-info">
Edit account Edit account
</a> </a>
<a href="{% url "change_password" user_obj.pk %}"> <a href="{% url "change_password" user_obj.pk %}" class="ml-5 btn btn-info">
Change password Change password
</a> </a>
</p> </div>
{% endifequal %} {% endifequal %}
<div>
<p>Username: {{ user_obj.username }}</p> <p>Username: {{ user_obj.username }}</p>
<p>First name: {{ user_obj.first_name }}</p> <p>Имя: {{ user_obj.first_name }}</p>
<p>Last name: {{ user_obj.last_name }}</p> <p>Фамилия: {{ user_obj.last_name }}</p>
<p>Date of birth: {{ user_obj.profile.birth_date }}</p> <p>Дата рождения: {{ user_obj.profile.birth_date }}</p>
<p>Пол: {{ user_obj.profile.gender }}</p>
<p>Номер телефона: {{ user_obj.profile.phone_number }}</p>
<p>Почта: {{ user_obj.email }}</p>
</div>
{% endblock %} {% endblock %}
\ No newline at end of file
from django.conf import settings from django.conf import settings
from django.contrib.auth import login, authenticate, logout, get_user_model, update_session_auth_hash from django.contrib.auth import login, authenticate, logout, get_user_model, update_session_auth_hash
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.urls import reverse from django.urls import reverse
from django.views import View from django.views import View
from django.views.generic import CreateView, DetailView, UpdateView from django.views.generic import CreateView, DetailView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from accounts.forms import RegistrationForm, ProfileChangeForm, UserChangeForm, PasswordChangeForm from accounts.forms import RegistrationForm, ProfileChangeForm, UserChangeForm, PasswordChangeForm
from accounts.models import Profile from accounts.models import Profile
...@@ -49,24 +48,24 @@ class RegisterView(CreateView): ...@@ -49,24 +48,24 @@ class RegisterView(CreateView):
return redirect("index") return redirect("index")
class UserDetailView(DetailView): class UserDetailView(UserPassesTestMixin, DetailView):
model = get_user_model() model = get_user_model()
template_name = "user_detail.html" template_name = "user_detail.html"
context_object_name = "user_obj" context_object_name = "user_obj"
def test_func(self):
return self.request.user.has_perm('accounts.view_profile') or self.request.user == self.get_object()
# class ChangeProfileAccessMixin(UserPassesTestMixin):
# def test_func(self):
# return self.request.user == self.get_object() or \
# self.request.user.is_superuser or self.request.user.groups.filter(name="admins")
class UserChangeView(UserPassesTestMixin, UpdateView):
class UserChangeView(UpdateView):
model = get_user_model() model = get_user_model()
form_class = UserChangeForm form_class = UserChangeForm
template_name = "edit_profile.html" template_name = "edit_profile.html"
context_object_name = "user_obj" context_object_name = "user_obj"
def test_func(self):
return self.request.user == self.get_object()
def get_profile_form(self): def get_profile_form(self):
form_kwargs = {"instance": self.object.profile} form_kwargs = {"instance": self.object.profile}
if self.request.method == "POST": if self.request.method == "POST":
...@@ -105,12 +104,15 @@ class UserChangeView(UpdateView): ...@@ -105,12 +104,15 @@ class UserChangeView(UpdateView):
return reverse("profile", kwargs={"pk": self.object.pk}) return reverse("profile", kwargs={"pk": self.object.pk})
class ChangePasswordView(LoginRequiredMixin, UpdateView): class ChangePasswordView(UserPassesTestMixin, UpdateView):
model = get_user_model() model = get_user_model()
form_class = PasswordChangeForm form_class = PasswordChangeForm
template_name = "change_password.html" template_name = "change_password.html"
context_object_name = "user_obj" context_object_name = "user_obj"
def test_func(self):
return self.request.user == self.get_object()
def form_valid(self, form): def form_valid(self, form):
form.save() form.save()
update_session_auth_hash(self.request, form.instance) update_session_auth_hash(self.request, form.instance)
......
[
{
"model": "auth.group",
"pk": 1,
"fields": {
"name": "manager",
"permissions": [
[
"add_profile",
"accounts",
"profile"
],
[
"change_profile",
"accounts",
"profile"
],
[
"view_profile",
"accounts",
"profile"
],
[
"add_event",
"webapp",
"event"
],
[
"can_see_all_user_in_event",
"webapp",
"event"
],
[
"change_event",
"webapp",
"event"
],
[
"delete_event",
"webapp",
"event"
],
[
"view_event",
"webapp",
"event"
]
]
}
},
{
"model": "auth.user",
"pk": 1,
"fields": {
"password": "pbkdf2_sha256$260000$DaJ5zHnTAllGmsZSKlgIO1$eG44fWwJDAJAkBFvVhfvhvK/8iBfu6Xvrk8I8/BaosM=",
"last_login": "2021-11-04T03:27:25.278Z",
"is_superuser": true,
"username": "admin",
"first_name": "",
"last_name": "",
"email": "admin@admin.com",
"is_staff": true,
"is_active": true,
"date_joined": "2021-11-03T08:31:01Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 2,
"fields": {
"password": "pbkdf2_sha256$260000$Sw1oq0NKk3kxoY9zSnYqSB$KYhLCOhjFDGwIBf0rPe0wE6F4D3zhI+CPyoTT4mcZ88=",
"last_login": "2021-11-03T17:26:40.907Z",
"is_superuser": false,
"username": "Test",
"first_name": "Test",
"last_name": "Test",
"email": "Test@test.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-03T12:16:31Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 3,
"fields": {
"password": "pbkdf2_sha256$260000$zeJmltTHerV3ZydTixRCDV$e+i0jCzRnxCUM5Vb0zvvAyvDM9z18LNWE3plzxBZChU=",
"last_login": "2021-11-03T17:58:03.525Z",
"is_superuser": false,
"username": "Test2",
"first_name": "Test2",
"last_name": "Test2",
"email": "test2@test2.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-03T12:45:29.642Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 4,
"fields": {
"password": "pbkdf2_sha256$260000$0PfdUXrMYDYLxeONfEJgJS$qphlddjCVTBQrRSeeMX7BuoUpIkI2yn7XtD3aw0IlN0=",
"last_login": null,
"is_superuser": false,
"username": "Test3",
"first_name": "Test3",
"last_name": "Test3",
"email": "Test3@test3.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-03T12:49:26.208Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 5,
"fields": {
"password": "pbkdf2_sha256$260000$hSKpHboRK9JlUKZh6Qyp0u$8XHOJdbh93EbeD7jFhQZY604XcHbJXDNYQtGKdlVdb0=",
"last_login": "2021-11-03T17:58:35.885Z",
"is_superuser": false,
"username": "Test4",
"first_name": "Test4",
"last_name": "Test4",
"email": "",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-03T12:51:46.480Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 6,
"fields": {
"password": "pbkdf2_sha256$260000$NQJFAPs1xq719ylgD5ct73$qt42f8c0etHixAt2tzDAmOLDdkk1TbcH5YZt1MsRYbY=",
"last_login": "2021-11-04T02:07:26.850Z",
"is_superuser": false,
"username": "Egor",
"first_name": "Егор",
"last_name": "Шифудинский",
"email": "sharamurz@icloud.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-04T02:03:39.043Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 7,
"fields": {
"password": "pbkdf2_sha256$260000$RwG7EKb7H66K6BmRwsgMoZ$Gq0vp51BqtcWlynyEk5bSh+8o3Mw6UtZgvTZ58Enn0k=",
"last_login": "2021-11-04T03:25:06Z",
"is_superuser": false,
"username": "manager",
"first_name": "manager",
"last_name": "manager",
"email": "manager@manager.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-04T02:10:20Z",
"groups": [
[
"manager"
]
],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 8,
"fields": {
"password": "pbkdf2_sha256$260000$8bHetuOwqPOt7cIyzSulOT$YUTByWs3E8Ey6xj7AM0noeZJiPCu+tTvHxTmcs8jcuU=",
"last_login": "2021-11-04T02:51:15.284Z",
"is_superuser": false,
"username": "adam",
"first_name": "Адам",
"last_name": "Смит",
"email": "Adam@adam.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-04T02:51:15.149Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 9,
"fields": {
"password": "pbkdf2_sha256$260000$PADX1FBWDSEKoU1BcAYR3J$UBHY5y3W7A2r89aNjXK/yptZglaeDiEtJf8Sz1M0s8w=",
"last_login": "2021-11-04T03:24:50.322Z",
"is_superuser": false,
"username": "ela",
"first_name": "Елизавета",
"last_name": "Вторая",
"email": "Ela@ela.com",
"is_staff": false,
"is_active": true,
"date_joined": "2021-11-04T03:17:56.211Z",
"groups": [],
"user_permissions": []
}
}
]
[
{
"model": "webapp.restaurant",
"pk": 1,
"fields": {
"name": "CheChil Pub",
"address": "Толе Би, 236",
"photo": "photo/XXL.jpg",
"description": "КУХНЯ: Европейская, Итальянская, Мексиканская\r\nПАРКОВКА: Неохраняемая бесплатная\r\nПРИНИМАЕМ К ОПЛАТЕ: Наличные, Оплата картой\r\nСЕТЬ ЗАВЕДЕНИЙ: CHECHIL PUB (5 В СЕТИ)\r\nОСОБЕННОСТИ: WiFi, Фоновая музыка, Живая музыка, Танцпол, VIP-зал, На вынос, Шоу-программа, Кальян"
}
},
{
"model": "webapp.restaurant",
"pk": 2,
"fields": {
"name": "Pinta",
"address": "Абая, 185",
"photo": "photo/pi.jpg",
"description": "КУХНЯ: Европейская, Американская, Гриль меню\r\nПАРКОВКА: Охраняемая бесплатная\r\nПРИНИМАЕМ К ОПЛАТЕ: Наличные, Оплата картой\r\nОСОБЕННОСТИ: WiFi, Бизнес-ланч, Фоновая музыка, Танцпол, Есть летняя терраса\r\nБИЗНЕС-ЛАНЧ: 800 тенге С 12:00 до 16:00\r\nСАЙТ: www.pinta.kz"
}
},
{
"model": "webapp.event",
"pk": 10,
"fields": {
"place": 2,
"date": "2021-11-30T13:00:00Z",
"users": [
1,
7,
8,
9
]
}
},
{
"model": "webapp.event",
"pk": 11,
"fields": {
"place": 1,
"date": "2021-12-20T15:00:00Z",
"users": []
}
}
]
[
{
"model": "accounts.gender",
"pk": 1,
"fields": {
"name": "Мужской"
}
},
{
"model": "accounts.gender",
"pk": 2,
"fields": {
"name": "Женский"
}
},
{
"model": "accounts.profile",
"pk": 1,
"fields": {
"user": 1,
"birth_date": "2021-02-01",
"phone_number": "+7705",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 2,
"fields": {
"user": 2,
"birth_date": "2021-11-03",
"phone_number": "+77777777777999",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 3,
"fields": {
"user": 5,
"birth_date": "2020-10-10",
"phone_number": "456456456456",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 4,
"fields": {
"user": 6,
"birth_date": "1992-06-06",
"phone_number": "+78789",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 5,
"fields": {
"user": 7,
"birth_date": "1992-06-06",
"phone_number": "123412341234",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 6,
"fields": {
"user": 8,
"birth_date": "1992-06-06",
"phone_number": "87019500265",
"gender": 1
}
},
{
"model": "accounts.profile",
"pk": 7,
"fields": {
"user": 9,
"birth_date": "1992-06-06",
"phone_number": "87019500265",
"gender": 2
}
}
]
...@@ -108,7 +108,7 @@ AUTH_PASSWORD_VALIDATORS = [ ...@@ -108,7 +108,7 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC' TIME_ZONE = 'Asia/Dhaka'
USE_I18N = True USE_I18N = True
......
...@@ -32,6 +32,8 @@ urlpatterns = [ ...@@ -32,6 +32,8 @@ urlpatterns = [
path("events/", webapp_views.EventView.as_view(), name="list_events"), path("events/", webapp_views.EventView.as_view(), name="list_events"),
path("events/create/", webapp_views.EventCreateView.as_view(), name="create_events"), path("events/create/", webapp_views.EventCreateView.as_view(), name="create_events"),
path("events/<int:pk>/", webapp_views.EventDetailView.as_view(), name="detail_events"), path("events/<int:pk>/", webapp_views.EventDetailView.as_view(), name="detail_events"),
path("events/<int:pk>/add-user/", webapp_views.ParticipateView.as_view(), name="add_user"),
path("events/<int:pk>/edit/", webapp_views.EventUpdateView.as_view(), name="update_events"), path("events/<int:pk>/edit/", webapp_views.EventUpdateView.as_view(), name="update_events"),
path("events/<int:pk>/delete/", webapp_views.EventDeleteView.as_view(), name="delete_events") path("events/<int:pk>/delete/", webapp_views.EventDeleteView.as_view(), name="delete_events"),
path("events/<int:pk>/view-all-users", webapp_views.ParticipateListInEventView.as_view(), name="list_users_in_event")
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
...@@ -3,7 +3,7 @@ from webapp.models import Event ...@@ -3,7 +3,7 @@ from webapp.models import Event
class EventForm(forms.ModelForm): class EventForm(forms.ModelForm):
date = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'YYYY-MM-DD HH-MM-SS'})) date = forms.DateTimeField(widget=forms.TextInput(attrs={'placeholder': 'YYYY-MM-DD HH-MM-SS'}))
class Meta: class Meta:
model = Event model = Event
......
# Generated by Django 3.2.9 on 2021-11-03 13:25
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('webapp', '0002_restaurant_photo'),
]
operations = [
migrations.AddField(
model_name='event',
name='users',
field=models.ManyToManyField(blank=True, related_name='participants', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.2.9 on 2021-11-03 17:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('webapp', '0003_event_users'),
]
operations = [
migrations.AlterModelOptions(
name='event',
options={'permissions': [('can_see_all_user_in_event', 'Can see all user in event')]},
),
]
from django.contrib.auth.models import User
from django.db import models from django.db import models
...@@ -20,8 +21,15 @@ class Event(models.Model): ...@@ -20,8 +21,15 @@ class Event(models.Model):
date = models.DateTimeField(verbose_name="Дата") date = models.DateTimeField(verbose_name="Дата")
users = models.ManyToManyField(User, blank=True, related_name="participants")
def __str__(self): def __str__(self):
return f'{self.place} - {self.date}' return f'{self.place} - {self.date}'
class Meta:
permissions = [
("can_see_all_user_in_event", "Can see all user in event"),
]
{% extends "base.html" %}
{% block title %}Список участников{% endblock %}
{% block content %}
<h1>Список участников</h1>
<p>
{% for u in event.users.all %}
<a href="{% url "profile" event.pk %}">{{ u }}</a>
<br>
{% endfor %}
</p>
<a href="{% url "detail_events" event.pk %}" class="mt-3 btn btn-info">Назад</a>
{% endblock %}
\ No newline at end of file
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="{% url 'index' %}">Speed Dating</a> <a class="navbar-brand" href="{% url 'index' %}">Speed Dating</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
...@@ -22,9 +22,11 @@ ...@@ -22,9 +22,11 @@
<li class="nav-item active"> <li class="nav-item active">
<a class="nav-link" href="{% url 'list_events' %}">Мероприятия<span class="sr-only">(current)</span></a> <a class="nav-link" href="{% url 'list_events' %}">Мероприятия<span class="sr-only">(current)</span></a>
</li> </li>
{% if perms.webapp.add_event %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'create_events' %}">Создать мероприятие</a> <a class="nav-link" href="{% url 'create_events' %}">Создать мероприятие</a>
</li> </li>
{% endif %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<li class="nav-item"> <li class="nav-item">
<form action="{% url "logout" %}" method="post"> <form action="{% url "logout" %}" method="post">
......
...@@ -3,11 +3,41 @@ ...@@ -3,11 +3,41 @@
{% block title %}Events{% endblock %} {% block title %}Events{% endblock %}
{% block content %} {% block content %}
{{ event.place.name }} <div class="mt-5">
<img src="{{ event.place.photo.url }}" alt=""> <h2>{{ event.place.name }}</h2>
{{ event.place.address }} <p>{{ event.place.address }}</p>
<div class="d-flex">
<div class="col">
<img src="{{ event.place.photo.url }}" height="400px" width="600px" alt="">
</div>
<div class="col">
{{ event.place.description }} {{ event.place.description }}
{{ event.date }} </div>
<a href="{% url "update_events" event.pk %}">Редактировать</a> </div>
<a href="{% url "delete_events" event.pk %}">Удалить</a> <p class="mt-5">{{ event.date|date:"M d Y - h:m" }}</p>
{% if perms.webapp.change_event %}
<a href="{% url "update_events" event.pk %}" class="btn btn-info">Редактировать</a>
{% endif %}
{% if perms.webapp.delete_event %}
<a href="{% url "delete_events" event.pk %}" class="ml-5 btn btn-info">Удалить</a>
{% endif %}
<div class="mt-3">
{% if user in event.users.all %}
<p>Вы уже участвуете в данном мероприятии</p>
{% else %}
{% if user.profile.gender and user.profile.birth_date and user.profile.phone_number %}
<a href="{% url "add_user" event.pk %}" class="btn btn-info mb-3">Участвовать</a>
{% else %}
<p>Вам необходимо заполнить Ваш профиль. Нажмите на Ваш логин, который размещен сверху</p>
{% endif %}
{% endif %}
{% if perms.webapp.can_see_all_user_in_event %}
<a href="{% url "list_users_in_event" event.pk %}" class="mb-3 btn btn-info">Посмотреть список участников</a>
{% endif %}
</div>
<a href="{% url "list_events" %}" class="btn btn-info">Назад</a>
</div>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -3,10 +3,13 @@ ...@@ -3,10 +3,13 @@
{% block title %}Events{% endblock %} {% block title %}Events{% endblock %}
{% block content %} {% block content %}
<h1 class="mt-5">Список мероприятий</h1>
{% for event in events %} {% for event in events %}
<a href="{% url 'detail_events' event.pk %}">{{ event.place }}</a> <div class="mt-5">
{{ event.date }} <a href="{% url 'detail_events' event.pk %}">{{ event.place }} - {{ event.place.address }}</a>
<br>
<p>{{ event.date|date:"M d Y - h:m" }}</p>
<hr> <hr>
</div>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
{% block title %}Home{% endblock %} {% block title %}Home{% endblock %}
{% block content %} {% block content %}
<div id="carouselExampleSlidesOnly" class="carousel slide" data-ride="carousel"> <div id="carouselExampleSlidesOnly" class="carousel slide mt-5" data-ride="carousel">
<div class="carousel-inner"> <div class="carousel-inner">
<div class="carousel-item active"> <div class="carousel-item active">
<img src="https://blogs.egu.eu/network/water-underground/files/2017/05/1-2-1400x800.jpg" <img src="https://blogs.egu.eu/network/water-underground/files/2017/05/1-2-1400x800.jpg"
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
</div> </div>
</div> </div>
<div> <div>
<h1>Что такое Speed Dating</h1> <h1 class="mt-5">Что такое Speed Dating?</h1>
<p> <p class="mt-5">
Участников, как правило, подбирают по равноценным социальным группам. Некоторые организаторы вводят Участников, как правило, подбирают по равноценным социальным группам. Некоторые организаторы вводят
возрастные ограничения. На классической спид-дейтинг-вечеринке каждый участник будет иметь 10–15 возрастные ограничения. На классической спид-дейтинг-вечеринке каждый участник будет иметь 10–15
встреч наедине с представителями противоположного пола. Девушки размещаются за столиками с номерами. встреч наедине с представителями противоположного пола. Девушки размещаются за столиками с номерами.
......
{% extends "base.html" %}
{% block title %}Участие {{ event.place }}{% endblock %}
{% block content %}
<h2>Участвовать в мероприятии "{{ event.place }}"</h2>
<a href="{% url "list_events" %}">Cancel</a>
<form action="{% url "add_user" event.pk %}" method="post">
{% csrf_token %}
<button>Yes</button>
</form>
{% endblock %}
\ No newline at end of file
from django.shortcuts import render from django.shortcuts import render, redirect
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.views import View from django.views import View
from django.views.generic import CreateView, DetailView, UpdateView, DeleteView from django.views.generic import CreateView, DetailView, UpdateView, DeleteView
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
import datetime
from webapp.forms import EventForm from webapp.forms import EventForm
from webapp.models import Event from webapp.models import Event
...@@ -14,14 +16,21 @@ def index_view(request): ...@@ -14,14 +16,21 @@ def index_view(request):
class EventView(View): class EventView(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
events = Event.objects.all() events = Event.objects.all()
# now = datetime.datetime.now(datetime.timezone.utc)
# for event in events:
# print(event.date)
# print(now)
# if event.date < now:
# event.delete()
context = {"events": events} context = {"events": events}
return render(request, "event_list.html", context) return render(request, "event_list.html", context)
class EventCreateView(CreateView): class EventCreateView(PermissionRequiredMixin, CreateView):
model = Event model = Event
template_name = "event_create.html" template_name = "event_create.html"
form_class = EventForm form_class = EventForm
permission_required = "webapp.add_event"
def get_success_url(self): def get_success_url(self):
return reverse("detail_events", kwargs={"pk": self.object.pk}) return reverse("detail_events", kwargs={"pk": self.object.pk})
...@@ -33,19 +42,42 @@ class EventDetailView(DetailView): ...@@ -33,19 +42,42 @@ class EventDetailView(DetailView):
context_object_name = "event" context_object_name = "event"
class EventUpdateView(UpdateView): class EventUpdateView(PermissionRequiredMixin, UpdateView):
model = Event model = Event
template_name = "event_update.html" template_name = "event_update.html"
form_class = EventForm form_class = EventForm
permission_required = "webapp.change_event"
def get_success_url(self): def get_success_url(self):
return reverse("detail_events", kwargs={"pk": self.object.pk}) return reverse("detail_events", kwargs={"pk": self.object.pk})
class EventDeleteView(DeleteView): class EventDeleteView(PermissionRequiredMixin, DeleteView):
model = Event model = Event
template_name = "event_delete.html" template_name = "event_delete.html"
success_url = reverse_lazy("list_events") success_url = reverse_lazy("list_events")
permission_required = "webapp.delete_event"
class ParticipateView(UserPassesTestMixin, UpdateView):
model = Event
template_name = "participate.html"
fields = ["users"]
def test_func(self):
return self.request.user.profile.birth_date and self.request.user.profile.phone_number and \
self.request.user.profile.gender
def post(self, request, *args, **kwargs):
participate = self.get_object()
participate.users.add(self.request.user)
return redirect('list_events')
class ParticipateListInEventView(PermissionRequiredMixin, DetailView):
model = Event
template_name = "all_user_in_event.html"
permission_required = "webapp.can_see_all_user_in_event"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment