Running ApiSpec with Flask and Swagger UI - rest

I am trying to render my API's in Swagger. I am using ApiSpec library to generate the Open Api Spec, which then I trying to add into my Swagger UI. I am trying to use MethodView available in Flask with the following code below.
from flask.views import MethodView
from flask import Blueprint, after_this_request, make_response
test_data = Blueprint('test', __name__, url_prefix='/testdata')
class TestDataApi(MethodView):
def get():
"""Get all TestData.
---
description: Get a random data
security:
- ApiKeyAuth: []
responses:
200:
description: Return all the TestData
content:
application/json:
schema: TestDataSchema
headers:
- $ref: '#/components/headers/X-Total-Items'
- $ref: '#/components/headers/X-Total-Pages'
"""
data = TestData.query.all()
response_data = test_schema.dump(data)
resp = make_response(json.dumps(response_data), 200)
return resp
This is my app.py where I am trying to register swagger and corresponding views:
api = Blueprint('api', __name__, url_prefix="/api/v0")
spec = APISpec(
title='Test Backend',
version='v1',
openapi_version='3.0.2',
plugins=[MarshmallowPlugin(), FlaskPlugin()],
)
api.register_blueprint(test_data)
app.register_blueprint(api)
test_view = TestDataApi.as_view('test_api')
app.add_url_rule('/api/v0/testdata/', view_func=test_view, methods=['GET',])
spec.components.schema("TestData", schema=TestDataSchema)
spec.path(view=test_view, operations=dict(get={}))
SWAGGER_URL = '/api/v0/docs'
API_URL = 'swagger.json'
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "Backend"
})
app.register_blueprint(swaggerui_blueprint)
But I keep hitting this below error and I am not able to deduce how to fix it.
File "/home/hh/Projects/testdata/src/goodbytz_app.py", line 29, in <module>
app = create_app()
File "/home/hh/Projects/testdata/src/app.py", line 100, in create_app
spec.path(view=additives_view, operations=dict(get={}))
File "/home/hh/Projects/testdata/test_poc/lib/python3.10/site-packages/apispec/core.py", line 516, in path
plugin.operation_helper(path=path, operations=operations, **kwargs)
File "/home/hh/Projects/testdata/test_poc/lib/python3.10/site-packages/apispec/ext/marshmallow/__init__.py", line 218, in operation_helper
self.resolver.resolve_operations(operations)
File "/home/hh/Projects/testdata/test_poc/lib/python3.10/site-packages/apispec/ext/marshmallow/schema_resolver.py", line 34, in resolve_operations
self.resolve_response(response)
File "/home/hh/Projects/testdata/test_poc/lib/python3.10/site-packages/apispec/ext/marshmallow/schema_resolver.py", line 183, in resolve_response
if "headers" in response:
TypeError: argument of type 'NoneType' is not iterable

can try this one, more simple and its automatically generate openapi/swagger https://pypi.org/project/flask-toolkits/

Related

Error in saving data to mongodb database using flask

I am using a mongodb database with my app in Flask, and I am connecting it to the app with pymongo.
I am having an issue while trying to save documents in my mongodb database, see the error below :
127.0.0.1 - - [01/Oct/2019 15:56:47] "POST /movie HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/lancelot/.local/lib/python3.6/site-packages/pymongo/mongo_client.py", line 1385, in _retry_with_session
return func(session, sock_info, retryable)
File "/home/lancelot/.local/lib/python3.6/site-packages/pymongo/collection.py", line 595, in _insert_command
retryable_write=retryable_write)
File "/home/lancelot/.local/lib/python3.6/site-packages/pymongo/pool.py", line 613, in command
user_fields=user_fields)
File "/home/lancelot/.local/lib/python3.6/site-packages/pymongo/network.py", line 167, in command
parse_write_concern_error=parse_write_concern_error)
File "/home/lancelot/.local/lib/python3.6/site-packages/pymongo/helpers.py", line 159, in _check_command_response
raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: Transaction numbers are only allowed on storage engines that support document-level locking
This is my views function which is catching the post request :
#app.route('/movie', methods = ['GET','POST'])
def add_movie():
movie = mongo.db.movies
try :
name = request.json['name']
print(name)
movie_id = movie.insert({'name':name})
new_movie = movie.find_one({'_id': movie_id })
output = {'name' : new_movie['name']}
return jsonify({'result' : output})
except TypeError:
return jsonify({'result' : 'niet'})
and my POST request is made with an AJAX request in one of my template :
$(document).ready(function() {
$('#movies_btn').click(function() {
$.ajax({
url: "{{ url_for('add_movie') }}",
type: 'POST',
contentType: 'application/json;charset=UTF-8',
data: JSON.stringify({'name':'oui'}),
success: res => {
alert('stop')
window.location.href="{{ url_for('index') }}"
},
error: xhr => {
alert(xhr.responseText.split('\n')[1])
}
})
})
})
Can you help me with this issue? I tried to look at the documentation of flask pymongo but I don't find the answer.
Thanks

