milesrichardson / ParsePy

A relatively up-to-date fork of ParsePy, the Python wrapper for the Parse.com API. Originally maintained by @dgrtwo
MIT License
515 stars 184 forks source link

User Can't Save - Impossible to add or change fields #146

Closed SovcikJoe closed 8 years ago

SovcikJoe commented 8 years ago

I am testing out this Library and ParseServer and testing out my database design before I commit to using Parse for one of my projects.

However, I encountered an issue when I want to save a new state.

It fails even if I just log in and then call save()

== On the Aside, is there a way to save and modify users and User table without logging in? As sometimes I might not actually have access to the session of User (Let's say I want to connect to Users, and one of them initializes the "connection". I can add (theoretically) the pointer for the logged in user, but I can't do it for the user the connection is made to. ==

Here's the exception:

Traceback (most recent call last):
  File "/home/theshade/.virtualenvs/ParseBabynames/lib/python3.5/site-packages/parse_rest/connection.py", line 134, in execute
    response = urlopen(request, timeout=CONNECTION_TIMEOUT)
  File "/usr/lib64/python3.5/urllib/request.py", line 163, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib64/python3.5/urllib/request.py", line 472, in open
    response = meth(req, response)
  File "/usr/lib64/python3.5/urllib/request.py", line 582, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib64/python3.5/urllib/request.py", line 510, in error
    return self._call_chain(*args)
  File "/usr/lib64/python3.5/urllib/request.py", line 444, in _call_chain
    result = func(*args)
  File "/usr/lib64/python3.5/urllib/request.py", line 590, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "parsetestscript.py", line 124, in <module>
    create_user_tables()
  File "parsetestscript.py", line 63, in create_user_tables
    user2.save()
  File "/home/theshade/.virtualenvs/ParseBabynames/lib/python3.5/site-packages/parse_rest/user.py", line 27, in ret
    return func(obj, *args, **kw)
  File "/home/theshade/.virtualenvs/ParseBabynames/lib/python3.5/site-packages/parse_rest/user.py", line 63, in save
    response = User.PUT(url, extra_headers=session_header, batch=batch, **data)
  File "/home/theshade/.virtualenvs/ParseBabynames/lib/python3.5/site-packages/parse_rest/connection.py", line 156, in PUT
    return cls.execute(uri, 'PUT', **kw)
  File "/home/theshade/.virtualenvs/ParseBabynames/lib/python3.5/site-packages/parse_rest/connection.py", line 142, in execute
    raise exc(e.read())
parse_rest.core.ResourceRequestBadRequest: b'{"code":111,"error":"This is not a valid Relation"}'

The code is simple, I get this even if I just call user.login(); user.save();

If I don't call save, I get no exception.

Can anybody enlighten me why is this happening or if this is a bug? If so, any steps I could tryy to take to solve it?

So far I thought about creating a separate Users table which would be just an object but that might bring extra complexity to the design?

milesrichardson commented 8 years ago

You didn't post your code, so not sure I can help much. But one guess I have is that you are using User as the class. For special Parse classes, like User and Session, the classname is actually _User and _Session.

So instead of:

class User(Object):
    pass

You want:

class _User(Object):
    pass
SovcikJoe commented 8 years ago

Sorry for late reply, I got no notification about your reply.

I read about the _User class problem before, but I am just using the Implemented user class

so my code is for example First I import the user from parse_rest.user import User then

user3 = User.Query.get(username="user3")
    user2 = User.login("user2","-------")
    user2.pythontest = "testingPythonCode"
    user2.connectedTo = user3
    user2.save()
    user3.connectedTo = user2
    user3.save()

But even if I call the Query or Login method on User and get the User object back, which I always do, then I can't save it as I get an error.

milesrichardson commented 8 years ago

@SovcikJoe It looks like the error you are getting is

parse_rest.core.ResourceRequestBadRequest: b'{"code":111,"error":"This is not a valid Relation"}'

It's hard for me to debug this without any context, but I know that that error comes from parse-server. Googling "parse error 111" brought me here: https://parse.com/questions/cloud-code-error-111-invalid-type-for-key-users-expected-relation_user-but-got-object

"the basic solution/problem/fact is that with Cloud Code your functions are basically always beginning with only pointers or objectIds"

From your code, I'm assuming you have added a relation column on User? And the error is happening because user.connectedTo is a relation column, but for some reason the value you assign to it is interpreted by Parse as a bad relation.

Again, hard without context, but try this:

...
user2.connectedTo = User(objectId=user3.objectId)
user2.save()
...
user3.connectedTo = User(objectId=user2.objectId)
user3.save()

If that doesn't work, also try _User instead of User.

If I could see your schema I might be able to help more. Hopefully this works.

SovcikJoe commented 8 years ago

@milesrichardson Okay, so just to let you know.

To re-iterate what was wrong. It was impossible to save the User after logging in, even if there were no changes made. (So just logging in and calling .save() afterwards)

The problem was with one row in the user table which I added manually at the beginning using the Dashboard. Because of that, it always failed.

I solved it by deleting all the rows and starting over. Then everything worked.

And to solve the other problem == Saving the changes to the User without the need of logging in.

I used the method of creating the _User(Object) class and then used that when querying instead of the implemented User class from the library.

With this I would also like to thank you for this library as it makes dealing with Parse so much easier, and if you need some help with it I'd be happy to help out.

Thank you