How to make a field required for a post request in an API? - flask

I'm making an API route that returns a random number in Flask. When sending a post request to the end-point, I want it to return an error(s) if a certain field(s) is not in the post request (for example, if there is no "name" in the request, it should return an error).
I've tried doing this with a dictionary, try, and catch. If a field is missing, I add a key: value to the dictionary and if the dictionary isn't empty, to return that. First problem is if there is more than one field missing, it only adds one of them to the error dictionary. Second problem is, I'm also trying to make sure some fields also have a certain value (for example, color needs to be red or blue). If I check for one thing, it works - if I do
if color != "red" or color != "blue":
it will always show an error. Even if I split it up into multiple if statements, it will still be an error. I've searched Google, rephrasing my question at least 30 different times, and most answers I've gotten are about SalesForce (which I'm assuming is some company/software etc).
So...is there a way to make a certain field(s) required? Or am I on the right track with try and catch? If it is through try and catch, how do I make it show more than one error/have a variable a certain thing?
#app.route('/api/get-num', methods=["POST"])
def num():
errors = {}
try:
name = request.json['name']
except:
errors["errors"] = {"name" : "This field is required."}
try:
color = request.json['color']
if color != "red" or color != "blue":
errors["errors"] = {"color" : "Invalid value, must be red or blue."}
except:
errors["errors"] = {"color" : "Invalid value, must be red or blue."}
if len(errors) != 0:
return errors
create_dict = {
'name' : request.json['name'],
'email ': request.json['email'],
'year': request.json['year'],
'color' : request.json['color']
}
return jsonify(create_dict)
Examples:
If name is missing and color is wrong, it should show:
{
"errors": {
"color": [
"Invalid value, must be red or blue."
],
"name": [
"This field is required."
]
}
}
With name missing and color being "red", it's currently showing:
{
"errors": {
"color": "Invalid value, must be red or blue."
}
}

Create a dict with expected errors, in this case it would be all the required fields
errorsDict = {"errors":{"color":[],"name":[]}}
In your try except block append to the nested as items as necessary, example:
errorsDict = {"errors":{"color":[],"name":[]}}
try:
name = request.json['name']
except:
errorsDict["errors"]["name"].append("This field is required.")
try:
color = request.json['color']
except:
errorsDict["errors"]["color"].append( "COLORS MISSING!")

Related

How to use mod_assign_save_grade?

I'm trying to use mod_assign_save_grade with : https:/[my-root]/webservice/rest/server.php?wstoken=[token]&wsfunction=mod_assign_save_grade&moodlewsrestformat=json&assignmentid=4&userid =45&grade =15&attemptnumber =-1&addattempt =0&workflowstate =graded&applytoall =1
but the output came with
{
"exception": "invalid_parameter_exception",
"errorcode": "invalidparameter",
"message": "Invalid parameter value detected"
}
any ideas to use it correctly
It seems there are blank spaces before = in several places. I copied your request, (of course, with actual server name, token and parameter values), removed blanks and it works correctly. When I insert blank space anywhere, the message that you posted appears.

I want to get data from JavaScript with Django

There is price filtering written in JavaScript in the template. I want to take the price range given in this filter with dajngo and write a filtering function. I couldn't because I don't know JavaScript. How will I do?
So, i want to write a django function that takes the given start and end values and sorts the products accordingly.
main.js
// PRICE SLIDER
var slider = document.getElementById('price-slider');
if (slider) {
noUiSlider.create(slider, {
start: [1, 100],
connect: true,
tooltips: [true, true],
format: {
to: function(value) {
return value.toFixed(2) + '₼';
},
from: function(value) {
return value
}
},
range: {
'min': 1,
'max': 100
}
});
}
I'm not familiar with noUiSlider but you would need to get the from and to values into Django - you can do that either by submitting a form when clicking FILTER or by sending an AJAX request. I presume you would just submit the form in a standard page submission as you aren't familiar with JS (and therefore AJAX).
def your_view(request)
filter_from = request.POST.get('slider_from')
filter_to = request.POST.get('slider_to')
YourModel.objects.filter(value__gte=filter_from, value__lte=filter_to)
...
You will need to replace slider_from and slider_to with the key values that are sent by the slider input in request.POST - this will be the name of the inputs themselves. You can wrap request.POST in a print statement to easily see what these are. It's just a matter of getting the values and passing them into the filter() function of your model.

Cannot define custom metrics in ray

I'm using a framework called FLOW RL. It enables me to use rllib and ray for my RL algorithm. I have been trying to plot non learning data on tensorboard. Following ray documentation ( link ), I have tried to add custom metrics. Therefore, I need to use the info dict, which is accessed by on_episode_step(info). An "episode" element is supposed to be present in this dictionary. That lets me access to my custom scalars.
However, every time I try to access to the episode element, I get an error because it does not exist in the info dict. Is this normal?
File "examples/rllib/newGreenWaveGrid2.py", line 295, in on_episode_start
episode = info["episode"]
KeyError: 'episode'
def on_episode_step(info):
episode = info["episode"]
whatever = abs(episode.last_observation_for()[2])
episode.user_data["whatever"].append(whatever)
if __name__ == '__main__':
alg_run, gym_name, config = setup_exps()
ray.init(num_cpus=N_CPUS + 1, redirect_output=False)
trials = run_experiments({
flow_params['exp_tag']: {
'run': alg_run,
'env': gym_name,
'config': {
**config,
'callbacks': {
"on_episode_start": on_episode_start,
"on_episode_step": on_episode_step,
"on_episode_end": on_episode_end,
}
},
'checkpoint_freq': 20,
'max_failures': 999,
'stop': {
'training_iteration': 200,
},
},
})

How to POST to server with null Related Resource in TastyPie?

I've got the following two models. They are linked by a OneToOneField relation 'mission' going from the TextMission table to the Mission table.
#Models.py
class Mission(models.Model):
name = models.CharField(max_length = 40)
class TextMission(models.Model):
mission = models.OneToOneField(Mission, related_name="text_mission", primary_key = True)
Sometimes missions will have a corresponding TextMission, but not always. I'm able to get everything working when I'm creating/updating objects in the shell, but TastyPie only handles requests correctly when there IS a TextMission (PUTing to /mission/{id}/). When text_mission=null, it craps out.
My tastypie config:
class MissionResource(ModelResource):
text_mission = fields.ToOneField('path.to.TextMissionResource', attribute='text_mission', related_name='mission', full = True, null = True)
class TextMissionResource(ModelResource):
mission = fields.ToOneField(MissionResource, attribute='mission', related_name='text_mission')
When PUTing the following JSON back to the server (the exact same JSON I received), I get a ValueError:
FAILS
{ "name": "TEST", "id": "1", "text_mission": null, "resource_uri":
"/api/web/mission/1/", }
*** ValueError: Cannot assign None: "Mission.text_mission" does not allow null values.
SUCCEEDS
{ "name": "TEST", "id": "1", "text_mission": {"id": "1", "resource_uri": "/api/web/text_mission/1/"}, "resource_uri":
"/api/web/mission/1/", }
Is there something I'm doing wrong in my code or it just not supposed to work this way. I'm at a loss here.
I'm running TastyPie 0.9.11.
I ended up figuring it out and it was a pretty dumb error. I just needed to add blank = True in addition to null = True:
class MissionResource(ModelResource):
text_mission = fields.ToOneField('path.to.TextMissionResource', attribute='text_mission', related_name='mission', full = True, blank = True, null = True)
That got everything working properly.

How to check the type of a field before checking the value in rethinkdb?

I have few tables in rethinkdb with very varied datasets. Mostly because over time, out of simple string properties complex objects were created to be more expressive.
When I run a query, I'm making sure that all fields exist, with the hasFields - function. But what if I want to run a RegExp query on my Message property, which can be of type string or object. Of course if it is an object, I don't care about the row, but instead of ignoring it, rethinkdb throws the error:
Unhandled rejection RqlRuntimeError: Expected type STRING but found OBJECT in...
Can I somehow use typeOf to first determine the type, before running the query?
Or what would be a good way to do this?
Your question is not 100% clear to me so I'm going to restate the problem to make sure my solution gets sense.
Problem
Get all documents where the message property is of type object or the message property is a string and matches a particular regular expression (using the match method).
Solution
You basically need an if statement. For that, you can use the r.branch to 'branch' your conditions depending on these things.
Here's a very long, but clear example on how to do this:
Let's say you have these documents and you want all documents where the message property is an object or a string that has the substring 'string'. The documents look like this:
{
"id": "a1a17705-e7b0-4c84-b9d5-8a51f4599eeb" ,
"message": "invalid"
}, {
"id": "efa3e26f-2083-4066-93ac-227697476f75" ,
"message": "this is a string"
}, {
"id": "80f55c96-1960-4c38-9810-a76aef60d678" ,
"not_messages": "hello"
}, {
"id": "d59d4e9b-f1dd-4d23-a3ef-f984c2361226" ,
"message": {
"exists": true ,
"text": "this is a string"
}
}
For that , you can use the following query:
r.table('messages')
.hasFields('message') // only get document with the `message` property
.filter(function (row) {
return r.branch( // Check if it's an object
row('message').typeOf().eq('OBJECT'), // return true if it's an object
true,
r.branch( // Check if it's a string
row('message').typeOf().eq('STRING'),
r.branch( // Only return true if the `message` property ...
row('message').match('string'), // has the substring `string`
true,
false // return `false` if it's a string but doesn't match our regex
),
false // return `false` if it's neither a string or an object
)
)
})
Again this query is long and could be written a lot more elegantly, but it explains the use of branch very clearly.
A shorter way of writing this query is this:
r.table('messages')
.hasFields('message')
.filter(function (row) {
return
row('message').typeOf().eq('OBJECT')
.or(
row('message').typeOf().eq('STRING').and(row('message').match('string'))
)
})
This basically uses the and and or methods instead of branch.
This query will return you all registers on table message that have the field message and the field is String.
Cheers.
r.db('test').table('message').hasFields('message')
.filter(function (row) {
return row('message').typeOf().eq('STRING')
})