Redirection using Scrapy Spider Middleware (Unhandled error in Deferred)

I've made a spider using Scrapy that first solves a CAPTCHA in a redirected address before accessing the main website I intend to scrape. It says that I have an HTTP error causing an infinite loop but I can't find which part of the script is causing this.
In the middleware:
from scrapy.downloadermiddlewares.redirect import RedirectMiddleware
class ProtectRedirectMiddleware(RedirectMiddleware):
def __init__(self, settings):
super().__init__(settings)
self.source = urllib.request.urlopen('http://sampleurlname.com/')
soup = BeautifulSoup(source, 'lxml')
def _redirect(self, redirected, request, spider, reason):
# act normally if this isn't a CAPTCHA redirect
if not self.is_protected(redirected.url):
return super()._redirect(redirected, request, spider, reason)
# if this is a CAPTCHA redirect
logger.debug(f'The protect URL is triggered for {request.url}')
request.cookies = self.bypass_protection(redirected.url)
request.dont_filter = True
return request
def is_protected(self, url):
return 'sampleurlname.com/protect' in url
def bypass_protection(self, url=None):
# only navigate if any explicit url is provided
if url:
url = url or self.source.geturl(url)
img = soup.find_all('img')[0]
imgurl = img['src']
urllib.request.urlretrieve(imgurl, "captcha.png")
return self.solve_captcha(imgurl)
# wait for the redirect and try again
self.wait_for_redirect()
return self.bypass_protection()
def wait_for_redirect(self, url = None, wait = 0.1, timeout=10):
url = self.url
for i in range(int(timeout//wait)):
time.sleep(wait)
if self.response.url() != url:
return self.response.url()
logger.error(f'Maybe {self.response.url()} isn\'t a redirect URL')
raise Exception('Timed out')
def solve_captcha(self, img, width=150, height=50):
# open image
self.img = 'captcha.png'
img = Image.open("captcha.png")
# image manipulation - simplified
# input the captcha text - simplified
# click the submit button - simplified
# save the URL
url = self.response.url()
# try again if wrong
if self.is_protected(self.wait_for_redirect(url)):
return self.bypass_protection()
# return the cookies as a dict
cookies = {}
for cookie_string in self.response.css.cookies():
if 'domain=sampleurlname.com' in cookie_string:
key, value = cookie_string.split(';')[0].split('=')
cookies[key] = value
return cookies
Then, this is the error I get when I run the scrapy crawl of my spider:
Unhandled error in Deferred:
2018-08-06 16:34:33 [twisted] CRITICAL: Unhandled error in Deferred:
2018-08-06 16:34:33 [twisted] CRITICAL:
Traceback (most recent call last):
File "/username/anaconda/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
File "/username/anaconda/lib/python3.6/site-packages/scrapy/crawler.py", line 80, in crawl
self.engine = self._create_engine()
File "/username/anaconda/lib/python3.6/site-packages/scrapy/crawler.py", line 105, in _create_engine
return ExecutionEngine(self, lambda _: self.stop())
File "/username/anaconda/lib/python3.6/site-packages/scrapy/core/engine.py", line 69, in __init__
self.downloader = downloader_cls(crawler)
File "/username/anaconda/lib/python3.6/site-packages/scrapy/core/downloader/__init__.py", line 88, in __init__
self.middleware = DownloaderMiddlewareManager.from_crawler(crawler)
File "/username/anaconda/lib/python3.6/site-packages/scrapy/middleware.py", line 58, in from_crawler
return cls.from_settings(crawler.settings, crawler)
File "/username/anaconda/lib/python3.6/site-packages/scrapy/middleware.py", line 36, in from_settings
mw = mwcls.from_crawler(crawler)
File "/username/anaconda/lib/python3.6/site-packages/scrapy/downloadermiddlewares/redirect.py", line 26, in from_crawler
return cls(crawler.settings)
File "/username/...../scraper/myscraper/myscraper/middlewares.py", line 27, in __init__
self.source = urllib.request.urlopen('http://sampleurlname.com/')
File "/username/anaconda/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 532, in open
response = meth(req, response)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 642, in http_response
'http', request, response, code, msg, hdrs)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 564, in error
result = self._call_chain(*args)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 756, in http_error_302
return self.parent.open(new, timeout=req.timeout)
File "/username/anaconda/lib/python3.6/urllib/request.py", line 532, in open
It basically repeats the bottom part of these over and over: open, http_response, error, _call_chain, and http_error_302, until these show at the end:
File "/username/anaconda/lib/python3.6/urllib/request.py", line 746, in http_error_302
self.inf_msg + msg, headers, fp)
urllib.error.HTTPError: HTTP Error 307: The HTTP server returned a redirect error that would lead to an infinite loop.
The last 30x error message was:
Temporary Redirect
In setting.py is:
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': None,
'myscrape.middlewares.ProtectRedirectMiddleware': 600}
Your issue has nothing to do with scrapy itself. You are using blocking requests in your middleware initiation.
This request seems to be stuck in a redirect loop. This usually happens when websites do not act appropriately and require cookies to allow you through:
First you connect and get a redirect response 30x and some setCokies headers
You redirect again but not with Cookies headers and the page lets you through
Python urllib doesn't handle cookies, so try this:
import urllib
from http.cookiejar import CookieJar
def __init__(self):
try:
req=urllib.request.Request(url)
cj = CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
response = opener.open(req)
source = response.read().decode('utf8', errors='ignore')
response.close()
except urllib.request.HTTPError as e:
logging.error(f"couldn't initiate middleware: {e}")
return
# you should use scrapy selectors instead of beautiful soup here
#soup = BeautifulSoup(source, 'lxml')
selector = Selector(text=source)
Alternatively you should use requests package that handles cookies by itself.

