Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
ap-11_django
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Давид Ли
ap-11_django
Commits
7e1bde5a
Commit
7e1bde5a
authored
Jul 31, 2023
by
Давид Ли
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lesson 55
parent
06ec603a
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
369 additions
and
65 deletions
+369
-65
.DS_Store
.DS_Store
+0
-0
admin.py
accounts/admin.py
+13
-2
forms.py
accounts/forms.py
+69
-2
0002_profile.py
accounts/migrations/0002_profile.py
+28
-0
0003_auto_20230731_1645.py
accounts/migrations/0003_auto_20230731_1645.py
+21
-0
models.py
accounts/models.py
+20
-1
change_password.html
accounts/templates/user/change_password.html
+16
-0
detail.html
accounts/templates/user/detail.html
+24
-0
update.html
accounts/templates/user/update.html
+18
-0
urls.py
accounts/urls.py
+4
-1
views.py
accounts/views.py
+93
-4
settings.py
core/settings.py
+3
-3
users_dump.json
fixtures/users_dump.json
+1
-1
.DS_Store
media/.DS_Store
+0
-0
capibara.jpg
media/avatars/capibara.jpg
+0
-0
capibara_CHIsGVx.jpg
media/avatars/capibara_CHIsGVx.jpg
+0
-0
reqs.txt
reqs.txt
+15
-0
article_detail.html
web/templates/article/article_detail.html
+1
-1
delete.html
web/templates/article/delete.html
+2
-2
index.html
web/templates/article/index.html
+1
-33
base.html
web/templates/base.html
+4
-4
article_list.html
web/templates/partial/article_list.html
+24
-0
form.html
web/templates/partial/form.html
+3
-2
urls.py
web/urls.py
+3
-3
article.py
web/views/article.py
+3
-3
comment.py
web/views/comment.py
+3
-3
No files found.
.DS_Store
0 → 100644
View file @
7e1bde5a
File added
accounts/admin.py
View file @
7e1bde5a
from
django.contrib
import
admin
from
django.contrib.auth.admin
import
UserAdmin
from
accounts.models
import
User
from
accounts.models
import
User
,
Profile
# Register your models here.
admin
.
site
.
register
(
User
)
class
ProfileInline
(
admin
.
StackedInline
):
model
=
Profile
fields
=
[
'birth_date'
,
'avatar'
]
class
UserProfileAdmin
(
UserAdmin
):
inlines
=
[
ProfileInline
]
admin
.
site
.
register
(
User
,
UserProfileAdmin
)
accounts/forms.py
View file @
7e1bde5a
from
django
import
forms
from
django.contrib.auth.forms
import
AuthenticationForm
,
UserCreationForm
from
django.contrib.auth
import
password_validation
from
django.contrib.auth
import
password_validation
,
get_user_model
from
accounts.models
import
User
from
accounts.models
import
User
,
Profile
class
LoginForm
(
AuthenticationForm
):
...
...
@@ -60,3 +60,70 @@ class RegisterForm(UserCreationForm):
'last_name'
:
forms
.
TextInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
'email'
:
forms
.
EmailInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
}
class
UserUpdateForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
get_user_model
()
fields
=
[
'first_name'
,
'last_name'
,
'email'
]
labels
=
{
'first_name'
:
'Имя'
,
'last_name'
:
'Фамилия'
,
'email'
:
'Почта'
}
widgets
=
{
'first_name'
:
forms
.
TextInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
'last_name'
:
forms
.
TextInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
'email'
:
forms
.
EmailInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
}
class
ProfileUpdateForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Profile
exclude
=
[
'user'
]
widgets
=
{
'birth_date'
:
forms
.
SelectDateWidget
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
'avatar'
:
forms
.
ClearableFileInput
(
attrs
=
{
'class'
:
'form-control mb-3'
}),
}
class
PasswordChangeForm
(
forms
.
ModelForm
):
old_password
=
forms
.
CharField
(
label
=
'Old password'
,
strip
=
False
,
widget
=
forms
.
PasswordInput
(
attrs
=
{
'class'
:
'form-control mb-3'
})
)
password
=
forms
.
CharField
(
label
=
'New password'
,
strip
=
False
,
widget
=
forms
.
PasswordInput
(
attrs
=
{
'class'
:
'form-control mb-3'
})
)
password_confirm
=
forms
.
CharField
(
label
=
'Confirm password'
,
strip
=
False
,
widget
=
forms
.
PasswordInput
(
attrs
=
{
'class'
:
'form-control mb-3'
})
)
def
clean_password_confirm
(
self
):
password
=
self
.
cleaned_data
.
get
(
'password'
)
password_confirm
=
self
.
cleaned_data
.
get
(
'password_confirm'
)
if
password
and
password_confirm
and
password_confirm
==
password
:
return
password_confirm
raise
forms
.
ValidationError
(
'Passwords not match or missed'
)
def
clean_old_password
(
self
):
old_password
=
self
.
cleaned_data
.
get
(
'old_password'
)
if
not
self
.
instance
.
check_password
(
old_password
):
raise
forms
.
ValidationError
(
'Incorrect old password'
)
return
old_password
def
save
(
self
,
commit
=
True
):
user
=
self
.
instance
user
.
set_password
(
self
.
cleaned_data
.
get
(
'password'
))
if
commit
:
user
.
save
()
return
user
class
Meta
:
model
=
get_user_model
()
fields
=
[
'old_password'
,
'password'
,
'password_confirm'
]
accounts/migrations/0002_profile.py
0 → 100644
View file @
7e1bde5a
# Generated by Django 3.2.19 on 2023-07-31 10:12
from
django.conf
import
settings
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'accounts'
,
'0001_initial'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Profile'
,
fields
=
[
(
'id'
,
models
.
BigAutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'birth_date'
,
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
verbose_name
=
'Дата рождения'
)),
(
'avatar'
,
models
.
ImageField
(
blank
=
True
,
null
=
True
,
upload_to
=
'avatars'
,
verbose_name
=
'Аватар'
)),
(
'user'
,
models
.
OneToOneField
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
related_name
=
'profile'
,
to
=
settings
.
AUTH_USER_MODEL
,
verbose_name
=
'Пользователь'
)),
],
options
=
{
'verbose_name'
:
'Профиль'
,
'verbose_name_plural'
:
'Профили'
,
},
),
]
accounts/migrations/0003_auto_20230731_1645.py
0 → 100644
View file @
7e1bde5a
# Generated by Django 3.2.19 on 2023-07-31 10:45
from
django.db
import
migrations
def
create_profiles
(
apps
,
schema_editor
):
User
=
apps
.
get_model
(
'accounts'
,
'User'
)
Profile
=
apps
.
get_model
(
'accounts'
,
'Profile'
)
for
user
in
User
.
objects
.
filter
(
profile
=
None
):
Profile
.
objects
.
create
(
user
=
user
)
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'accounts'
,
'0002_profile'
),
]
operations
=
[
migrations
.
RunPython
(
create_profiles
,
migrations
.
RunPython
.
noop
)
]
accounts/models.py
View file @
7e1bde5a
from
django.contrib.auth.models
import
AbstractUser
from
django.db
import
models
from
django.contrib.auth
import
get_user_model
class
User
(
AbstractUser
):
pass
class
Profile
(
models
.
Model
):
user
=
models
.
OneToOneField
(
get_user_model
(),
related_name
=
'profile'
,
on_delete
=
models
.
CASCADE
,
verbose_name
=
'Пользователь'
)
birth_date
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
'Дата рождения'
)
avatar
=
models
.
ImageField
(
null
=
True
,
blank
=
True
,
upload_to
=
'avatars'
,
verbose_name
=
'Аватар'
)
def
__str__
(
self
):
return
self
.
user
.
username
+
"'s Profile"
class
Meta
:
verbose_name
=
'Профиль'
verbose_name_plural
=
'Профили'
accounts/templates/user/change_password.html
0 → 100644
View file @
7e1bde5a
{% extends 'base.html' %}
{% block title %}
<h1>
Смена пароля
</h1>
{% endblock %}
{% block content %}
{% url "accounts:password_change" user_obj.pk as action_url %}
<form
action=
"{{ action_url }}"
method=
"post"
>
{% csrf_token %}
{% include 'partial/form.html' with button_text='Change' %}
</form>
{% endblock %}
\ No newline at end of file
accounts/templates/user/detail.html
0 → 100644
View file @
7e1bde5a
{% extends 'base.html' %}
{% block title %}
<h1
class=
"my-4"
>
Cabinet
</h1>
{% endblock %}
{% block content %}
<h1>
Личная страница пользователя {{ user.first_name }} {{ user.last_name }}
</h1>
{% if user.profile.avatar %}
<img
src=
"{{ user.profile.avatar.url }}"
width=
"250"
height=
"250"
alt=
"user avatar"
>
{% endif %}
<p>
Имя пользователя: {{ user.username }}
</p>
<p>
Дата рождения: {{ user.profile.birth_date|date:'d.m.Y' }}
</p>
<p>
Почта: {{ user.email }}
</p>
<a
href=
"{% url 'user_update' user.id %}"
class=
"btn btn-primary mb-3"
>
Update
</a>
<a
href=
"{% url 'user_change_pass' user.id %}"
class=
"btn btn-primary mb-3"
>
Change Password
</a>
<h2>
Статьи автора
</h2>
{% include 'partial/article_list.html' %}
{% endblock %}
accounts/templates/user/update.html
0 → 100644
View file @
7e1bde5a
{% extends 'base.html' %}
{% block content %}
<h1>
Поменять личные данные
</h1>
<form
action=
"{% url 'user_update' user_obj.id %}"
method=
"post"
enctype=
"multipart/form-data"
>
{% csrf_token %}
{% include 'partial/form.html' with form=form %}
{% include 'partial/form.html' with form=profile_form %}
<br>
<input
type=
"submit"
value=
"Submit"
class=
"btn btn-success"
>
</form>
{% endblock %}
\ No newline at end of file
accounts/urls.py
View file @
7e1bde5a
...
...
@@ -5,5 +5,8 @@ from accounts import views
urlpatterns
=
[
path
(
'login/'
,
views
.
LoginView
.
as_view
(),
name
=
'login'
),
path
(
'logout/'
,
views
.
LogoutView
.
as_view
(),
name
=
'logout'
),
path
(
'register/'
,
views
.
RegisterView
.
as_view
(),
name
=
'register'
)
path
(
'register/'
,
views
.
RegisterView
.
as_view
(),
name
=
'register'
),
path
(
'users/<int:id>/detail/'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user_detail'
),
path
(
'users/<int:id>/update/'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user_update'
),
path
(
'users/<int:id>/change-pass/'
,
views
.
UserPasswordChangeView
.
as_view
(),
name
=
'user_change_pass'
)
]
accounts/views.py
View file @
7e1bde5a
from
django.contrib.auth
import
views
,
login
from
django.views.generic
import
CreateView
from
django.contrib.auth
import
views
,
login
,
get_user_model
,
update_session_auth_hash
from
django.contrib.auth.mixins
import
LoginRequiredMixin
,
UserPassesTestMixin
from
django.contrib.auth.views
import
PasswordChangeView
from
django.core.paginator
import
Paginator
from
django.http
import
HttpResponseRedirect
from
django.views.generic
import
CreateView
,
DetailView
,
UpdateView
from
django.shortcuts
import
redirect
from
django.urls
import
reverse_lazy
from
accounts.forms
import
LoginForm
,
RegisterForm
from
accounts.models
import
User
from
accounts.forms
import
LoginForm
,
RegisterForm
,
UserUpdateForm
,
ProfileUpdateForm
,
PasswordChangeForm
from
accounts.models
import
User
,
Profile
class
AuthSuccessUrlMixin
:
...
...
@@ -35,5 +39,90 @@ class RegisterView(AuthSuccessUrlMixin, CreateView):
def
form_valid
(
self
,
form
):
user
=
form
.
save
()
Profile
.
objects
.
create
(
user
=
user
)
login
(
self
.
request
,
user
)
return
redirect
(
self
.
get_success_url
())
class
UserDetailView
(
LoginRequiredMixin
,
DetailView
):
model
=
get_user_model
()
# accounts.User
template_name
=
'user/detail.html'
context_object_name
=
'user'
pk_url_kwarg
=
'id'
paginate_related_by
=
5
paginate_related_orphans
=
0
def
get_context_data
(
self
,
**
kwargs
):
articles
=
self
.
object
.
articles
.
order_by
(
'-created_at'
)
paginator
=
Paginator
(
object_list
=
articles
,
per_page
=
self
.
paginate_related_by
,
orphans
=
self
.
paginate_related_orphans
)
page_number
=
self
.
request
.
GET
.
get
(
'page'
,
1
)
page
=
paginator
.
get_page
(
page_number
)
kwargs
|=
{
'page_obj'
:
page
,
'articles'
:
page
.
object_list
,
'is_paginated'
:
page
.
has_other_pages
(),
'paginator'
:
paginator
}
return
super
()
.
get_context_data
(
**
kwargs
)
class
UserUpdateView
(
UserPassesTestMixin
,
UpdateView
):
model
=
get_user_model
()
form_class
=
UserUpdateForm
template_name
=
'user/update.html'
pk_url_kwarg
=
'id'
context_object_name
=
'user_obj'
def
test_func
(
self
):
return
self
.
request
.
user
==
self
.
get_object
()
def
get_context_data
(
self
,
**
kwargs
):
if
'profile_form'
not
in
kwargs
:
kwargs
[
'profile_form'
]
=
self
.
get_profile_form
()
return
super
()
.
get_context_data
(
**
kwargs
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
object
=
self
.
get_object
()
form
=
self
.
get_form
()
profile_form
=
self
.
get_profile_form
()
if
form
.
is_valid
()
and
profile_form
.
is_valid
():
profile_form
.
save
()
return
self
.
form_valid
(
form
)
else
:
context
=
self
.
get_context_data
(
form
=
form
,
profile_form
=
profile_form
)
return
self
.
render_to_response
(
context
)
def
get_success_url
(
self
):
return
reverse_lazy
(
'user_detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
def
get_profile_form
(
self
):
form_kwargs
=
{
'instance'
:
self
.
object
.
profile
}
if
self
.
request
.
method
==
'POST'
:
form_kwargs
[
'data'
]
=
self
.
request
.
POST
form_kwargs
[
'files'
]
=
self
.
request
.
FILES
return
ProfileUpdateForm
(
**
form_kwargs
)
class
UserPasswordChangeView
(
UserPassesTestMixin
,
UpdateView
):
model
=
get_user_model
()
template_name
=
'user/change_password.html'
form_class
=
PasswordChangeForm
pk_url_kwarg
=
'id'
context_object_name
=
'user_obj'
def
test_func
(
self
):
return
self
.
request
.
user
==
self
.
get_object
()
def
form_valid
(
self
,
form
):
user
=
form
.
save
()
update_session_auth_hash
(
self
.
request
,
user
)
return
HttpResponseRedirect
(
self
.
get_success_url
())
def
get_success_url
(
self
):
return
reverse_lazy
(
'user_detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
core/settings.py
View file @
7e1bde5a
...
...
@@ -129,9 +129,9 @@ STATICFILES_DIRS = [
#
#
# # Media files
#
#
MEDIA_URL = '/media/'
#
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL
=
'/media/'
MEDIA_ROOT
=
os
.
path
.
join
(
BASE_DIR
,
'media'
)
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
...
...
fixtures/users_dump.json
View file @
7e1bde5a
...
...
@@ -239,7 +239,7 @@
"fields"
:
{
"name"
:
"Can delete article"
,
"content_type"
:
7
,
"codename"
:
"
delete_articl
e"
"codename"
:
"
article_delet
e"
}
},
{
...
...
media/.DS_Store
0 → 100644
View file @
7e1bde5a
File added
media/avatars/capibara.jpg
0 → 100644
View file @
7e1bde5a
225 KB
media/avatars/capibara_CHIsGVx.jpg
0 → 100644
View file @
7e1bde5a
225 KB
reqs.txt
View file @
7e1bde5a
asgiref==3.7.2
blessed==1.20.0
bpython==0.24
certifi==2023.5.7
charset-normalizer==3.2.0
curtsies==0.4.1
cwcwidth==0.1.8
Django==3.2.19
django-extensions==3.2.3
greenlet==2.0.2
idna==3.4
Pillow==10.0.0
Pygments==2.15.1
pytz==2023.3
pyxdg==0.28
requests==2.31.0
six==1.16.0
sqlparse==0.4.4
urllib3==2.0.3
wcwidth==0.2.6
web/templates/article/article_detail.html
View file @
7e1bde5a
...
...
@@ -28,7 +28,7 @@
{% if perms.web.change_article or article.author == request.user %}
<a
href=
"{% url 'article_update' article.pk %}"
class=
"btn btn-primary mt-4 me-3"
>
Edit
</a>
{% endif %}
<form
action=
"{% url '
delete_articl
e' article.pk %}"
method=
"POST"
onsubmit=
"return confirm('Are you sure?')"
>
<form
action=
"{% url '
article_delet
e' article.pk %}"
method=
"POST"
onsubmit=
"return confirm('Are you sure?')"
>
{% csrf_token %}
<button
class=
"btn btn-danger mt-4"
>
Delete
</button>
</form>
...
...
web/templates/article/delete.html
View file @
7e1bde5a
...
...
@@ -6,11 +6,11 @@
{% block content %}
<h1>
Are you sure you want to delete article: {{ article.title }}?
</h1>
<form
action=
"{% url '
delete_articl
e' article.pk %}"
method=
"POST"
>
<form
action=
"{% url '
article_delet
e' article.pk %}"
method=
"POST"
>
{% csrf_token %}
<p><input
type=
"submit"
value=
"Confirm"
></p>
<p><a
href=
"{% url 'article
s-
detail' article.pk %}"
>
Cancel
</a></p>
<p><a
href=
"{% url 'article
_
detail' article.pk %}"
>
Cancel
</a></p>
</form>
...
...
web/templates/article/index.html
View file @
7e1bde5a
...
...
@@ -5,38 +5,6 @@
{% block content %}
<h1>
{{ "Articles"|upper }}
</h1>
<h1>
{{ greetings }}
</h1>
{% custom_range 1 10 as range %}
{% for num in range %}
{{ num }}
{% endfor %}
{% if perms.web.add_article %}
<a
href=
"{% url 'articles-add' %}"
class=
"btn btn-primary"
>
Создать
</a>
{% endif %}
{% include 'partial/search_form.html' %}
{% for article in articles %}
<br>
<hr>
<br>
<h2>
{{ article.title }}
</h2>
{# {% if user.is_authenticated %}#}
<p>
<a
href=
"{% url 'articles-detail' id=article.id %}"
>
Подробнее
</a>
</p>
{# {% endif %}#}
<br>
<hr>
<br>
{% endfor %}
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
{% include 'partial/article_list.html' %}
{% endblock %}
web/templates/base.html
View file @
7e1bde5a
...
...
@@ -23,7 +23,7 @@
<div
class=
"collapse navbar-collapse flex-grow-0"
id=
"navbarNav"
>
<ul
class=
"navbar-nav"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link active"
aria-current=
"page"
href=
"{% url 'article
s-
add' %}"
>
<a
class=
"nav-link active"
aria-current=
"page"
href=
"{% url 'article
_
add' %}"
>
Create
</a>
</li>
...
...
@@ -31,14 +31,14 @@
<a
class=
"nav-link"
href=
"#"
>
Features
</a>
</li>
{% if user.is_authenticated %}
{% if
request.
user.is_authenticated %}
<li
class=
"nav-item dropdown"
>
<a
class=
"nav-link dropdown-toggle"
href=
"#"
role=
"button"
data-bs-toggle=
"dropdown"
aria-expanded=
"false"
>
{{ user.username }}
{{
request.
user.username }}
</a>
<ul
class=
"dropdown-menu"
>
<li><a
class=
"dropdown-item"
href=
"
#"
>
Action
</a></li>
<li><a
class=
"dropdown-item"
href=
"
{% url 'user_detail' request.user.id %}"
>
Cabinet
</a></li>
<li><a
class=
"dropdown-item"
href=
"#"
>
Another action
</a></li>
<li>
<hr
class=
"dropdown-divider"
>
...
...
web/templates/partial/article_list.html
0 → 100644
View file @
7e1bde5a
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
{% for article in articles %}
<br>
<hr>
<br>
<h2>
{{ article.title }}
</h2>
<p>
<a
href=
"{% url 'article_detail' id=article.id %}"
>
Подробнее
</a>
</p>
<br>
<hr>
<br>
{% endfor %}
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
\ No newline at end of file
web/templates/partial/form.html
View file @
7e1bde5a
...
...
@@ -17,5 +17,6 @@
{{ field }}
{% endfor %}
<button
type=
"submit"
class=
"btn btn-success"
>
{{ button_text }}
</button>
{% if button_text %}
<button
type=
"submit"
class=
"btn btn-success"
>
{{ button_text }}
</button>
{% endif %}
web/urls.py
View file @
7e1bde5a
...
...
@@ -4,10 +4,10 @@ from web import views
urlpatterns
=
[
path
(
'articles/'
,
views
.
ArticleIndexView
.
as_view
(),
name
=
'main_page'
),
path
(
'articles/add/'
,
views
.
ArticleCreateView
.
as_view
(),
name
=
'article
s-
add'
),
path
(
'articles/<int:id>/'
,
views
.
ArticleDetailView
.
as_view
(),
name
=
'article
s-
detail'
),
path
(
'articles/add/'
,
views
.
ArticleCreateView
.
as_view
(),
name
=
'article
_
add'
),
path
(
'articles/<int:id>/'
,
views
.
ArticleDetailView
.
as_view
(),
name
=
'article
_
detail'
),
path
(
'articles/<int:id>/edit'
,
views
.
ArticleUpdateView
.
as_view
(),
name
=
'article_update'
),
path
(
'articles/<int:id>/delete'
,
views
.
ArticleDeleteView
.
as_view
(),
name
=
'
delete_articl
e'
),
path
(
'articles/<int:id>/delete'
,
views
.
ArticleDeleteView
.
as_view
(),
name
=
'
article_delet
e'
),
path
(
'comments/add/'
,
...
...
web/views/article.py
View file @
7e1bde5a
...
...
@@ -52,7 +52,7 @@ class ArticleIndexView(ListView):
return
self
.
form
.
cleaned_data
.
get
(
'search'
)
class
ArticleCreateView
(
PermissionRequiredMixin
,
CreateView
):
class
ArticleCreateView
(
CreateView
):
template_name
=
'article/article_create.html'
model
=
Article
form_class
=
ArticleModelForm
...
...
@@ -60,7 +60,7 @@ class ArticleCreateView(PermissionRequiredMixin, CreateView):
permission_denied_message
=
'You have no rights'
def
get_success_url
(
self
):
return
reverse
(
'article
s-
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
return
reverse
(
'article
_
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
class
ArticleDetailView
(
DetailView
):
...
...
@@ -91,7 +91,7 @@ class ArticleUpdateView(UserPassesTestMixin, UpdateView):
self
.
request
.
user
.
has_perm
(
'web.change_article'
)
def
get_success_url
(
self
):
return
reverse
(
'article
s-
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
return
reverse
(
'article
_
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
id
})
class
ArticleDeleteView
(
DeleteView
):
...
...
web/views/comment.py
View file @
7e1bde5a
...
...
@@ -15,7 +15,7 @@ class CommentCreateView(CreateView):
form_class
=
CommentModelForm
def
get_success_url
(
self
):
return
reverse
(
'article
s-
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
return
reverse
(
'article
_
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
class
CommentUpdateView
(
PermissionRequiredMixin
,
UpdateView
):
...
...
@@ -34,7 +34,7 @@ class CommentUpdateView(PermissionRequiredMixin, UpdateView):
return
super
()
.
has_permission
()
or
self
.
request
.
user
==
self
.
get_object
()
.
author
def
get_success_url
(
self
):
return
reverse
(
'article
s-
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
return
reverse
(
'article
_
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
class
CommentDeleteView
(
DeleteView
):
...
...
@@ -42,4 +42,4 @@ class CommentDeleteView(DeleteView):
pk_url_kwarg
=
'id'
def
get_success_url
(
self
):
return
reverse
(
'article
s-
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
return
reverse
(
'article
_
detail'
,
kwargs
=
{
'id'
:
self
.
object
.
article
.
id
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment