forked from mirrors/bookwyrm
Moves user views to class view
This commit is contained in:
parent
8693895bc6
commit
85d01d5df0
11 changed files with 316 additions and 269 deletions
|
@ -82,7 +82,7 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/user-edit" class="navbar-item">
|
||||
<a href="/edit-profile" class="navbar-item">
|
||||
Settings
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
{% if is_self %}
|
||||
<div class="column is-narrow">
|
||||
<a href="/user-edit/">
|
||||
<a href="/edit-profile">
|
||||
<span class="icon icon-pencil">
|
||||
<span class="is-sr-only">Edit profile</span>
|
||||
</span>
|
||||
|
|
|
@ -221,83 +221,6 @@ class Views(TestCase):
|
|||
response.context_data['user_results'][0], self.local_user)
|
||||
|
||||
|
||||
def test_import_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.import_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'import.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_import_status(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.tasks.app.AsyncResult') as async_result:
|
||||
async_result.return_value = []
|
||||
result = views.import_status(request, import_job.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'import_status.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_user_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.user_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'user.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.user_page(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_followers_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.followers_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'followers.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.followers_page(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_following_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.following_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'following.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.following_page(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_status_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
status = models.Status.objects.create(
|
||||
|
|
99
bookwyrm/tests/views/test_user.py
Normal file
99
bookwyrm/tests/views/test_user.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
''' test for app action functionality '''
|
||||
from unittest.mock import patch
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import forms, models, views
|
||||
from bookwyrm.activitypub import ActivitypubResponse
|
||||
|
||||
|
||||
class UserViews(TestCase):
|
||||
''' view user and edit profile '''
|
||||
def setUp(self):
|
||||
''' we need basic test data and mocks '''
|
||||
self.factory = RequestFactory()
|
||||
self.local_user = models.User.objects.create_user(
|
||||
'mouse@local.com', 'mouse@mouse.mouse', 'password',
|
||||
local=True, localname='mouse')
|
||||
|
||||
|
||||
def test_user_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
view = views.User.as_view()
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'user.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_followers_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
view = views.Followers.as_view()
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'followers.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_following_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
view = views.Following.as_view()
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'following.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.user.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = view(request, 'mouse')
|
||||
self.assertIsInstance(result, ActivitypubResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_edit_profile_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
view = views.EditUser.as_view()
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'edit_user.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_edit_user(self):
|
||||
''' use a form to update a user '''
|
||||
view = views.EditUser.as_view()
|
||||
form = forms.EditUserForm(instance=self.local_user)
|
||||
form.data['name'] = 'New Name'
|
||||
request = self.factory.post('', form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
view(request)
|
||||
self.assertEqual(self.local_user.name, 'New Name')
|
|
@ -69,16 +69,14 @@ urlpatterns = [
|
|||
re_path(r'^import/?$', views.Import.as_view()),
|
||||
re_path(r'^import/(\d+)/?$', views.ImportStatus.as_view()),
|
||||
|
||||
re_path(r'^user-edit/?$', vviews.edit_profile_page),
|
||||
|
||||
# should return a ui view or activitypub json blob as requested
|
||||
# users
|
||||
re_path(r'%s/?$' % user_path, vviews.user_page),
|
||||
re_path(r'%s\.json$' % local_user_path, vviews.user_page),
|
||||
re_path(r'%s/?$' % local_user_path, vviews.user_page),
|
||||
re_path(r'%s/shelves/?$' % local_user_path, vviews.user_shelves_page),
|
||||
re_path(r'%s/followers(.json)?/?$' % local_user_path, vviews.followers_page),
|
||||
re_path(r'%s/following(.json)?/?$' % local_user_path, vviews.following_page),
|
||||
re_path(r'%s/?$' % user_path, views.User.as_view()),
|
||||
re_path(r'%s\.json$' % user_path, views.User.as_view()),
|
||||
re_path(r'%s/shelves/?$' % user_path, vviews.user_shelves_page),
|
||||
re_path(r'%s/followers(.json)?/?$' % user_path, views.Followers.as_view()),
|
||||
re_path(r'%s/following(.json)?/?$' % user_path, views.Following.as_view()),
|
||||
re_path(r'^edit-profile/?$', views.EditUser.as_view()),
|
||||
|
||||
# statuses
|
||||
re_path(r'%s(.json)?/?$' % status_path, vviews.status_page),
|
||||
|
@ -102,7 +100,6 @@ urlpatterns = [
|
|||
re_path(r'^search/?$', vviews.search),
|
||||
|
||||
# internal action endpoints
|
||||
re_path(r'^edit-profile/?$', actions.edit_profile),
|
||||
|
||||
re_path(r'^resolve-book/?$', actions.resolve_book),
|
||||
re_path(r'^edit-book/(?P<book_id>\d+)/?$', actions.edit_book),
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
''' views for actions you can take in the application '''
|
||||
from io import BytesIO
|
||||
from uuid import uuid4
|
||||
from PIL import Image
|
||||
|
||||
import dateutil.parser
|
||||
from dateutil.parser import ParserError
|
||||
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import transaction
|
||||
from django.http import HttpResponseBadRequest, HttpResponseNotFound
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
|
@ -21,50 +16,6 @@ from bookwyrm.broadcast import broadcast
|
|||
from bookwyrm.vviews import get_user_from_username, get_edition
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def edit_profile(request):
|
||||
''' les get fancy with images '''
|
||||
form = forms.EditUserForm(
|
||||
request.POST, request.FILES, instance=request.user)
|
||||
if not form.is_valid():
|
||||
data = {'form': form, 'user': request.user}
|
||||
return TemplateResponse(request, 'edit_user.html', data)
|
||||
|
||||
user = form.save(commit=False)
|
||||
|
||||
if 'avatar' in form.files:
|
||||
# crop and resize avatar upload
|
||||
image = Image.open(form.files['avatar'])
|
||||
target_size = 120
|
||||
width, height = image.size
|
||||
thumbnail_scale = height / (width / target_size) if height > width \
|
||||
else width / (height / target_size)
|
||||
image.thumbnail([thumbnail_scale, thumbnail_scale])
|
||||
width, height = image.size
|
||||
|
||||
width_diff = width - target_size
|
||||
height_diff = height - target_size
|
||||
cropped = image.crop((
|
||||
int(width_diff / 2),
|
||||
int(height_diff / 2),
|
||||
int(width - (width_diff / 2)),
|
||||
int(height - (height_diff / 2))
|
||||
))
|
||||
output = BytesIO()
|
||||
cropped.save(output, format=image.format)
|
||||
ContentFile(output.getvalue())
|
||||
|
||||
# set the name to a hash
|
||||
extension = form.files['avatar'].name.split('.')[-1]
|
||||
filename = '%s.%s' % (uuid4(), extension)
|
||||
user.avatar.save(filename, ContentFile(output.getvalue()))
|
||||
user.save()
|
||||
|
||||
broadcast(user, user.to_update_activity(user))
|
||||
return redirect('/user/%s' % request.user.localname)
|
||||
|
||||
|
||||
@require_POST
|
||||
def resolve_book(request):
|
||||
''' figure out the local path to a book from a remote_id '''
|
||||
|
|
|
@ -6,3 +6,4 @@ from .landing import About, Home, Feed, Discover
|
|||
from .notifications import Notifications
|
||||
from .direct_message import DirectMessage
|
||||
from .import_data import Import, ImportStatus
|
||||
from .user import User, EditUser, Followers, Following
|
||||
|
|
|
@ -2,6 +2,21 @@
|
|||
from django.db.models import Q
|
||||
from bookwyrm import models
|
||||
|
||||
def get_user_from_username(username):
|
||||
''' helper function to resolve a localname or a username to a user '''
|
||||
# raises DoesNotExist if user is now found
|
||||
try:
|
||||
return models.User.objects.get(localname=username)
|
||||
except models.User.DoesNotExist:
|
||||
return models.User.objects.get(username=username)
|
||||
|
||||
|
||||
def is_api_request(request):
|
||||
''' check whether a request is asking for html or data '''
|
||||
return 'json' in request.headers.get('Accept') or \
|
||||
request.path[-5:] == '.json'
|
||||
|
||||
|
||||
def get_activity_feed(
|
||||
user, privacy, local_only=False, following_only=False,
|
||||
queryset=models.Status.objects):
|
||||
|
|
|
@ -94,7 +94,7 @@ class ChangePassword(View):
|
|||
confirm_password = request.POST.get('confirm-password')
|
||||
|
||||
if new_password != confirm_password:
|
||||
return redirect('/user-edit')
|
||||
return redirect('/edit-profile')
|
||||
|
||||
request.user.set_password(new_password)
|
||||
request.user.save()
|
||||
|
|
192
bookwyrm/views/user.py
Normal file
192
bookwyrm/views/user.py
Normal file
|
@ -0,0 +1,192 @@
|
|||
''' non-interactive pages '''
|
||||
from io import BytesIO
|
||||
from uuid import uuid4
|
||||
from PIL import Image
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.paginator import Paginator
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import forms, models
|
||||
from bookwyrm.activitypub import ActivitypubResponse
|
||||
from bookwyrm.broadcast import broadcast
|
||||
from bookwyrm.settings import PAGE_LENGTH
|
||||
from .helpers import get_activity_feed, get_user_from_username, is_api_request
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
class User(View):
|
||||
''' user profile page '''
|
||||
def get(self, request, username):
|
||||
''' profile page for a user '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
# we have a json request
|
||||
return ActivitypubResponse(user.to_activity())
|
||||
# otherwise we're at a UI view
|
||||
|
||||
try:
|
||||
page = int(request.GET.get('page', 1))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
shelf_preview = []
|
||||
|
||||
# only show other shelves that should be visible
|
||||
shelves = user.shelf_set
|
||||
is_self = request.user.id == user.id
|
||||
if not is_self:
|
||||
follower = user.followers.filter(id=request.user.id).exists()
|
||||
if follower:
|
||||
shelves = shelves.filter(privacy__in=['public', 'followers'])
|
||||
else:
|
||||
shelves = shelves.filter(privacy='public')
|
||||
|
||||
for user_shelf in shelves.all():
|
||||
if not user_shelf.books.count():
|
||||
continue
|
||||
shelf_preview.append({
|
||||
'name': user_shelf.name,
|
||||
'local_path': user_shelf.local_path,
|
||||
'books': user_shelf.books.all()[:3],
|
||||
'size': user_shelf.books.count(),
|
||||
})
|
||||
if len(shelf_preview) > 2:
|
||||
break
|
||||
|
||||
# user's posts
|
||||
activities = get_activity_feed(
|
||||
request.user,
|
||||
['public', 'unlisted', 'followers'],
|
||||
queryset=models.Status.objects.filter(user=user)
|
||||
)
|
||||
paginated = Paginator(activities, PAGE_LENGTH)
|
||||
activity_page = paginated.page(page)
|
||||
|
||||
prev_page = next_page = None
|
||||
if activity_page.has_next():
|
||||
next_page = '/user/%s/?page=%d' % \
|
||||
(username, activity_page.next_page_number())
|
||||
if activity_page.has_previous():
|
||||
prev_page = '/user/%s/?page=%d' % \
|
||||
(username, activity_page.previous_page_number())
|
||||
data = {
|
||||
'title': user.name,
|
||||
'user': user,
|
||||
'is_self': is_self,
|
||||
'shelves': shelf_preview,
|
||||
'shelf_count': shelves.count(),
|
||||
'activities': activity_page.object_list,
|
||||
'next': next_page,
|
||||
'prev': prev_page,
|
||||
}
|
||||
|
||||
return TemplateResponse(request, 'user.html', data)
|
||||
|
||||
class Followers(View):
|
||||
''' list of followers view '''
|
||||
def get(self, request, username):
|
||||
''' list of followers '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
return ActivitypubResponse(
|
||||
user.to_followers_activity(**request.GET))
|
||||
|
||||
data = {
|
||||
'title': '%s: followers' % user.name,
|
||||
'user': user,
|
||||
'is_self': request.user.id == user.id,
|
||||
'followers': user.followers.all(),
|
||||
}
|
||||
return TemplateResponse(request, 'followers.html', data)
|
||||
|
||||
class Following(View):
|
||||
''' list of following view '''
|
||||
def get(self, request, username):
|
||||
''' list of followers '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
return ActivitypubResponse(
|
||||
user.to_following_activity(**request.GET))
|
||||
|
||||
data = {
|
||||
'title': '%s: following' % user.name,
|
||||
'user': user,
|
||||
'is_self': request.user.id == user.id,
|
||||
'following': user.following.all(),
|
||||
}
|
||||
return TemplateResponse(request, 'following.html', data)
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class EditUser(View):
|
||||
''' edit user view '''
|
||||
def get(self, request):
|
||||
''' profile page for a user '''
|
||||
user = request.user
|
||||
|
||||
form = forms.EditUserForm(instance=request.user)
|
||||
data = {
|
||||
'title': 'Edit profile',
|
||||
'form': form,
|
||||
'user': user,
|
||||
}
|
||||
return TemplateResponse(request, 'edit_user.html', data)
|
||||
|
||||
def post(self, request):
|
||||
''' les get fancy with images '''
|
||||
form = forms.EditUserForm(
|
||||
request.POST, request.FILES, instance=request.user)
|
||||
if not form.is_valid():
|
||||
data = {'form': form, 'user': request.user}
|
||||
return TemplateResponse(request, 'edit_user.html', data)
|
||||
|
||||
user = form.save(commit=False)
|
||||
|
||||
if 'avatar' in form.files:
|
||||
# crop and resize avatar upload
|
||||
image = Image.open(form.files['avatar'])
|
||||
target_size = 120
|
||||
width, height = image.size
|
||||
thumbnail_scale = height / (width / target_size) if height > width \
|
||||
else width / (height / target_size)
|
||||
image.thumbnail([thumbnail_scale, thumbnail_scale])
|
||||
width, height = image.size
|
||||
|
||||
width_diff = width - target_size
|
||||
height_diff = height - target_size
|
||||
cropped = image.crop((
|
||||
int(width_diff / 2),
|
||||
int(height_diff / 2),
|
||||
int(width - (width_diff / 2)),
|
||||
int(height - (height_diff / 2))
|
||||
))
|
||||
output = BytesIO()
|
||||
cropped.save(output, format=image.format)
|
||||
ContentFile(output.getvalue())
|
||||
|
||||
# set the name to a hash
|
||||
extension = form.files['avatar'].name.split('.')[-1]
|
||||
filename = '%s.%s' % (uuid4(), extension)
|
||||
user.avatar.save(filename, ContentFile(output.getvalue()))
|
||||
user.save()
|
||||
|
||||
broadcast(user, user.to_update_activity(user))
|
||||
return redirect('/user/%s' % request.user.localname)
|
|
@ -157,121 +157,6 @@ def search(request):
|
|||
return TemplateResponse(request, 'search_results.html', data)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_GET
|
||||
def user_page(request, username):
|
||||
''' profile page for a user '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
# we have a json request
|
||||
return ActivitypubResponse(user.to_activity())
|
||||
# otherwise we're at a UI view
|
||||
|
||||
try:
|
||||
page = int(request.GET.get('page', 1))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
shelf_preview = []
|
||||
|
||||
# only show other shelves that should be visible
|
||||
shelves = user.shelf_set
|
||||
is_self = request.user.id == user.id
|
||||
if not is_self:
|
||||
follower = user.followers.filter(id=request.user.id).exists()
|
||||
if follower:
|
||||
shelves = shelves.filter(privacy__in=['public', 'followers'])
|
||||
else:
|
||||
shelves = shelves.filter(privacy='public')
|
||||
|
||||
for user_shelf in shelves.all():
|
||||
if not user_shelf.books.count():
|
||||
continue
|
||||
shelf_preview.append({
|
||||
'name': user_shelf.name,
|
||||
'local_path': user_shelf.local_path,
|
||||
'books': user_shelf.books.all()[:3],
|
||||
'size': user_shelf.books.count(),
|
||||
})
|
||||
if len(shelf_preview) > 2:
|
||||
break
|
||||
|
||||
# user's posts
|
||||
activities = get_activity_feed(
|
||||
request.user,
|
||||
['public', 'unlisted', 'followers'],
|
||||
queryset=models.Status.objects.filter(user=user)
|
||||
)
|
||||
paginated = Paginator(activities, PAGE_LENGTH)
|
||||
activity_page = paginated.page(page)
|
||||
|
||||
prev_page = next_page = None
|
||||
if activity_page.has_next():
|
||||
next_page = '/user/%s/?page=%d' % \
|
||||
(username, activity_page.next_page_number())
|
||||
if activity_page.has_previous():
|
||||
prev_page = '/user/%s/?page=%d' % \
|
||||
(username, activity_page.previous_page_number())
|
||||
data = {
|
||||
'title': user.name,
|
||||
'user': user,
|
||||
'is_self': is_self,
|
||||
'shelves': shelf_preview,
|
||||
'shelf_count': shelves.count(),
|
||||
'activities': activity_page.object_list,
|
||||
'next': next_page,
|
||||
'prev': prev_page,
|
||||
}
|
||||
|
||||
return TemplateResponse(request, 'user.html', data)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_GET
|
||||
def followers_page(request, username):
|
||||
''' list of followers '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
return ActivitypubResponse(user.to_followers_activity(**request.GET))
|
||||
|
||||
data = {
|
||||
'title': '%s: followers' % user.name,
|
||||
'user': user,
|
||||
'is_self': request.user.id == user.id,
|
||||
'followers': user.followers.all(),
|
||||
}
|
||||
return TemplateResponse(request, 'followers.html', data)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_GET
|
||||
def following_page(request, username):
|
||||
''' list of followers '''
|
||||
try:
|
||||
user = get_user_from_username(username)
|
||||
except models.User.DoesNotExist:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
return ActivitypubResponse(user.to_following_activity(**request.GET))
|
||||
|
||||
data = {
|
||||
'title': '%s: following' % user.name,
|
||||
'user': user,
|
||||
'is_self': request.user.id == user.id,
|
||||
'following': user.following.all(),
|
||||
}
|
||||
return TemplateResponse(request, 'following.html', data)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_GET
|
||||
def status_page(request, username, status_id):
|
||||
|
@ -327,22 +212,6 @@ def replies_page(request, username, status_id):
|
|||
|
||||
return ActivitypubResponse(status.to_replies(**request.GET))
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def edit_profile_page(request):
|
||||
''' profile page for a user '''
|
||||
user = request.user
|
||||
|
||||
form = forms.EditUserForm(instance=request.user)
|
||||
data = {
|
||||
'title': 'Edit profile',
|
||||
'form': form,
|
||||
'user': user,
|
||||
}
|
||||
return TemplateResponse(request, 'edit_user.html', data)
|
||||
|
||||
|
||||
@require_GET
|
||||
def book_page(request, book_id):
|
||||
''' info about a book '''
|
||||
|
|
Loading…
Reference in a new issue