Integrate djongo (Mongo ORM) into Django Rest Framework

Actually I am developping a POC on which we want an app which has a REST API and discuss with MongoDB in Python.
For this we found several techs, such as Django-rest-framework for the API side and djongo for the ORM side. Nevertheless, I scan lots of tutos on how to implement djongo ORM in DRF, no way there is nothing BUT apparently it's possible, can someone confirm?
My main problem is my POC does absolutely not work, indeed, in used djongo models in my DRF Serializers but it does not work at all, I dont understand, can someone figure it out whats going on?:
models.py:
from djongo import models
class Channel(models.Model):
sourceId = models.IntegerField(default=-1)
usageId = models.IntegerField(default=0)
channelId = models.IntegerField(default=0)
cabinetId = models.IntegerField(default=0)
zoneId = models.IntegerField(default=0)
class Product(models.Model):
dateCreation = models.DateTimeField(auto_now=True)
dateUpdate = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=50, default="Unknown product name")
channels = models.EmbeddedModelField(
model_container=Channel,
)
objects = models.DjongoManager()
views.py:
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from Api.models import Product
from Api.serializers import ProductSerializer
#csrf_exempt
def ProductList(aRequest):
"""
#brief List all products, or create a new product.
"""
if aRequest.method == 'GET':
wProducts = Product.objects.all()
wSerializer = ProductSerializer(wProducts, many=True)
return JsonResponse(wSerializer.data, safe=False)
elif aRequest.method == 'POST':
data = JSONParser().parse(aRequest)
wSerializer = ProductSerializer(data=data)
if wSerializer.is_valid():
wSerializer.save()
return JsonResponse(wSerializer.data, status=201)
return JsonResponse(wSerializer.errors, status=400)
#csrf_exempt
def ProductDetail(aRequest, pk):
"""
#brief Retrieve, update or delete a product.
"""
try:
wProducts = Product.objects.get(pk=pk)
except Product.DoesNotExist:
return HttpResponse(status=404)
if aRequest.method == 'GET':
wSerializer = ProductSerializer(wProducts)
return JsonResponse(wSerializer.data)
elif aRequest.method == 'PUT':
data = JSONParser().parse(aRequest)
wSerializer = ProductSerializer(wProducts, data=data)
if wSerializer.is_valid():
wSerializer.save()
return JsonResponse(wSerializer.data)
return JsonResponse(wSerializer.errors, status=400)
elif aRequest.method == 'DELETE':
Product.delete()
return HttpResponse(status=204)
serializers.py:
from rest_framework import serializers
from Api.models import Product, Channel
class ChannelSerializer(serializers.ModelSerializer):
class Meta:
model = Channel
fields = ('sourceId', 'usageId', 'channelId', 'cabinetId', 'zoneId')
def create(self, validated_data):
wChannel = Channel.objects.create(**validated_data)
return wChannel
class ProductSerializer(serializers.ModelSerializer):
channels = ChannelSerializer(many=True)
class Meta:
model = Product
fields = ('dateCreation', 'dateUpdate', 'name', 'channels')
def create(self, validated_data):
wChannels = validated_data.pop("channels")
wProduct = Product.objects.create(**validated_data)
for wChannel in wChannels:
Channel.objects.create(product=wProduct, **wChannel)
return wProduct
When I run my server with this POST request:
{
"dateCreation": "2018-07-20 12:00:00.000",
"dateUpdate": "2018-07-20 12:00:00.000",
"name": "post_test_channel_1",
"channels": [{
"sourceId": -1,
"usageId": 100,
"channelId": 0,
"cabinetId": 0,
"zoneId": 1
}]
}
I obtain that stacktrace:
Internal Server Error: /products/
Traceback (most recent call last):
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/soulasb/projects/POC/PocEms/Api/views.py", line 25, in ProductList
wSerializer.save()
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/home/soulasb/projects/POC/PocEms/Api/serializers.py", line 29, in create
wProduct = Product.objects.create(**validated_data)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/query.py", line 417, in create
obj.save(force_insert=True, using=self.db)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/base.py", line 729, in save
force_update=force_update, update_fields=update_fields)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/base.py", line 759, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/base.py", line 842, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/base.py", line 880, in _do_insert
using=using, raw=raw)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/query.py", line 1125, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1284, in execute_sql
for sql, params in self.as_sql():
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1237, in as_sql
for obj in self.query.objs
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1237, in <listcomp>
for obj in self.query.objs
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1236, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1176, in prepare_value
value = field.get_db_prep_save(value, connection=self.connection)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 767, in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False)
File "/home/soulasb/projects/POC/venv-app/lib/python3.6/site-packages/djongo/models/fields.py", line 461, in get_db_prep_value
model=Model
ValueError: Value: None must be instance of Model: <class 'django.db.models.base.Model'>
This usually happens when you have added an EmbeddedModelField in your model and not passing an object to this field while creating an entry to this model.
I didnt find an option to add an EmbeddedModelField with null=True option.
Hope this helps someone
It could be the ENFORCE_SCHEMA set to true in settings.py. Maybe change it to "ENFORCE_SCHEMA: false".

