I want an EmbeddedListField of comments to show up only when I 'GET' a single post and not when I 'GET' a list of posts - tastypie

I have a mongodb document 'Post' which has EmbeddedListField of 'comments'. I'm using tastypie to build the API layer and I want the comments to be listed with their body fields only when a single post is requested. When a list of posts is requested I do not want to show the full comment body as this would kill my app's performance. This is what I have in my resource file:
comments = tastypie_mongoengine_fields.EmbeddedListField(of='api_core.resources.EmbeddedCommentResource', attribute='comments', full=True, null=True)
What can I do about this? I do not want to create two entry points for 'post_entry' and 'post_list' as this would be bad design for the consumer of the APIs.

I did a simple check in the dehydrate method:
def dehydrate(self, bundle):
if self.get_resource_uri(bundle) != bundle.request.path:
bundle.data['comments_count'] = len(bundle.data['comments'])
del bundle.data['comments']
bundle.data['user_id'] = bundle.data['user'].data['id']
bundle.data['user_name'] = bundle.data['user'].data['first_name']
bundle.data['user_uri'] = bundle.data['user'].data['resource_uri']
del bundle.data['user']
return bundle

Related

Add a subpanel record to a SugarCRM account through REST API

Question: How do I create a subpanel record through the SugarCRM rest api endpoint for accounts?
Steps taken so far:
I've added a new package called, "transactionHistory" with a module named, "InvoiceHistory" using the SugarCRM studio.
I added a One to Many relationship to the Accounts module using studio.
I'm using NetSuite to push new invoices to the new module's record via the subpanel "create" option. Here's the code I'm using:
function createSugarTransaction(transaction, token) {
var url = 'https://crm.techsoft3d.com/rest/v10/Accounts/' + transaction.customer;
var headers = {
"Content-Type": "application/json",
"OAuth-Token": token
};
var now = (new Date()).toISOString();
var body = {transactionHistory_InvoiceHistory:
{
create: [{
name: transaction.docId,
transaction_date_c: transaction.date,
invoice_status_c: transaction.status,
due_date_c: transaction.duedate,
total_amount_c: transaction.total,
amount_due_c: transaction.remaining,
start_date_c: transaction.startdate,
end_date_c: transaction.enddate
}]
}
};
var response = nlapiRequestURL(url, JSON.stringify(body), headers, 'PUT');
return response;
}
The transaction object has been validated and the json object within the create: [] array has matching sugar fields (key) with the corresponding transaction object values.
When making the API call to sugar I'm successfully authenticated and have access to the custom module and accounts - so no problem there. However, when the call is returned to response it's showing the following error:
{"error":"no_method","error_message":"Could not find a route with 1 elements"}
I'm unsure of what else is needed in order for the record to be created. According to sugar's help documentation and developer community this should work. I'm using the basic information provided by sugarcrm support portal:
http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.6/API/Web_Services/Examples/v10/module_POST/
According to other blog posts within the developer community, it should be as simple as adding the subpanel name, followed by an array of fields under the "create" object... similar to this:
var requestBody = { package_module:create[{name:value}]};
My initial thinking of what's wrong is:
1. my package_module name isn't correct, but I'm unable to find it anywhere within the applicaiton or help documentation.
2. the request body isn't formatted properly, even though it's structure was copied from this article https://developer.sugarcrm.com/2014/02/28/sugarcrm-cookbook2/
Any help would be appreciated.
try the createRelatedRecord api endpoint
type {sugarurl}/rest/v10/help to see a list of endpoints to look through, most of which have documentation and examples
https://crm.techsoft3d.com/rest/v10/help
your API url should have the name of the link (relationship) you want, in addition to the values in the POST payload
https://crm.techsoft3d.com/rest/v10/Accounts/{transaction.customer}/link/accounts_transactionhistory (or whatever your link's name is)
per the documentation for this endpoint, you just specify the field values in the payload
{
"first_name":"Bill",
"last_name":"Edwards"
}

RESTful URLs for collection of objects

