Adding 'Value Example' to swagger, using flask-restx - flask

how can i add 'value example' (like on picture 3) to swagger documentation (picture 4 is that where i want to put 'value example' in) without using decorator marshall_with/marshall_list_with? Cuz the function got two responses depending on two endpoints

You can use the model to define an example, like this:
...
# define model with example
example_response = api.model('ExampleResponse', {
'field_you_want': fields.String(example="Example Value")
})
#api.route("/")
class Example(Resource):
#api.marshal_with(example_response)
def get(self):
response = get_response()
return response, 200
...

Related

`op_name` parameter for `graphene_django`

The django graphene documentation shows a test example like this:
class MyFancyTestCase(GraphQLTestCase):
def test_some_query(self):
response = self.query(
'''
query {
myModel {
id
name
}
}
''',
op_name='myModel'
)
content = json.loads(response.content)
# This validates the status code and if you get errors
self.assertResponseNoErrors(response)
# Add some more asserts if you like
...
They don't have any API documentation for what op_name is, and what we should set it as. I tried to set it to my query name, but get the error:
[{'message': 'Unknown operation named "myQuery".'}]
Operation name is only needed when there are multiple operations in the query string. You only have one operation so the default (None) is fine.
https://docs.graphene-python.org/en/latest/execution/execute/#operation-name
As per my comment:
If the query is a mutation or named query, you must supply the op_name. For annon queries ("{ ... }"), should be None (default)
I am not sure how to create a "named query" with django graphene, but apparently my query is NOT a named query. Leaving op_name as None got my query to work via my unit test.

Graphene-Django - how to pass an argument from Query to class DjangoObjectType

First of all, thanks ! it has been 1 year without asking question as I always found an answer. You're a tremendous help.
Today, I do have a question I cannot sort out myself.
Please, I hope you would be kind enough to help me on the matter.
Context: I work on a project with Django framework, and I have some dynamic pages made with react.js. The API I'm using in between is graphQL based. Apollo for the client, graphene-django for the back end.
I want to do a dynamic pages made from a GraphQL query having a set (a declared field in the class DjangoObjectType made from a Django query), and I want to be able to filter dynamically the parent with a argument A, and the set with argument B. My problem is how to find a way to pass the argument B to the set to filter it.
The graphQL I would achieved based on graphQL documentation
query DistributionHisto
(
$id:ID,
$limit:Int
)
{
distributionHisto(id:$id)
{
id,
historical(limit:$limit)
{
id,
date,
histo
}
}
}
But I don't understand how to pass (limit:$limit) to my set in the back end.
Here my schema.py
import graphene
from graphene_django.types import DjangoObjectType
class DistributionType(DjangoObjectType):
class Meta:
model = DistributionTuple
historical = graphene.List(HistoricalTimeSeriesType)
def resolve_historical(self, info):
return HistoricalTimeSeries.objects.filter(
distribution_tuple_id=self.id
).order_by('date')[:2]
class Query(object):
distribution_histo = graphene.List(
graphene.NonNull(DistributionType),
id=graphene.ID(),
limit=graphene.Int()
)
def resolve_distribution_histo(
self, info, id=None, limit=None):
filter_q1 = {'id': id} if id else {}
return DistributionTuple.objects.filter(**filter_q1)
I have tried few things, but I didn't find a way to make it to work so far.
At the moment, as you see, the arg "limit" reaches a dead end in def resolve*, where ideally, it would be pass up to the class DistributionSetHistoType where it would replace the slice [:2] by [:limit] in resolve_distribution_slice_set()
I hope I have been clear, please let me know if it's not the case.
Thanks for your support.
This topic called pagination.
front end seletion
const { loading, error, data, fetchMore } = useQuery(GET_ITEMS, {
variables: {
offset: 0,
limit: 10
},
});
backend selction
the number 10 in .count(10) represent the first 10 elements in the array
DistributionTuple.objects.filter(**filter_q1).count(10)

DJANGO API REST FRAMEWORK: schema methods

Django 1.11.3, python 3.6
I have 2 classes in my view.py:
class ProductList(generics.ListAPIView):
class SampleList(generics.ListAPIView):
Please note the same superclass. Might be relevant: Product is an actual model, Sample is not, SampleList is just a method that calls Product.objects.all() (same code as in ProductList)
All the code inside those classes besides class names is IDENTICAL (including serializer) - I just copied the class and renamed the copy).
The client before it hits urls for those two gets the schema
schema = self.client.get(self.myAppApiUrl)
#works, returns the results
result1 = self.client.action(schema, ["products", "list"])
params = {"id" : some_id, }
#fails with this: coreapi.exceptions.LinkLookupError: Index ['samples']['list'] did not reference a link. Key 'list' was not found.
result2 = self.client.action(schema, ["samples", "list"], params)
When I print "schema", I see
products: {
list([page])
}
samples: {
read(id)
}
My questions are: what makes it to add "list" to schema in the first case and "read" in the second case? And how can I add "list" to the second case? Maybe some schema update needs to be done somehow? The API web server was restarted.
What does that message "Key 'list' was not found" mean? Does this failure have something to do with the params passed? Removing params from the client call does not change anything.
I am also somewhat curious about what is that "page" thing in list and what adds that and but that's not important.