AttributeError 'IdLookup' object has no attribute 'rel'

I try to use the django REST-framework's tutorial http://django-rest-framework.org/#django-rest-framework to administrate users. (I also use the Neo4j database and the neo4django mapper https://github.com/scholrly/neo4django to acces data via python.)
Whatever, wen I call localhost:8000/users an AttributeError appears.
models.py
from django.utils import timezone
from django.conf import settings
from django.contrib.auth import models as django_auth_models
from ..db import models
from ..db.models.manager import NodeModelManager
from ..decorators import borrows_methods
class UserManager(NodeModelManager, django_auth_models.UserManager):
pass
# all non-overriden methods of DjangoUser are called this way instead.
# inheritance would be preferred, but isn't an option because of conflicting
# metaclasses and weird class side-effects
USER_PASSTHROUGH_METHODS = (
"__unicode__", "natural_key", "get_absolute_url",
"is_anonymous", "is_authenticated", "get_full_name", "set_password",
"check_password", "set_unusable_password", "has_usable_password",
"get_group_permissions", "get_all_permissions", "has_perm", "has_perms",
"has_module_perms", "email_user", 'get_profile','get_username')
#borrows_methods(django_auth_models.User, USER_PASSTHROUGH_METHODS)
class User(models.NodeModel):
objects = UserManager()
username = models.StringProperty(indexed=True, unique=True)
first_name = models.StringProperty()
last_name = models.StringProperty()
email = models.EmailProperty(indexed=True)
password = models.StringProperty()
is_staff = models.BooleanProperty(default=False)
is_active = models.BooleanProperty(default=False)
is_superuser = models.BooleanProperty(default=False)
last_login = models.DateTimeProperty(default=timezone.now())
date_joined = models.DateTimeProperty(default=timezone.now())
USERNAME_FIELD = 'username'
REQUIRED_FIELDS=['email']
serializers.py
from neo4django.graph_auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email')
views.py
from neo4django.graph_auth.models import User
from rest_framework import viewsets
from api.serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
I get this:
Environment:
Request Method: GET
Request URL: http://localhost:8000/users/
Django Version: 1.5.3
Python Version: 2.7.3
Installed Applications:
('core.models',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'neo4django.graph_auth',
'rest_framework')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/opt/phaidra/env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
115. response = callback(request, *callback_args, **callback_kwargs)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
78. return self.dispatch(request, *args, **kwargs)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
77. return view_func(*args, **kwargs)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
399. response = self.handle_exception(exc)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
396. response = handler(request, *args, **kwargs)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list
92. serializer = self.get_pagination_serializer(page)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/generics.py" in get_pagination_serializer
113. return pagination_serializer_class(instance=page, context=context)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/pagination.py" in __init__
85. self.fields[results_field] = object_serializer(source='object_list', **context_kwarg)
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/serializers.py" in __init__
162. self.fields = self.get_fields()
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/serializers.py" in get_fields
198. default_fields = self.get_default_fields()
File "/opt/phaidra/env/local/lib/python2.7/site-packages/rest_framework/serializers.py" in get_default_fields
599. while pk_field.rel and pk_field.rel.parent_link:
Exception Type: AttributeError at /users/
Exception Value: 'IdLookup' object has no attribute 'rel'
I am rather new on the Python/Django/REST service area. I hope someone could help. Thanks in advance.
Firstly I would recommend to either use Tastypie - which is out of the box supported by neo4django - instead of Django Rest Framework - or use Django Rest Framework Serializer instead of the ModelSerializer or (worst choice in my opinion) HyperlinkedModelSerializer.
As for the error you get, the problem is that neo4django does not return the record id, therefore you get the error.
One solution is to override the restore_object function, like this, to include the ID.
# User Serializer
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField()
username = serializers.CharField(max_length=30)
first_name = serializers.CharField(max_length=30)
last_name = serializers.CharField(max_length=30)
email = serializers.EmailField()
password = serializers.CharField(max_length=128)
is_staff = serializers.BooleanField()
is_active = serializers.BooleanField()
is_superuser = serializers.BooleanField()
last_login = serializers.DateTimeField()
date_joined = serializers.DateTimeField()
def restore_object(self, attrs, instance=None):
"""
Given a dictionary of deserialized field values, either update
an existing model instance, or create a new model instance.
"""
if instance is not None:
instance.id = attrs.get('ID', instance.pk)
instance.username = attrs.get('Username', instance.username)
instance.first_name = attrs.get('First Name', instance.first_name)
instance.last_name = attrs.get('First Name', instance.last_name)
instance.email = attrs.get('email', instance.email)
instance.password = attrs.get('Password', instance.password)
instance.is_staff = attrs.get('Staff', instance.is_staff)
instance.is_active = attrs.get('Active', instance.is_active)
instance.is_superuser = attrs.get('Superusers', instance.is_superuser)
instance.last_login = attrs.get('Last Seen', instance.last_login)
instance.date_joined = attrs.get('Joined', instance.date_joined)
return instance
return User(**attrs)
But I still think it's better to use Tastypie with ModelResource.
Here's a gist by Matt Luongo (or Lukas Martini ?) https://gist.github.com/mhluongo/5789513
TIP. Where Serializer in Django Rest Framework, is Resource in Tastypie and always make sure you are using the github version of neo4django (pip install -e git+https://github.com/scholrly/neo4django/#egg=neo4django)

Error with OAuth in the Google Data Protocol Client Libraries

When I was testing the code in "OAuth in the Google Data Protocol Client Libraries (http://code.google.com/apis/gdata/docs/auth/oauth.html)", I always got the following error. Anyone can give me a hint?
Error Code:
File "D:\PROJ\GAE\proj2\proj2.py", line 262, in get
return self.redirect(auth_url)
File "C:\DEV\google_appengine\v1.4.2\google\appengine\ext\webapp\__init__.py", line 380, in redirect
absolute_url = urlparse.urljoin(self.request.uri, uri)
File "C:\DEV\Python\v2.5.4\lib\urlparse.py", line 253, in urljoin
urlparse(url, bscheme, allow_fragments)
File "C:\DEV\Python\v2.5.4\lib\urlparse.py", line 154, in urlparse
tuple = urlsplit(url, scheme, allow_fragments)
File "C:\DEV\Python\v2.5.4\lib\urlparse.py", line 193, in urlsplit
i = url.find(':')
AttributeError: 'Uri' object has no attribute 'find'
Here is the code I want to fetch Google contacts info:
class Test(webapp.RequestHandler):
def get(self):
client = gdata.contacts.client.ContactsClient(source = 'www.mydomainname.com')
callback_url = 'http://%s/test2' % self.request.host
request_token = client.GetOAuthToken(['http://www.google.com/m8/feeds/'],
callback_url,
GOOGLE_KEY,
GOOGLE_SECRET)
gdata.gauth.AeSave(request_token, 'request_token')
auth_url = request_token.generate_authorization_url(google_apps_domain = None)
return self.redirect(auth_url) #Error?!
Thanks in advance!
The auth_url generated is not a string.
Just do:
return self.redirect(str(auth_url))
and it will work.