I've been working on Django-rest-framework for past few months. I did not quite understood how the json request can be used.Can you please help me, I got stuck here for months.
I have a third-party html snippet on another website and lets assume it sends this json data
[{"idcomment":1,"isFlagged":false,"isDeleted":false,"isApproved":true,"createdAt":"2015-11-22T12:39:33Z","numReports":0,"isEdited":false,"message":"xcvvzvc","isSpam":false,"isHighlighted":false,"ip_address":"","is_public":true,"tree_path":"0000000001","tone":"Neutral","forum":1,"parent":null,"topic":1,"last_child":null,"user":1}][{"idcomment":1,"isFlagged":false,"isDeleted":false,"isApproved":true,"createdAt":"2015-11-22T12:39:33Z","numReports":0,"isEdited":false,"message":"xcvvzvc","isSpam":false,"isHighlighted":false,"ip_address":"","is_public":true,"tree_path":"0000000001","tone":"Neutral","forum":1,"parent":null,"topic":1,"last_child":null,"user":1}]
My question: How can I use this json request data and do some verification like if the comment belongs to the correct topic.
I couldn't find any examples where its done. So I figured its possible in Flask by using something like this.
mod.route("/create/", methods=["POST"])
def create():
json = getJson(request)
check_required(json, ['date', 'thread', 'message', 'user', 'forum'])
uid = id_by_email(json['user'])
fid = id_by_sname(json['forum'])
if uid < 0 or fid < 0:
return send_resp(json)
if 'parent' in json:
parent = json['parent']
else:
parent = None
json['parent'] = None
if 'isApproved' in json:
approved = json['isApproved']
else:
approved = 0
json['isApproved'] = 0
if 'isHighlighted' in json:
highlighted = json['isHighlighted']
else:
highlighted = 0
json['isHighlighted'] = 0
if 'isEdited' in json:
edited = json['isEdited']
else:
edited = 0
json['isEdited'] = 0
if 'isSpam' in json:
spam = json['isSpam']
else:
spam = 0
json['isSpam'] = 0
if 'isDeleted' in json:
deleted = json['isDeleted']
else:
deleted = 0
json['isDeleted'] = 0
db.insert("""INSERT INTO posts (date,thread_id,message,user_id,forum_id,parent,approved,highlighted,edited,spam,deleted)
values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""", (
json['date'], json['thread'], json['message'], uid, fid, parent, approved, highlighted, edited, spam, deleted))
pid = db.query("SELECT LAST_INSERT_ID() as id")[0]['id']
json['id'] = pid
return send_resp(json)
What is the alternative for something like this in django-rest-framework.
I am quite new, so please explain in simple language. I don't need any code, just searching how can I use json requests I get to the server.
It's a no-brainer I read the documentation several times
Disclaimer: I have also gonna all over through the django-rest-framework code
This job is handled by your Serializer Class :
The first thing we need to get started on our Web API is to provide a
way of serializing and deserializing the snippet instances into
representations such as json. We can do this by declaring serializers
that work very similar to Django's forms.
A serializer class is very similar to a Django Form class, and
includes similar validation flags on the various fields, such as
required, max_length and default.
If your serializer inherit of serializer.ModelSerializer then it use your model do validate your data like form class that inherit from form.ModelForm. And yes, you don't re-write any code to validate your data, and it seems to be magical. (DRY concept) But, of-course, you can define and override models validators in your serializer class.
I recommend you to re-read Django-Rest-Framework and specially Serializer part. It explain all serializers class that DRF provides with use cases.
Related
I am using python rebar for validating request_body_schema, it works well. we can validate input body arguments. Its cool, we do not want to implement any manual input validations like adding if statements.
Same way I could not able to validate response arguments.
But flask_rebar mentioned we can implement Link
Opting In to Response Validation
There are two ways to opt-in to response validation:
Globally, via validate_on_dump attribute of your Rebar instance. Using this method, it is easy to turn on validation for things like test cases, while reaping performance gains by leaving it off in your production endpoints (assuming your API contract testing is sufficient to guarantee that your API can’t return invalid data).
At schema level, via flask_rebar.validation.RequireOnDumpMixin (including if you use our legacy pre-canned ResponseSchema as the base class for your schemas). Any schema that includes that mixin is automatically opted in to response validation, regardless of global setting. Note that in Flask-Rebar 2, that mixin serves only as a “marker” to trigger validation; we plan to augment/replace this with ability to use SchemaOpts as a more logical way of accomplishing the same thing in the near future (https://github.com/plangrid/flask-rebar/issues/252).
But I am not getting any example, Can any body help me with example
my code:
from marshmallow import fields, Schema
from flask import Flask
from flask_rebar import Rebar, RequestSchema, get_validated_body
class CreateAccountSchema(RequestSchema):
email = fields.String(required=True)
country = fields.String(required=True)
default_currency = fields.String(required=True)
class AccountSchema(Schema):
id = fields.String()
email = fields.String()
country = fields.String()
default_currency = fields.String(required=True) # if this is not passed raise error
rebar = Rebar()
registry = rebar.create_handler_registry(prefix="/v1")
#registry.handles(
rule='/accounts',
method='POST',
marshal_schema={201: AccountSchema()},
request_body_schema=CreateAccountSchema(),)
def get_todos():
"""
This docstring will be rendered as the operation's description in
the auto-generated OpenAPI specification.
"""
body = get_validated_body()
body = rebar.validated_body
data = {"id": "myname", "email": "myemail", "country": "any"}
return data, 201
#registry.handles(
rule='/values',
method='GET',
marshal_schema=None,)
def get_values():
"""
This docstring will be rendered as the operation's description in
the auto-generated OpenAPI specification.
"""
data = {"id": "myname", "email": "myemail", "country": "any"}
return 'Hello, Poorvika'
def create_app(name) -> Flask:
app = Flask(name)
rebar.init_app(app)
return app
if __name__ == '__main__':
create_app(__name__).run()
To get the example to work in Flask-Rebar 2.0, you have to replace marshal_schema argument in the #registry.handle decorator with response_body_schema. marshal_schema is the old deprecated name which was removed in Rebar 2.0. The new name response_body_schema was introduced in Rebar 1.7.
response_body_schema is a Marshmallow schema that will be used marshal the return value of the function. marshmallow.Schema.dump will be called on the return value. response_body_schema can also be a dictionary mapping status codes to Marshmallow schemas - see Marshaling. NOTE: In Flask-Rebar 1.0-1.7.0, this was referred to as marshal_schema. It is being renamed and both names will function until version 2.0.
– Basics - Flask-Rebar documentation
https://flask-restplus.readthedocs.io/en/stable/marshalling.html
`#api.marshal_with`
user reponse marshaling
In django rest framework, it's possible to make a function to customize the process of creating an object inside the serializer of that respective model, but I can't figure out how to do that in "vanilla" django, so to speak. What I need to do is take one field and do a bunch of stuff with it. encode it into a 256 character hash is all I have to worry about now. How can I go about doing what I need? I've been basing myself off of an online course and Django's documentation, but I either couldn't interpret it well enough or I just straight up haven't found it there. Here is the code I have so far, at least what I judge is relevant to the question. It's all in models.py:
class SpedFile(models.Model):
json_file = models.FileField(max_length=100)
sped_file = models.FileField(max_length=100)
integrity_hash = models.CharField(max_length=256)
line_counter = models.CharField(max_length=150000)
created_at = models.DateField(auto_now_add=True)
#classmethod
def create(cls, json_file):
file_bearer = json_file
m = hashlib.sha256()
m.update(file_bearer.encode('utf-8'))
integrity_hash = m.hexdigest()
new_object = cls(json_file=file_bearer, integrity_hash=integrity_hash)
return new_object
Working with Google App Engine for Python, I am trying to create and then update an ndb entity. To update a single property, you can just access the property using a dot, e.g.
post.body = body
But I would like to know if there is a simple way to update multiple fields within an ndb entity. The following code:
class Create(Handler):
def post(self):
## code to get params
post = Post(author = author,
title = title,
body = body)
post.put()
class Update(Handler):
def post(self, post_id):
post = post.get_by_id(int(post_id))
fields = ['author', 'title', 'body']
data = get_params(self.request, fields)
for field in fields:
post[field] = data[field]
post.put()
The "Create" handler works fine, but the "Update" handler results in:
TypeError: 'Post' object does not support item assignment
So it seems I would need to access the properties using a dot, but that is not going to work when I have a list of properties I want to access.
Can someone provide an alternative way to update multiple properties of an NDB entity after it has been created?
You should use setattr.
for field in fields:
setattr(post, field, data[field])
(Note that GAE objects do actually provide a hidden way of updating them via a dict, but you should use the public interface.)
You can use the populate method:
post.populate(**data)
tl;dr: is it possible, with endpoints-proto-datastore, to receive a list with objects from a POST and insert it in the db?
Following the samples, when building my API i didn't got how could i let the users POST a list of objects so that i could be more efficient about putting a bunch of data in the db using ndb.put_multi, for example.
From this comment here at endpoints_proto_datastore.ndb.model i imagine that it is not possible with how it is designed. Am i right or i am missing something?
Extending the sample provided by endpoints achieved the desired with:
class Greeting(messages.Message):
message = messages.StringField(1)
class GreetingCollection(messages.Message):
items = messages.MessageField(Greeting, 1, repeated=True)
# then inside the endpoints.api class
#endpoints.method(GreetingCollection, GreetingCollection,
path='hellogretting', http_method='POST',
name='greetings.postGreeting')
def greetings_post(self, request):
result = [item for item in request.items]
return GreetingCollection(items=result)
-- edit --
See the docs about POSTing into the datastore, your only issue is that your models aren't EndpointsModels. Instead define a datastore model for both your Greeting and GreetingCollection:
from endpoints_proto_datastore.ndb import EndpointsModel
class Greeting(EndpointsModel):
message = ndb.StringProperty()
class GreetingCollection(EndpointsModel):
items = ndb.StructuredProperty(Greeting, repeated=True)
Once you've done this, you can use
class MyApi(remote.Service):
# ...
#GreetingCollection.method(path='hellogretting', http_method='POST',
name='greetings.postGreeting')
def greetings_post(self, my_collection):
ndb.put_multi(my_collection.items)
return my_collection
I am using Tastypie for non-ORM data source (Amazon Dynamodb). I have gone through the official documentation for non-ORM source and found the following code:
class MessageResource(Resource):
# Just like a Django ``Form`` or ``Model``, we're defining all the
# fields we're going to handle with the API here.
uuid = fields.CharField(attribute='uuid')
user_uuid = fields.CharField(attribute='user_uuid')
message = fields.CharField(attribute='message')
created = fields.IntegerField(attribute='created')
I am new to Tastypie and what I understand is that fields uuid, message, created.. which are returned by API are defined over here. Is there any way that I return those fields that are not defined here i.e. all those fields returned by the dictionary in obj_get_list or obj_get.
You can use the dehydrade method. Simply add a new key to bundle.data.
def dehydrate(self, bundle):
for item in bundle.obj.iteritems():
bundle.data["new_key"] = "new_value"
return bundle