I have an entity Temperature.
My URLs are designed as follows:
GET /api/temperatures/new
GET /api/temperatures/{id}/edit
GET /api/temperatures
POST /api/temperatures
PUT /api/temperatures/{id}
DELETE /api/monitoring/temperatures/{id}
I would like to create multiple temperatures (a collection of temperatures) at once - are there any conventions in terms of the urls to use?
So far, I came up with the following:
POST /api/monitoring/temperatures/collection
GET /api/monitoring/temperatures/cnew
I thought there must be a convention for this already so would like to check with you.
GET /api/temperatures # Getting all resources
POST /api/temperatures # Create new resource
GET /api/temperatures/<id> # Get a single resource
PUT /api/temperatures/<id> # Edit all fields
PATCH /api/temperatures/<id> # Edit some fields
DELETE /api/temperatures/<id> # Delete a resource
These are the kinds of URL's Fielding describes in his thesis on REST. You shouldn't be describing what an end point does in the URL especially when used properly the HTTP verbs provide plenty of information. Be aware the REST architectural style has more to it than JSON over HTTP. Generic connectors, decoupling of components and a stateless server are key components of a RESTful application.
Note: Most people probably wouldn't implement both PUT and PATCH. PUT will be fine but I included it for completeness.
In response to your comment, if you are referring to creating multiple resources with one POST request you don't need a new URL. Your application should be able to handle {temp: 45, date: ...} and [{temp: 45, date: ...}, {temp: 50, date: ...}] at the same endpoint.
The HTTP method GET is not suitable for creating or editing resources - /api/temperatures/new and /api/temperatures/{id}/edit. HTTP GET is used for getting information without changing state in a server. You should use POST or PUT.
If you want to create multiple temperatures, you should use
POST /api/monitoring/temperatures
and consume JSON or XML list of objects.
Java example:
#POST
#Path("/temperatures")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response postTemperatures(Temperatures temperatures){
// process and save
}
#XmlRootElement
public class Temperatures {
public List<Temperature> temperatures;
Temperatures(){}
}
You can update multiple entries with a single post by sending in an array of temperatures instead of a single entry,
POST /api/temperatures { [{...},{...}] }
but your api endpoint structure could be streamlined a little.
Ideally you want a simple consistent interface for all API resources.
I would personally simplify:
GET /api/temperatures/new
GET /api/temperatures/{id}/edit
GET /api/temperatures
POST /api/temperatures
PUT /api/temperatures/{id}
DELETE /api/monitoring/temperatures/{id}
to
GET /api/temperatures // Get all temperatures
POST /api/temperatures // Send in array of new entries to update
GET /api/temperatures/{id} // Read a specific temperature
PUT /api/temperatures/{id} // Update a specific temperature
DELETE /api/temperatures/{id} // Delete a specific temperature
This gives a consistent interface to the api for all temperature related calls that maps onto a CRUD interface.
Without context its hard to work out exactly what /api/temperatures/new is used for, but I would consider using a parameter on the call for finegraining the response.
e.g.
/api/temperatures?age=new // Get new temps
Which will allow you to use the common structure to add different types of criteria later on.

PUT request in Tasty PIE to update using non PK value

I am using Tasty Pie to create Services. I have applied filtering so that it searches based on non PK value:
My api.py file :
class TestResource(ModelResource):
class Meta:
queryset = ack_dadc.objects.all()
authorization = Authorization()
filtering = {
'DistributorUID': ['exact'],
}
detail_allowed_methods = ['get', 'post', 'put', 'delete']
My question is:
Can I do a PUT request based on http:localhost/api/v1/test/?DistributorUID=steve
I have googled a lot but no luck I just want to update the database based on non PK value.
You'll find an example of how to achieve this using normal URL arguments in the Tastypie Cookbook: http://django-tastypie.readthedocs.org/en/latest/cookbook.html#using-non-pk-data-for-your-urls
I don't think you can do this : filters are only applied on GET requests.
So if you want to achieve this you have to do it with 2 requests :
GET http:localhost/api/v1/test/?DistributorUID=steve
to get the ID of the resource and then
PUT http:localhost/api/v1/test/ID
to update it based on its ID.

Facebook Request Dialog with data

I read this article.
So, I tried it and I put a number in the data property.
FB.ui({
method: 'apprequests',
message: 'Come join me and play at MyWebSite!',
data: '12345',
redirect_uri: 'myWebSite'
});
I get the request_ids, but how do I get the data part (the 12345 number)?.
on server side, you can do something like:(using php here)
$request_ids = $_GET['request_ids'];
$request_ids = explode(",", $request_ids);
foreach($request_ids as $request_id)
{
$request_object = $facebook->api($request_id);
if(isset($request_object['data'])) $req_data = $request_object['data']; //$req_data will be '12345' as per your request data set.
// after getting the data, you may like to delete the request.
$full_request_id = $request_id."_".$fbid; //$fbid is current user facebook id
$facebook->api("$full_request_id","DELETE");
}
Did you try Facebook's documentation too?
https://developers.facebook.com/docs/requests/ has more documentation; if a data parameter was added in the call to the requests dialog, the same value should also be there when requesting the Request details via the API (i.e. a call to /REQUEST_ID)
See the facebook developer site documentation for more details
http://developers.facebook.com/docs/reference/dialogs/requests/
Note:
data:Optional, additional data you may pass for tracking. This will be stored as part of the request objects created. The maximum length is 255 characters.

Retrieve User ID of Facebook App Invitor

In the context of a given Facebook app, suppose User A invited user B to start using it. Once User B accepts to use the app, is there any way to retrieve the ID of User A programmatically (via either PHP/JS SDK) ? This doesn't seem quite documented.
For what it's worth, A/B users are friends, if it's any use.
when user comes following the app request, you can get request id's using
$_GET['request_ids']
then retrieve all the request ids with which you can call graph api to get the corresponding request details like below:
if(isset($_GET['request_ids']))
{
$request_ids = $_GET['request_ids'];
}
$request_ids = explode(",", $request_ids);
foreach($request_ids as $request_id)
{
$request_object = $facebook->api($request_id);
//this $request_object have sender facebook id in the field uid_from
}
If you look here:
http://developers.facebook.com/docs/reference/dialogs/requests/
You can see the object layout. Of note is the data property:
Optional, additional data you may pass for tracking. This will be
stored as part of the request objects created. The maximum length is
255 characters.
In this object you can add your referring UserId and then when the request is claimed, you can then process it on your end.
Hope this helps.