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

User bookmarking #14

Merged
merged 2 commits into from
Jan 20, 2017
Merged

User bookmarking #14

merged 2 commits into from
Jan 20, 2017

Conversation

Pomax
Copy link
Contributor

@Pomax Pomax commented Jan 13, 2017

  • /entries and /entries/1234 show entries/a single entry with their total fave count as field favorite_count, and a field is_favorite that is true for a user that is a) logged in, and b) has favorited this entry. In any other case, it will be false.
  • /entries/123/favorite toggles a fave/not-fave value for entry 123 for the currently logged in user. If a user is not logged in, they will receive a 403

fixes #12
fixes #30

@@ -0,0 +1,12 @@
from django.core.urlresolvers import reverse
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file old?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, I'll remove it.

Serializes a {user,entry,when} fave.
"""

user = '__all__'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question @gideonthomas do you remember why we needed this? If so, we can document it in the source

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I don't know what this is :P I thought all serializer fields should be instances. Are you sure this is working?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__all__ normally exposes all public methods for use in import ... from ... statements including those prefixed with underscores (usually 'hidden') but in this case it doesn't look like it actually does anything, so I'll remove it.

def entries(self, instance):
"""
Show all entries as a string of titles. In the future we should make them links.
"""
print('entries instance')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this logging

from rest_framework.generics import ListCreateAPIView, RetrieveAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

from pulseapi.entries.models import Entry
from pulseapi.entries.serializers import EntrySerializer
from pulseapi.users.models import UserFavorites

# FIXME: TODO: Remove the handling for GET, so that only PUT works
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the GET there just so it's easier to test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct. The "real" use would be PUT only, but for testing a GET is way easier to do without writing an XHR test page


# FIXME: TODO: Remove the handling for GET, so that only PUT works
@api_view(['GET','PUT'])
def toggle_favorite(request, entryid):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so I understand what's going on here because I've seen this before, can you explain line 17 and 18 from a django standpoint? Why is this a function and not a view class? Is 17 the indicator that it's a generic GET/PUT view which does nothing special?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 17 says "only expose this def when the http verb is GET or PUT (http verb whitelist)

line 18 is a function that services a view (see urls.py) as a general function rather than a class entry, as faving an entry is technically something "outside" of entries and users.

Copy link
Contributor

@alanmoo alanmoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment

@Pomax Pomax changed the title [WIP] User favoriting User favoriting Jan 16, 2017
@Pomax Pomax dismissed alanmoo’s stale review January 16, 2017 20:54

had to 'dismiss' to get rid of a detached review comment

@@ -2,26 +2,63 @@

from django.test import TestCase
from django.test import Client
from pulseapi.tests import PulseTestCase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did my PR reset this to older code?

@@ -1,9 +1,8 @@
import json

from django.core.urlresolvers import reverse
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, this looks to have old test code, too.

@@ -21,8 +56,8 @@ def post_validate(request):
nonce = False

if request.data:
csrf_token = request.data['csrfmiddlewaretoken']
nonce = request.data['nonce']
csrf_token = request.data.get('csrfmiddlewaretoken', False)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was throwing key errors so I turned it into get rather than direct access to get a fallback value.

REST endpoint:

  <PUT> /entries/<id>/bookmark

Behaviour:

  calling the endpoint, by an authenticated user, will
  mark the entry as bookmarked by the that user. Calling
  it again unbookmarks the entry.
@Pomax Pomax changed the title User favoriting User bookmarking Jan 19, 2017
@Pomax Pomax requested a review from alanmoo January 19, 2017 22:03
* User favorites route

* ‘favorite’ -> ‘bookmark’

* Bookmark view tests

is_bookmarked = serializers.SerializerMethodField()

def get_is_bookmarked(self, instance):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the kind of magic that bothers me. I understand it, but it still feels weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate Django for this kind of thing.

from pulseapi.users.models import UserBookmarks

@api_view(['PUT'])
def toggle_bookmark(request, entryid):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're sticking with the toggling behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about it some more, entries already say whether they are bookmarked or not when you call /entries so for regular operation we don't need a "toggle yes or no", the only time we would need that is for bulk bookmark syncing, which we should probably do on its own dedicated route so a full set of bookmarks can be sent over in a single call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. There's then a little bit of manual state management between the front and back end, but it seems reasonable.

@@ -21,7 +18,6 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=140)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='as_creator', to=settings.AUTH_USER_MODEL)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I probably shouldn't be reading into the migrations files too much but why is this being removed?

Should we merge these and then follow up with an immediate rebuild of migrations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be my suggestion too, yes. It's time to wipe the compound migrations we've been accumulating (except for issues, which is one step and has data) and rebuild everything as single step migrations.

Copy link
Contributor

@alanmoo alanmoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, just a few clarifications before merging?

@alanmoo alanmoo merged commit 5f8cbfd into master Jan 20, 2017
@alanmoo alanmoo deleted the user_favs branch January 20, 2017 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

rename favorites to bookmarks for developer clarity Add connection between entries and user favorites
3 participants