A beginner django question...
Here's a JSON response...
"data": [
{
"type": "Subject",
"id": "0",
"attributes": {
"created": "2019-01-01T00:00:00Z",
"modified": "2019-01-01T00:00:00Z",
"subject_code": "A&H",
"subject_name": "AH",
"subject_short_name": "A & HUM"
},
"relationships": {
"organization": {
"data": {
"type": "Organization",
"id": "61"
}
},
"created_user": {
"data": null
},
"last_updated_user": {
"data": null
}
},
"links": {
"self": "http://localhost:8001/v1/subject_owner/0"
}
},
The above response is coming from a serializer
queryset = Subject.objects.all()
I have a query which is
http://localhost:8001/v1/subject_owner?owner_ids=62,63
So, how do we write a filtering condition for the owner_ids as a list? The response should have only the results where the owner_ids match organization_id. I have tried few:
queryset.filter(organization__in=[owner_id_list])
and
queryset.filter(organization=owner_id_list)
and obviously they don't work. Any help will be appreciated.
FYI, here's the model class...
class SubjectManager(models.Manager):
def get_by_natural_key(self, subject_code):
return self.get(subject_code=subject_code)
class Subject(get_subject_base_class(Organization)):
objects = SubjectManager()
def __str__(self):
return self.subject_code
def natural_key(self):
return (self.subject_code,)
You have to make something like that:
owner_id_list = [62, 63]
Subject.objects.filter(organization_id__in=owner_id_list)
Related
Currently using Swagger/Flasgger/Flask to document APIs/routes in an app.
# app.py
from flask import Flask
from flasgger import Swagger
from myapp.blueprints.main import main
app = Flask(__name__)
app.register_blueprint(main)
swag = Swagger(app)
# myapp.blueprints.main.views.py
main = Blueprint('main', __name__)
#main.route('/user/<path:user_id>', methods=['GET', 'PUT', 'DELETE'])
#main.route('/user', methods=['GET', 'POST'])
def user(user_id=None):
pass
To get documentation on two routes used for the same function, I need to do two things per the Flasgger documentation:
Add a #swag_from declaration pointing to the file that contains the spec.
Give the #main.route and #swag_from the same endpoint kwarg.
When I do step 1, I start seeing the spec information in the Swagger output:
# myapp.blueprints.main.views.py
#main.route('/user/<path:user_id>', methods=['GET', 'PUT', 'DELETE'])
#main.route('/user', methods=['GET', 'POST'])
#swag_from('user_without_id.yml')
def user(user_id=None):
pass
// > curl localhost:8000/apispec_1.json
{
"definitions": {
"User": {
"properties": {
"age": {
"default": "180",
"description": "The user age (should be integer)",
"type": "integer"
},
"tags": {
"default": [
"wizard",
"hogwarts",
"dead"
],
"description": "optional list of tags",
"items": {
"type": "string"
},
"type": "array"
},
"username": {
"default": "Sirius Black",
"description": "The user name.",
"type": "string"
}
},
"required": [
"username",
"age"
]
}
},
"info": {
"description": "The test-swagger-api spec",
"termsOfService": "/tos",
"title": "test-swagger-api",
"version": "1.0"
},
"paths": {
"/user": {
"get": {
"description": "The default payload is invalid, try it, then change the age to a valid integer and try again<br/>",
"parameters": [
{
"in": "body",
"name": "body",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"200": {
"description": "A single user item",
"schema": {
"$ref": "#/definitions/User"
}
}
},
"summary": "Test validation using JsonSchema"
},
"post": {
"description": "The default payload is invalid, try it, then change the age to a valid integer and try again<br/>",
"parameters": [
{
"in": "body",
"name": "body",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"200": {
"description": "A single user item",
"schema": {
"$ref": "#/definitions/User"
}
}
},
"summary": "Test validation using JsonSchema"
}
},
"/user/{user_id}": {
"get": {
"description": "The default payload is invalid, try it, then change the age to a valid integer and try again<br/>",
"parameters": [
{
"in": "body",
"name": "body",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"200": {
"description": "A single user item",
"schema": {
"$ref": "#/definitions/User"
}
}
},
"summary": "Test validation using JsonSchema"
}
}
},
"swagger": "2.0"
}
However, as soon as I add the endpoint and methods kwargs, my output loses the spec:
# myapp.blueprints.main.views.py
#main.route('/user/<path:user_id>', methods=['GET', 'PUT', 'DELETE'])
#main.route('/user', endpoint='my-new-endpoint', methods=['GET', 'POST'])
#swag_from('user_without_id.yml', endpoint='my-new-endpoint', methods=['GET', 'POST'])
def user(user_id=None):
pass
// > curl localhost:8000/apispec_1.json
{
"definitions": {},
"info": {
"description": "The test-swagger-api spec",
"termsOfService": "/tos",
"title": "test-swagger-api",
"version": "1.0"
},
"paths": {},
"swagger": "2.0"
}
Not sure where the documentation is going. Flasgger's blueprint example doesn't show how to make this work with multiple routes on a single function.
https://stackoverflow.com/a/55109061/3316036
#swag_from needs to contain the blueprint name in its endpoint field which is unfortunately not clear from the flasgger docs.
# myapp.blueprints.main.views.py
#main.route('/user/<path:user_id>', methods=['GET', 'PUT', 'DELETE'])
#main.route('/user', endpoint='my-new-endpoint', methods=['GET', 'POST'])
#swag_from('user_without_id.yml', endpoint='main.my-new-endpoint', methods=['GET', 'POST'])
def user(user_id=None):
pass
So I'm trying to create an /api/info url that return various data on my application. It pulls data from various models and puts it together in one response. I got the following:
class SessionInfo(generics.GenericAPIView):
def get(self, request, format=None):
token = Token.objects.get(user=self.request.user)
userprofile = UserProfile.objects.get(user=self.request.user)
is_admin = self.request.user.is_staff
is_primary_owner = userprofile.primary_owner
managers = userprofile.reports_to.all()
man = ["test manager 1", "test manager 2"]
pages = Page.objects.filter(published=True, show_in_menu=True)
pages_output = JSONRenderer().render(PageSerializer(pages).data)
content = {
'user': {
"username": str(self.request.user.username),
"first_name": str(self.request.user.first_name),
"last_name": str(self.request.user.last_name),
"is_admin": is_admin,
"is_primary_owner": is_primary_owner,
"api_token": token.key,
"timezone": 'blalala',
"managers": man,
},
'license': {
"plan" : "gold",
"expiry_date" : "lol",
},
'feature_flags': {
'billing_test': False,
},
'pages': { pages_output },
}
return Response(content)
However it doesn't properly serialize and render pages, making it an escaped string instead:
{
"feature_flags": {
"billing_test": false
},
"user": {
"username": "test#user.com",
"first_name": "Test",
"last_name": "User",
"is_admin": true,
"managers": [
"test manager 1",
"test manager 2"
],
"api_token": "08d1a5827da9a90e7746949ffd2e69e87c51b272",
"timezone": "blalala",
"is_primary_owner": false
},
"license": {
"expiry_date": "lol",
"plan": "gold"
},
"pages": [
"[{\"id\": 1, \"title\": \"Trololol\"}, {\"id\": 2, \"title\": \"NEW pages\"}]"
]
}
if I use directuly use pages_output = PageSerializer(pages) I get:
<webapp_api_v1.serializers.PageSerializer object at 0x10a0d8f90> is not JSON serializable
How can I make a serializer properly nest within my constructed response? Thanks!
Solved it with pages_output = PageSerializer(pages).data and changing 'pages': pages_output,
I've implemented functionality to Like a non-FB URL in a cross-platform mobile app (Phonegap) I'm developing, and part of functionality is that I need to find out if a user has liked a URL before, hence a GET on the og.likes object. In the result of this request there's a field in the og.likes data that I'm unsure about.
My request:
GET me/og.likes?access_token={AccessToken}&object={EncodedExternalURL}
The response:
{
"data": [
{
"id": "_____",
"from": {
"id": "______",
"name": "______"
},
"start_time": "2015-01-12T06:17:24+0000",
"end_time": "2015-01-12T06:17:24+0000",
"publish_time": "2015-01-12T06:17:24+0000",
"application": {
"name": "______",
"namespace": "______",
"id": "______"
},
"data": {
"object": {
"id": "____",
"url": "____",
"type": "website",
"title": "____"
}
},
"type": "og.likes",
"no_feed_story": false,
"likes": { // <-- this guy here and its properties
"count": 0,
"can_like": true,
"user_likes": false
},
"comments": {
"count": 0,
"can_comment": true,
"comment_order": "chronological"
}
}
],
"paging": {
"next": "____"
}
}
What is the likes field? And the sub properties of count, can_like, user_likes? Is it that other users can like this Like?
likes field is for manage the likes that this like has. Users can like or comment a like.
In my view I'm trying to loop all pages and extract the name for each using the code below. But it does not appear to work.
How can I achieve this?
view.py
json_dict = json.loads(request.POST['site'])
for item in json_dict['pages']:
item.json_dict['name']
the JSON data
{
"someitem": "xaAX",
"pages": [
{
"id": "1364484811734",
"name": "Page Name",
"type": "basic",
"components": {
"img": "",
"text": ""
}
},
{
"id": "1364484812918",
"name": "Contact",
"type": "contact",
"components": {
"text": "Send us an email using the form below.",
"contact-form": {
"contact-name": "zzz",
"contact-email": "zz"
}
}
},
]
}
This should work:
json_dict = json.loads(request.POST['site'])
for item in json_dict['pages']:
print item['name']
Suppose following Resources are given:
class RecipeResource(ModelResource):
ingredients = fields.ToManyField(IngredientResource, 'ingredients')
class Meta:
queryset = Recipe.objects.all()
resource_name = "recipe"
fields = ['id', 'title', 'description',]
class IngredientResource(ModelResource):
recipe = fields.ToOneField(RecipeResource, 'recipe')
class Meta:
queryset = Ingredient.objects.all()
resource_name = "ingredient"
fields = ['id', 'ingredient',]
A HTTP Request to myhost.com/api/v1/recipe/?format=json gives following response:
{
"meta":
{
...
},
"objects":
[
{
"description": "Some Description",
"id": "1",
"ingredients":
[
"/api/v1/ingredient/1/"
],
"resource_uri": "/api/v1/recipe/11/",
"title": "MyRecipe",
}
]
}
So far so good.
But now, I would like to exchange the ingredients resource_uri ("/api/v1/ingredient/1/") with something like that:
{
"id": "1",
"ingredient": "Garlic",
"recipe": "/api/v1/recipe/1/",
"resource_uri": "/api/v1/ingredient/1/",
}
To get following response:
{
"meta":
{
...
},
"objects":
[
{
"description": "Some Description",
"id": "1",
"ingredients":
[
{
"id": "1",
"ingredient": "Garlic",
"recipe": "/api/v1/recipe/1/",
"resource_uri": "/api/v1/ingredient/1/",
}
],
"resource_uri": "/api/v1/recipe/11/",
"title": "MyRecipe",
}
]
}
The answer is the attribute full=True:
ingredients = fields.ToManyField('mezzanine_recipes.api.IngredientResource', 'ingredients', full=True)