Serialize data in django restframework - python

I get this following data through a POST request in Django restframework.
I need to serialize this data and this data contains data for multiple models.
data={'admin-1':
{'first_name':'john'
,'last_name':'white'
,'job_title':'CEO'
,'email':'test1#gmail.com'
},
'admin-2':
{'first_name':'lisa'
,'last_name':'markel'
,'job_title':'CEO'
,'email':'test2#gmail.com'
},
'company-detail':{'description':'We are a renowned engineering company'
,'size':'1-10'
,'industry':'Engineering'
,'url':'http://try.com'
,'logo':''
,'addr1':'1280 wick ter'
,'addr2':'1600'
,'city':'rkville'
,'state':'md'
,'zip_cd':'12000'
,'phone_number_1':'408-393-254'
,'phone_number_2':'408-393-221'}
r = requests.post('http://127.0.0.1:8000/api/create-company-profile/',data=data)
print r.status_code
print r.text
Here is the CreateAPI view -
class CompanyCreateApiView(CreateAPIView):
def post(self, request, *args, **kwargs):
print 'request ==', request
print 'request.data == ', request.data['admin-2']
import json
print json.loads(request.data)
data=json.dumps({'status':'success'})
return Response(data, status=status.HTTP_200_OK)
I basically need to de-serialize the data but get this error.
request ==
request.data == job_title
Internal Server Error: /api/create-company-profile/
Traceback (most recent call last):
File "/Users/prem/.virtualenvs/ghost/lib/python2.7/site-packages/django/core/handlers/base.py",
line 111, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/prem/.virtualenvs/ghost/lib/python2.7/site-packages/django/views/decorators/csrf.py",
line 57, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/prem/.virtualenvs/ghost/lib/python2.7/site-packages/django/views/generic/base.py",
line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/prem/.virtualenvs/ghost/lib/python2.7/site-packages/rest_framework/views.py",
line 452, in dispatch
response = self.handle_exception(exc)
File "/Users/prem/.virtualenvs/ghost/lib/python2.7/site-packages/rest_framework/views.py",
line 449, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/prem/Documents/Ghost/positionmatch-new/menkes-server-master/menkesserver/human_resources/views.py",
line 81, in post
print json.loads(request.data)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/init.py",
line 338, in loads
return _default_decoder.decode(s)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py",
line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer

There should be no need to manually decode the POST data in your view. As long as you are using the JSONParser, as described in the parsers documentation, request.data should already be fully parsed for you.
Additionally, it looks like the request you're sending to the view is probably not acting how you think. If you want to send JSON data with requests, you need to be a little more explicit. As shown in the example in the requests documentation:
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))

Related

Access cleaned data from django admin for pdf processing