Validate custom field with Flask-RESTPlus

I'm trying to create a custom field for validating POSTed JSON in my API using Flask-RESTPlus 0.10.1
Below is the basic setup...
from flask_restplus import fields
import re
EMAIL_REGEX = re.compile(r'\S+#\S+\.\S+')
class Email(fields.String):
__schema_type__ = 'string'
__schema_format__ = 'email'
__schema_example__ = 'email#domain.com'
def validate(self, value):
if not value:
return False if self.required else True
if not EMAIL_REGEX.match(value):
return False
return True
I like the way the above documents in Swagger UI, but I can't seem to figure out how to actually use the validate method on it.
Here's how I'm using the custom field.
Json = api.model('Input JSON', {
'subscribers': fields.List(Email),
[...]
})
#api.expect(Json) // validate is globally set to true
def post(self):
pass
I've had luck using
'subscribers': fields.List(fields.String(pattern='\S+#\S+\.\S+')) instead, but this doesn't give me the control to customize the error message, where'd I'd like it to return that the field is not of the email type.
I've also gone on and added a custom validate_payload function (found within http://aviaryan.in/blog/gsoc/restplus-validation-custom-fields.html) that I call again within my POST method (instead of api.expect). This requires me to duplicate some core functionality and call it every time in addition to api.expect to output the proper Swagger documentation and a little bit of finesse to get it to work within nested fields.
It's my understanding that this should work out of box? Am I wrong? What am I missing here?
I appreciate this is a little old but just had the same issue.
It looks like the "validate" actually sat over a python jsonschema impl, if you're still interested in digging, it's available here
That aside - you can configure restplus API to use a better formatchecker as follows: (I also validate date-time and date)
format_checker = FormatChecker(formats=["date-time", "email", "date"])
api_v1 = Api(
app, version='1.4',
title='[Anon]',
description='[Anon] API for developers',
format_checker=format_checker
)

Create/Update Tag for Intercom.io User in Python

Unfortunately there's no way to create a user in Intercom.io with a tag, so I'm trying to write some code that will look for an existing tag in Intercom, and if it's there, add a user to that tag, and if it's not, create the tag and add the user to it. I've tried several different variations by looking at the docs for the python-intercom library, but there are conflicting methods (Intercom.update_tag vs. Tag.update), and nothing has worked yet.
Here's how users are created in Intercom (this works):
import time
from members.models import Member
from intercom import Intercom, Tag
Intercom.app_id = settings.INTERCOM_TEST_APP_ID
Intercom.api_key = settings.INTERCOM_TEST_API_KEY
member = Member.objects.get(email="exampleemail#example.com")
Intercom.create_user(
email=member.email,
user_id=member.email,
name="%s %s" % (member.first_name, member.last_name),
created_at=int(time.time()),
city_name=member.city,
last_seen_ip=member.last_ip,
)
Here's what I currently have to look for and create or update tags, which triggers no errors, but doesn't successfully tag the user:
tag = Intercom.get_tag(name=member.referral_code)
if tag['id'] != None:
Intercom.update_tag(member.referral_code, "tag", user_ids=[member.pk])
else:
Intercom.create_tag(tag, "tag", user_ids=[member.pk])
I've also tried variations of the following, but it gets the error "descriptor 'update' requires a 'dict' object but received a 'unicode':
if Tag.find_by_name(member.referral_code) != 0:
Tag.update(member.referral_code, "tag", user_ids=[member.pk])
else:
Tag.create(member.referral_code, "tag", user_ids=[member.pk])
What do I need to change to get tagging to work?
My name's Jeff, I'm one of the customer success engineers at Intercom. Unfortunately the intercom-python library is still using our deprecated V1 API which is likely causing some of the confusion here. Until that library updates to use our newer REST API I would suggest that you use the python requests library and call our API directly. I've got minimal python experience but something like this should get you started on the right track.
import requests
from requests.auth import HTTPBasicAuth
import json
tags_url = 'https://api.intercom.io/tags'
app_id = 'YOUR_APP_ID'
api_key = 'YOUR_API_KEY'
headers = {'content-type': 'application/json', 'Accept': 'application/json'}
tag_name = 'My sweet tag'
# Get tags to then loop through
list_tag_response_as_json = requests.get(tags_url, auth=(app_id, api_key), headers=headers).json()
tag_names = [tag['name'] for tag in list_tag_response_as_json['tags']]
if tag_name not in tag_names
# Create a tag
tag_response = requests.post(tags_url, auth=(app_id, api_key), headers=headers, data={'name': tag_name})
# Tag users
tag_and_users = {'name':tag_name, 'users': [{'email': 'abc#example.com'}, {'email': 'def#example.com'}]}
tagged_user_response = requests.post(tags_url, auth=(app_id, api_key), headers=headers, data=tag_and_users)
Also, feel free to give us a shout in Intercom if you're still having trouble and we can help you there.