Managing Django Rest Framework 500 Internal Server Error in React when creating user - reactjs

I am attempting my first React + DRF project. Here is my difficulty. When I try to create a user with an existing username I get a 500 internal server error and I can't seem to catch it or do anything with it in React. It otherwise works perfectly well and I can display errors when retrieving user info (such as: "sure does not exist").
The full traceback of the IntegrityError error I get from the backend is:
Traceback (most recent call last):
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "users_customuser_username_key"
DETAIL: Key (username)=(kenshiro) already exists.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/views/generic/base.py", line 84, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/bernardino/Desktop/boombust/users/views.py", line 33, in post
user = serializer.save()
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/serializers.py", line 212, in save
self.instance = self.create(validated_data)
File "/Users/bernardino/Desktop/boombust/users/serializers.py", line 59, in create
instance.save()
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/contrib/auth/base_user.py", line 68, in save
super().save(*args, **kwargs)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 806, in save
self.save_base(
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 857, in save_base
updated = self._save_table(
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 1000, in _save_table
results = self._do_insert(
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 1041, in _do_insert
return manager._insert(
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/query.py", line 1434, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1621, in execute_sql
cursor.execute(sql, params)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 103, in execute
return super().execute(sql, params)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "users_customuser_username_key"
DETAIL: Key (username)=(kenshiro) already exists.
The view in views.py is:
class CustomUserCreate(APIView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format='json'):
serializer = CustomUserSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
try:
user = serializer.save()
if user:
json = serializer.data
return Response(json, status=status.HTTP_201_CREATED)
except IntegrityError:
return Response({"error": "This username is already taken."}, status=status.HTTP_406_NOT_ACCEPTABLE)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
And this is the React logic:
const onSubmit = async (values) => {
const user = {
first_name: values.firstName,
last_name: values.lastName,
username: values.username,
email: values.email,
password: values.password,
};
const response = await fetch(`users/user/create/`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({...user}),
}).catch(err => err);
const text = await response.text();
console.log(response.status);
if (response.status === 201) {
console.log("success", JSON.parse(text));
} else {
console.log("failed", text);
}
};
This is the serializer from serializers.py:
class CustomUserSerializer(serializers.ModelSerializer):
token = serializers.SerializerMethodField()
password = serializers.CharField(write_only=True)
email = serializers.EmailField(
required=True
)
username = serializers.CharField(required=True)
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
password = serializers.CharField(
min_length=8, write_only=True, required=True)
class Meta:
model = CustomUser
fields = ('email', 'username', 'password', 'token', 'first_name', 'last_name')
extra_kwargs = {'password': {'write_only': True}}
def get_token(self, user):
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
}
I do have a username = CICharField(unique=True) in the CustomUser class in models.py if it helps.

You need to check before you save the model.
class CustomUserCreate(APIView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format='json'):
serializer = CustomUserSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
# here you can check if the username already exists or not
username = serializer.validated_data.get('username')
if CustomUser.objects.filter(username = username).count() > 0:
return Response({"error": "This username is already taken."}, status=status.HTTP_406_NOT_ACCEPTABLE)
# if username is new
user = serializer.save()
if user:
json = serializer.data
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Related

Too many values to unpack in Django [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
My endpoint to edit a user in Django is implemented like this:
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def updateUser(request, pk):
user = User.objects.get(pk)
data = request.data
user.first_name = data['name']
user.username = data['email']
user.email = data['email']
user.is_staff = data['isAdmin']
user.save()
serializer = UserSerializer(user, many=False)
return Response(serializer.data)
My user serializer is implemented like this:
class UserSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(read_only=True)
_id = serializers.SerializerMethodField(read_only=True)
isAdmin = serializers.SerializerMethodField(read_only=True)
class Meta:
model = User
fields = ['id', '_id', 'username', 'email', 'name', 'isAdmin']
def get__id(self, obj):
return obj.id
def get_isAdmin(self, obj):
return obj.is_staff
def get_name(self, obj):
name = obj.first_name
if name == '':
name = obj.email
return name
My action in Redux to send a put request to Django is implemented like this:
export const updateUser = (user) => async (dispatch, getState) => {
try {
dispatch({
type: USER_UPDATE_REQUEST
})
const {
userLogin: { userInfo
}
} = getState()
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.put(
`/api/users/update/${user._id}/`,
user,
config
)
dispatch({
type: USER_UPDATE_SUCCESS,
})
dispatch({
type: USER_DETAILS_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: USER_UPDATE_FAIL,
payload: error.response && error.response.data.detail
? error.response.data.detail
: error.message,
})
}
}
I dispatch updateUser action on click of the button in my component like this:
const submitHandler = (e) => {
e.preventDefault()
dispatch(updateUser({ _id: user._id, name, email, isAdmin }))
}
I get error from Django:
Internal Server Error: /api/users/update/undefined/ Traceback (most recent call last): File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\generic\base.py", line 84, in view
return self.dispatch(request, *args, **kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\decorators.py", line 50, in handler
return func(*args, **kwargs) File "C:\Users\pc\Desktop\ecommerce\backend\base\views\user_views.py", line 94, in updateUser
user = User.objects.get(pk) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\query.py", line 482, in get
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\query.py", line 1071, in filter
return self._filter_or_exclude(False, args, kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\query.py", line 1089, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\query.py", line 1096, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs)) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\sql\query.py", line 1502, in add_q
clause, _ = self._add_q(q_object, self.used_aliases) File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\sql\query.py", line 1532, in _add_q
child_clause, needed_inner = self.build_filter( File "C:\Users\pc\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\models\sql\query.py", line 1374, in build_filter
arg, value = filter_expr ValueError: too many values to unpack (expected 2) [16/Dec/2022 10:32:19] "PUT /api/users/update/undefined/ HTTP/1.1" 500 133599
Please help me understand where the problem is
It is in the first line of your view function:
user = User.objects.get(pk=pk)
-- Explaination --
.get require keyword arguments.

snipe command not sniping messages

I found a command that sends the latest deleted message. While testing I found that when I delete a message it sends a traceback error to the console. Here's the traceback error and code.
Ignoring exception in on_message_delete
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "/home/runner/Isla/cogs/awp.py", line 21, in on_message_delete
if msg.author.client:
AttributeError: 'Member' object has no attribute 'client'
import discord
from discord.ext import commands
import datetime
import editdistance
import re
invitere = r"(?:https?:\/\/)?discord(?:\.gg|app\.com\/invite)?\/(?:#\/)([a-zA-Z0-9-]*)"
invitere2 = r"(http[s]?:\/\/)*discord((app\.com\/invite)|(\.gg))\/(invite\/)?(#\/)?([A-Za-z0-9\-]+)(\/)?"
class Awp(commands.Cog):
def __init__(self, client):
self.client = client
self.snipes = {}
#client.listen('on_message_delete')
async def on_message_delete(msg):
if msg.author.client:
return
self.snipes[msg.channel.id] = msg
#client.listen('on_message_edit')
async def on_message_edit(before, after):
if before.author.client or after.author.client:
return # DEPARTMENT OF REDUNDANCY DEPARTMENT
if (editdistance.eval(before.content, after.content) >= 10) and (
len(before.content) > len(after.content)):
self.snipes[before.channel.id] = [before, after]
#commands.Cog.listener()
async def on_ready(self):
print('Gifs bot is online.')
def sanitise(self, string):
if len(string) > 1024:
string = string[0:1021] + "..."
string = re.sub(invitere2, '[INVITE REDACTED]', string)
return string
#commands.command()
async def awp(self, ctx):
'"Snipes" someone\'s message that\'s been edited or deleted.'
try:
snipe = self.snipes[ctx.channel.id]
except KeyError:
return await ctx.send('No snipes in this channel!')
if snipe is None:
return await ctx.send('No snipes in this channel!')
# there's gonna be a snipe after this point
emb = discord.Embed()
if type(snipe) == list: # edit snipe
emb.set_author(
name=str(snipe[0].author),
icon_url=snipe[0].author.avatar_url)
emb.colour = snipe[0].author.colour
emb.add_field(
name='Before',
value=self.sanitise(snipe[0].content),
inline=False)
emb.add_field(
name='After',
value=self.sanitise(snipe[1].content),
inline=False)
emb.timestamp = snipe[0].created_at
else: # delete snipe
emb.set_author(
name=str(snipe.author),
icon_url=snipe.author.avatar_url)
emb.description = self.sanitise(snipe.content)
emb.colour = snipe.author.colour
emb.timestamp = snipe.created_at
emb.set_footer(
text=f'Message sniped by {str(ctx.author)}',
icon_url=ctx.author.avatar_url)
await ctx.send(embed=emb)
self.snipes[ctx.channel.id] = None
def setup(client):
client.add_cog(Awp(client))
You simply have to change message.author.client to message.author.bot, regardless of you using client or bot.
References:
discord.Member

Upload file using Material UI DropzoneDialogBase

I am having issues uploading the files using Material UI DropzoneDialogBase;
My frontend is react & backend is flask
My component is defined as below
<DropzoneDialogBase
dialogTitle={addFileClassDialogTitle()}
fileObjects={uploadFiles}
cancelButtonText={"cancel"}
submitButtonText={"submit"}
maxFileSize={5000000}
filesLimit={1}
open={fileClassState.showAddFileClassForm}
onAdd={newFile => {
console.log('onAdd', newFile);
setUploadFiles([].concat( uploadFiles , newFile ));
}}
onDelete={deleteFile => {
console.log('onDelete', deleteFile);
const fileList = [...uploadFiles];
fileList.splice( deleteFile, 1 );
setUploadFiles( fileList );
}}
onClose={() => setShowAddFileClassForm(false)}
onSave={() => saveNewFileClass( )}
showPreviews={true}
showFileNamesInPreview={true}
/>
The component works fine and adds the files to the object "uploadFiles"
This is my saveNewFileClass
const saveNewFileClass = async () => {
const credentials = localStorage.getItem("credentials");
const formData = new FormData();
formData.append("file", uploadFiles[0]);
console.log( "type of uploadfiles =>", typeof(uploadFiles[0]));
for (var key of formData.entries()) {
console.log(key[0] + ', ' + key[1]);
}
formData.append("data", JSON.stringify({ token: credentials, fileclass: newFileClass }));
console.log('onSave', uploadFiles);
console.log("save new file class", formData);
const requestOptions = {
mode: 'cors',
cache: 'no-cache',
headers: { 'Content-Type': 'multipart/form-data' },
redirect: 'follow',
referrerPolicy: 'no-referrer'
};
const response = await axios.post(
'https://myhost.com:5000/api/addfileclass',
formData,
requestOptions )
const responseData = await response.data;
storeCredentials( responseData.credentials );
setShowAddFileClassForm(false);
}
The Console logs displayed are as below
FileClass.js:143 type of uploadfiles => object
FileClass.js:146 file, [object Object]
FileClass.js:151 onSave [{…}]0: {file: File, data: "data:application/vnd.openxmlformats-officedocument…jUHJvcHMvYXBwLnhtbFBLBQYAAAAAEgASANcEAADDUgAAAAA="}length: 1__proto__: Array(0)
FileClass.js:152 save new file class FormData {}
The log on line 151 confirms that the uploadFiles has an array of Files
However when I append to FormData 'files' it is changed as [Object Object]
Due to this on the flask backend I am not getting any values in request.files and I get the following error
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/ubuntu/.local/lib/python3.8/site-packages/flask_cors/decorator.py", line 128, in wrapped_function
resp = make_response(f(*args, **kwargs))
File "/home/ubuntu/platform-streamxls/react-excel-upload/flaskapp/routes.py", line 286, in addfileclass
downloadfile = request.files["file"]
File "/home/ubuntu/.local/lib/python3.8/site-packages/werkzeug/datastructures.py", line 442, in __getitem__
raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'file'
The python code segment where the error is raised is
def addfileclass():
headers = request.headers
downloadfile = request.files["file"]
Any help on how to fix the react will be nice
The variable uploadFiles is an object array which has a structure of data,files
uploadFiles = []{ data : "mime information", file : "the file Object"}
I changed the append statement to the following
const formData = new FormData();
formData.append("file", uploadFiles[0].file);
This works fine for a single file
I have worked out the pattern to upload multiple files.
most of the examples I searched had multiple api calls in a loop to upload multiple files; this is not always an efficient solution
I have the following for multiple files
const formData = new FormData();
uploadFiles.map((file, idx) => {
formData.append("file"+idx, file.file);
});
formData.append("data", JSON.stringify({ filecount: uploadFiles.length }));
In my backend - I use the filecount to identify the number of files that are there and use the values of "file0", "file1"... to handle the file uploads

angularjs http post image file to drf rest interface got error: AttributeError: 'OrderedDict' object has no attribute 'pk'

I am creating a system consisting angularjs frontend web app and DRF rest interface.
I can use command line 'curl' to upload image file to DRF rest interface, but when I use angularjs http post, I got the error message: 'OrderedDict' object has no attribute 'pk'
My DRF setup is as follows:
models.py:
def upload_to(instance, filename):
return 'post_image/{0}/{1}'.format(instance.author.id, filename)
class PostImage(models.Model):
author = models.ForeignKey(Author, blank=False, editable=False, related_name='images')
post = models.ForeignKey(Post, blank=False, editable=False, related_name='images')
image = models.ImageField(_('image'), blank=True, null=True, upload_to=upload_to)
created = models.DateTimeField(editable=False)
updated = models.DateTimeField(editable=False)
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.created = timezone.now()
self.updated = timezone.now()
return super(PostImage, self).save(*args, **kwargs)
serializers.py
class PostImageSerializer(serializers.HyperlinkedModelSerializer):
author = serializers.HyperlinkedRelatedField(read_only=True, view_name='author-detail')
post = serializers.HyperlinkedRelatedField(read_only=True, view_name='post-detail')
class Meta:
model = PostImage
fields = ('url', 'image', 'author', 'post', 'created', 'updated')
views.py
class PostImageView(generics.ListCreateAPIView):
"""
List and Create post image endpoint
Allowed request method: Get, Post
"""
serializer_class = PostImageSerializer
permission_classes = [permissions.IsAuthenticated]
parser_classes = (FormParser, MultiPartParser, FileUploadParser,)
def get_queryset(self):
queryset = super(PostImageView, self).get_queryset()
return queryset.filter(post__pk=self.kwargs['pk'])
def perform_create(self, serializer):
post = Post.objects.get(pk=self.kwargs['pk'])
if 'upload' in self.request.data:
file_obj = self.request.data['upload']
serializer.save(author=self.request.user, post=post, image=file_obj)
return Response(status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
I am using JWT authentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
) ,
}
Log error message:
Internal Server Error: /api/v1/post/22/image
Traceback (most recent call last):
File "/root/rest_drf/env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/views.py", line 452, in dispatch
response = self.handle_exception(exc)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/views.py", line 449, in dispatch
response = handler(request, *args, **kwargs)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/generics.py", line 244, in post
return self.create(request, *args, **kwargs)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 21, in create
headers = self.get_success_headers(serializer.data)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 466, in data
ret = super(Serializer, self).data
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 215, in data
self._data = self.to_representation(self.validated_data)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 435, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/relations.py", line 264, in to_representation
return self.get_url(value, self.view_name, request, format)
File "/root/rest_drf/env/local/lib/python2.7/site-packages/rest_framework/relations.py", line 199, in get_url
if obj.pk is None:
AttributeError: 'OrderedDict' object has no attribute 'pk'
[pid: 29484|app: 0|req: 2/4] 76.114.185.25 () {54 vars in 1242 bytes} [Sun Jan 24 16:41:13 2016] POST /api/v1/post/22/image => generated 107983 bytes in 153 msecs (HTTP/1.1 500) 2 headers in 92 bytes (1 switches on core 1)

How should I store an entity key in a webapp2 session?

I've been trying to use webapp2 to store user data in session.
I tried to store the Key of the parent object in session data:
self.session['client'] = client.key
But I keep getting a:
TypeError: Key('Client', 6401356696911872) is not JSON serializable
How should I store an entity key in a session?
My code fairly simple:
import os
import urllib
import logging
from google.appengine.api import users
from google.appengine.ext import ndb
import jinja2
import webapp2
from webapp2_extras import sessions
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
self.session_store = sessions.get_store(request=self.request)
try:
# dispatch the request
webapp2.RequestHandler.dispatch(self)
finally:
# save all sessions
import pdb; pdb.set_trace()
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
# Returns a session using the default cookie key.
return self.session_store.get_session()
JINJA_ENVIRONMENT = jinja2.Environment(
loader = jinja2.FileSystemLoader(os.path.dirname(__file__)),
extensions=['jinja2.ext.autoescape'],
autoescape=True)
DEFAULT_LEADBOOK_NAME = 'whatsmyname'
def leadbook_key(leadbook_name=DEFAULT_LEADBOOK_NAME):
"""Constructs a Datastore key for a LeadBook entity with leadbook_name."""
return ndb.Key('LeadBook', leadbook_name)
class Client(ndb.Model):
email = ndb.StringProperty()
name = ndb.StringProperty(indexed=True)
street1 = ndb.StringProperty()
street2 = ndb.StringProperty()
city = ndb.StringProperty()
zipcode = ndb.IntegerProperty()
phone = ndb.StringProperty()
signup = ndb.DateTimeProperty(auto_now_add=True)
# this just creates a Client to use
if not ( Client.query( Client.name == "Bryan Wheelock").get()):
logging.info("create Admin")
client = Client(
email = "bryan#mail.com",
name = "Bryan Wheelock",
street1 = "555 Main St",
street2 = "unit 1",
city = "Atlanta",
zipcode = 99999,
phone = "(888)555-1212"
).put()
class Customer(ndb.Model):
client = ndb.KeyProperty(kind=Client)
email = ndb.StringProperty(indexed=True)
name = ndb.StringProperty(indexed=True)
street1 = ndb.StringProperty()
street2 = ndb.StringProperty()
city = ndb.StringProperty()
zipcode = ndb.IntegerProperty()
phone = ndb.StringProperty()
signup = ndb.DateTimeProperty(auto_now_add=True)
class MainPage(BaseHandler):
def get(self):
leadbook_name = self.request.get('leadbook_name',
DEFAULT_LEADBOOK_NAME)
# This should be the Client record that shows the info of the owner of the local clinic
# the question is how do I get the site to show the correct Client?
client = Client.query( Client.name == "Bryan Wheelock").get()
self.session['client'] = client.key
template_values = {
'client': client,
'leadbook_name': urllib.quote_plus(leadbook_name),
}
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.write(template.render(template_values))
class LeadBook(webapp2.RequestHandler):
def post(self):
leadbook_name = self.request.get('leadbook_name',
DEFAULT_LEADBOOK_NAME)
client = self.session.get('client')
cl = Client.query(client.key )
customer = Customer( client = cl.key)
customer.name = self.request.get('id_name')
customer.street = self.request.get('id_street')
customer.phone = self.request.get('id_phone')
customer.zip = self.request.get('id_zip')
import pdb; pdb.set_trace()
# How can I see the number of Customers before and after save?
customer.put()
query_params = {'leadbook_name': leadbook_name}
self.redirect('/?' + urllib.urlencode(query_params))
config = {}
config['webapp2_extras.sessions'] = {
'secret_key': 'my-super-secret-key',
}
application = webapp2.WSGIApplication([
('/', MainPage),
('/sign', LeadBook),
], config = config,
debug=True)
Traceback (most recent call last):
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/Users/Bryan/work/GoogleAppEngine/dermalfillersecrets/main.py", line 22, in dispatch
self.session_store.save_sessions(self.response)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 420, in save_sessions
session.save_session(response)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 205, in save_session
response, self.name, dict(self.session), **self.session_args)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 423, in save_secure_cookie
value = self.serializer.serialize(name, value)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 47, in serialize
value = self._encode(value)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 92, in _encode
return json.b64encode(value)
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/json.py", line 84, in b64encode
return base64.b64encode(encode(value, *args, **kwargs))
File "/Users/Bryan/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2_extras/json.py", line 55, in encode
return json.dumps(value, *args, **kwargs).replace("</", "<\\/")
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 250, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Key('Client', 6401356696911872) is not JSON serializable
Use a urlsafe version of the key:
https://cloud.google.com/appengine/docs/python/ndb/entities#retrieving_entities
self.session['client'] = client.key.urlsafe()
On retrieval, use
client = ndb.Key(urlsafe=self.session['client']).get()

Resources