As a newbie, I am currently trying to add a print button to every existing django admin view of a project.
The goal is to make it not depend on a single model I could resolve manually for printing but every existing model which contains foreign keys to other models an so on.
For simplicity I thought it would be the best to just get the cleaned_data of the form and process it for the pdf.
I alread added the print button, the path url and so on and it will create a pdf file for me.
What I am not able to do is to access the forms cleaned_data from my BaseAdmins (extends the ModelAdmin) class like this:
form = BaseForm(request.POST)
if form.is_valid():
data = form.cleaned_data
It will just give me random kinds of errors, like object has no attribute 'is_bound'
So I think that I am generally wrong with the context where I am trying to get the cleaned_data from the form. Every tutorial I found is just showing how to get the data but not fully resolved if it contains foreign keys and not in which context.
Could you please clear up for me where it would make sense to pass any kind of form data maybe as session data or post body to a print view where I can process it.
Thank you very much for reading, hope I was able to describe my problem, feel free to ask.
Edit
This is the BaseForm I changed variable names for internal reasons:
class BaseForm(ModelForm):
def clean_custom(self):
another_model = self.cleaned_data.get('AnotherModel')
custom_models = self.cleaned_data.get('CustomModel')
custom_models_allowed = CustomModel.objects.filter(AnotherModel=another_model)
custom_models_was_list = True
if not custom_models:
return
if not isinstance(custom_models, Iterable):
custom_models_was_list = False
custom_models = [custom_models]
for custom_model in custom_models:
if another_model and custom_model not in custom_models_allowed:
custom_models_allowed = [custom_model.titel for custom_model in custom_models_allowed]
custom_models_allowed = ', '.join(custom_models_allowed)
raise ValidationError(
f'{custom_model} is not part of {another_model}. For selection: {custom_models_allowed}'
)
if custom_models_was_list:
return custom_models
else:
return custom_models[0]
I'm trying to add cleaned_data in my BaseAdmin class where I have access to request and get the following trace:
AttributeError
AttributeError: type object 'CustomForm' has no attribute 'is_bound'
Traceback (most recent call last)
File ".../.env/lib/python3.9/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
return self.application(environ, start_response)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/wsgi.py", line 141, in __call__
response = self.get_response(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 75, in get_response
response = self._middleware_chain(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 36, in inner
response = response_for_exception(request, exc)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File ".../.env/lib/python3.9/site-packages/django_extensions/management/technical_response.py", line 40, in null_technical_500_response
raise exc_value.with_traceback(tb)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../.env/lib/python3.9/site-packages/django/contrib/admin/options.py", line 606, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/contrib/admin/sites.py", line 223, in inner
return view(request, *args, **kwargs)
File ".../admin/base_admin.py", line 203, in change_view
if self.form.is_valid(self.form):
File ".../.env/lib/python3.9/site-packages/django/forms/forms.py", line 185, in is_valid
return self.is_bound and not self.errors
AttributeError: type object 'CustomForm' has no attribute 'is_bound'
This is not a standard question format, you are supposed to give us the code for the piece of code where the error occurs, (i.e. the base_admin.py file) but what you have provided is just 3 lines of it.
But so far I can see you are not checking whether the request is of the type of post or not. Pay attention to the if condition at the beginning of the method
def edit(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = PurposeForm(request.POST)
# check whether it's valid:
if form.is_valid():
for key, value in form.cleaned_data.items():
# etc

user_id = getattr(user, api_settings.USER_ID_FIELD) AttributeError: 'str' object has no attribute 'id

I am trying to authenticate a user through their email using DRF but so far it's only errors i've been getting.
This is the class that handles the email verification
class VerifyEmail(GenericAPIView):
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY) # Decodes the user token and the secret key to get the user ID
print(payload)
user = User.objects.get(id=payload['user_id']) # Gotten the user ID
if not user.is_verified: # Runs an if statement to see if the user has been verified already
user.is_verified = True
user.save()
data = {"confirmation_message": "Your account has been verified"}
return Response(data, status=status.HTTP_200_OK)
except jwt.ExpiredSignatureError as identifier:
error = {"expired_activation_link": "The activation link has expired"}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
except jwt.DecodeError as identifier:
error = {"invalid_token": "The token is invalid request a new one"}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
and this is the error i keep getting
Internal Server Error: /auth/register
Traceback (most recent call last):
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/SRC/users/views.py", l
ine 43, in post
token = RefreshToken.for_user(user_email).access_token
File "/mnt/c/Users/Somtochukwu/Desktop/cultural-exchange/proj/lib/python3.8/sit
e-packages/rest_framework_simplejwt/tokens.py", line 161, in for_user
user_id = getattr(user, api_settings.USER_ID_FIELD)
AttributeError: 'str' object has no attribute 'id'
please how can i fix this?
In your views.py Line 43,
token = RefreshToken.for_user(user_email).access_token
This is wrong because the RefreshToken.for_user() method accepts a User object as argument and not a string and that's why you are getting that error.
Reference to for_user docs..
You can also see the relevant RefreshToken.for_user method's code on their github here.

How to pass json to render_to_response

I am trying to pass a json file through render_to_response to the front end. The front end is not a django template, its coded in JS, HTML etc. I am getting some weird error. Can anybody help me with that. I am attaching the code and the traceback.
return render_to_response('ModelView.html', json.dumps(newDict))
Traceback (most recent call last):
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\PythonWorkspace\ScApp\ScApp2\views.py", line 78, in ScorecardApp20
return render_to_response('ModelView.html', json.dumps(newDict))
File "C:\Users\kxc89\AppData\Local\Programs\Python\Python37\lib\site-packages\django\shortcuts.py", line 27, in render_to_response
content = loader.render_to_string(template_name, context, using=using)
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\template\loader.py", line 62, in render_to_string
return template.render(context, request)
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\template\backends\django.py", line 59, in render
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\django\template\context.py", line 274, in make_context
raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
TypeError: context must be a dict rather than str.
Don’t use render_to_response, it’s obsolete. Use render instead.
return render(request, 'ModelView.html', {'new_dict': json.dumps(newDict)})
The third argument has to be a dictionary, so you can either add the json string to the dictionary as I have done above, or perhaps you don’t want to use json.dumps() at all and just use newDict.
Use the code below
import json
data = open('/static/JsonFile.json').read() #opens the json file and saves the raw contents
JsonData = json.dumps(data) #converts to a json structure
context = {'obj': JsonData}
return render(request, 'templates', context)
Hope it should work !

DRF - 'str' object has no attribute 'pk'

I've got a front-end that sends JSON to the back-end to switch the input of a digital audio stream, with an optional time component to schedule the switch for the future. Here are the components of making this work:
from views.py:
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if stream.schedule_time is None:
tasks.switch_stream(stream.mnemonic, stream.current_input)
else:
tasks.schedule_switch(stream.mnemonic, stream.current_input, stream.schedule_time)
return HttpResponse('')
from serializers.py:
class RadioSwitchSerializer(serializers.ModelSerializer):
schedule_time = serializers.SerializerMethodField()
def get_schedule_time(self, obj):
return obj.get('schedule_time', None)
class Meta:
model = RadioStream
fields = ('mnemonic', 'current_input', 'schedule_time')
The issue I'm having is that however I try and send a test JSON snippet, I'm getting errors. With this setup, sending
[
{
"mnemonic": "TEST",
"current_input": "TEST"
}
]
results in the error 'str' object has no attribute 'pk', but if I change RadioSwitchSerializer(data=request.data, many=True) to many=False, and send
{
"mnemonic": "TEST",
"current_input": "TEST"
}
I get the response 'str' object has no attribute 'schedule_time' instead.
My plan was to use mnemonic to identify the stream, and current_input to identify which input to switch it to. My questions are; Why is this not working, and should I be using a non-Model serializer for this custom action instead of trying to fit the action into the existing fields of the model?
Edit: Here is the traceback
Internal Server Error: /api/switch/
Traceback (most recent call last):
File "...\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "...\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "...\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "...\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "...\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "...\lib\site-packages\rest_framework\views.py", line 489, in dispatch
response = self.handle_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 449, in handle_exception
self.raise_uncaught_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 486, in dispatch
response = handler(request, *args, **kwargs)
File "...\radio_switching\views.py", line 45, in post
for stream in serializer.data:
File "...\lib\site-packages\rest_framework\serializers.py", line 738, in data
ret = super(ListSerializer, self).data
File "...\lib\site-packages\rest_framework\serializers.py", line 266, in data
self._data = self.get_initial()
File "...\lib\site-packages\rest_framework\serializers.py", line 573, in get_initial
return self.to_representation(self.initial_data)
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in to_representation
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in <listcomp>
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 500, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "...\lib\site-packages\rest_framework\relations.py", line 259, in to_representation
return value.pk
AttributeError: 'str' object has no attribute 'pk'
replace your views.py by this snippet,
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if 'schedule_time' not in stream:
tasks.switch_stream(stream['mnemonic'], stream['current_input'])
else:
tasks.schedule_switch(stream['mnemonic'], stream['current_input'], stream['schedule_time'])
return HttpResponse('')
The reason for the error is, you are trying to access a python dict using dot operator. To access dictionary elements, you can use the familiar square brackets along with the key to obtaining it's value. Here is the official doc
EDIT
AttributeError: 'str' object has no attribute 'pk' this error because, somewhere you trying to access .pk from a str object
Reproducing the error
In [7]: my_str = 'this is just a string'
In [8]: my_str.pk
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-5bc39c990550> in <module>()
----> 1 my_str.pk
AttributeError: 'str' object has no attribute 'pk'
There were a few issues, but it turns out the root issue was that serlializer.data was for whatever reason returning a string and not an array of objects. I ended up replacing the ModelSerializer with a regular Serializer here:
class RadioSwitchSerializer(serializers.Serializer):
mnemonic = serializers.CharField(max_length=20)
new_input = serializers.CharField(max_length=20)
schedule_time = serializers.DateTimeField(allow_null=True)
As per Jerin's answer, I also fixed up the lines accessing the stream dictionary to use square brackets rather than the dot operator. These two things have fixed the issue.

django can't serialize non-model on post

New to django and trying to send an list of id's to the server to update some information. I do not want them to be a model class, theres no need for it. What I am trying to do is put them into a serializer to make sure they are "clean". Here is my code:
View Class:
class Update_Cards(APIView):
# This seems necessary or it will throw an error
queryset = Card.objects.all()
def post(self, request, board_id, format=None):
print request.DATA
serializer = CardMoveSerializer(data=request.DATA, many=True)
#this throws an error
print serializer.data
return Response(serializer.data)
Serializer:
class CardMoveSerializer(serializers.Serializer):
card_id = serializers.IntegerField()
lane_id = serializers.IntegerField()
Error I get:
[{u'lane_id': 21, u'card_id': 3}] #this is to show the data is coming across the wire
Internal Server Error: /api/board/2/updateCards
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/django/views/decorators/csrf.py", line 77, in wrapped_view
return view_func(*args, **kwargs)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 327, in dispatch
response = self.handle_exception(exc)
File "/Library/Python/2.7/site-packages/rest_framework/views.py", line 324, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/crob/Documents/workspace/tlckanban/python/rest/views.py", line 37, in post
print card_moves.data
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py", line 499, in data
self._data = [self.to_native(item) for item in obj]
TypeError: 'NoneType' object is not iterable
What I have done is implemented this with a simplejson parser for now, but I feel like its not the best way to do it:
def update_cards(request, board_id):
json_data = simplejson.loads(request.body)
for moveIndex in range(0, len(json_data)):
#do some work
return JSONResponse(json_data, status=status.HTTP_200_OK)
Thanks for the help in advance!
You need to be accessing 'serializer.is_valid()' before accessing the data. Looks like there's a missing bit of API there - serializer.data should probably raise an expection if its accessed before validation.
Seems you are not using Django's serializers but anyway serialization is not made for validation. Use forms to validate your data then use json as you do to serialize it. Django's serializers are for querysets and models only.

Categories

Resources