I have Flask back-end and Angular front-end. My backend working well when I test it via Postman. I send the this kind of data
{
"date": "2018-01-27"
}
#app.route("/schedule", methods=['GET', 'POST'])
def schedule():
cursor = mysql.connection.cursor()
get_date = request.get_json(force = True)
day_name = datetime.datetime.strptime(get_date['date'], '%Y-%m-%d').strftime('%A')
week_number = datetime.datetime.strptime(get_date['date'], '%Y-%m-%d').strftime('%V')
...
But I have problems when I'm trying to send it from Angular.
My service :
#Injectable()
export class RequestService {
constructor(private http:Http) { }
getData(model): Observable<any>{
return this.http.post("http://127.0.0.1:5000/schedule",model)
.map((response:Response)=>{return response.json() });
}
}
My component:
export class CalendarComponent implements OnInit {
public myDatePickerOptions: IMyDpOptions = {
dateFormat: 'yyyy-mm-dd',
openSelectorOnInputClick: true,
satHighlight: true
};
data:any;
public model:any = { jsdate: new Date()};
constructor(private http:RequestService) { }
ngOnInit() {
}
getData(){
this.http.getData(this.model.formatted).subscribe(result => {
this.data = result;
});
console.log(this.model.formatted)
}
the error:
zone.js:2933 POST http://127.0.0.1:5000/schedule 400 (BAD REQUEST)
ERROR Response {_body: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final/…object: Extra data: line 1 column 5 (char 4)</p>↵", status: 400, ok: false, statusText: "BAD REQUEST", headers: Headers, …}
And this is structure of this.model:
{date: {…}, jsdate: Sat Jan 27 2018 00:00:00 GMT+0300 (RTZ 2 (зима)), formatted: "2018-01-27", epoc: 1517000400}
What should I send to get a normal reponse?
Use this
this.http.getData({date: this.model.formatted})
And modify your post methot like that
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post("http://127.0.0.1:5000/schedule", JSON.stringify(model), {headers: headers})
Related
I keep getting the below error when I complete payment via Paypal in development:
JSONDecodeError at /checkout/thankyou
Expecting value: line 1 column 1 (char 0)
I have looked around and I can see that there is some issue with the format of the JSON, and my view can't process it. I can't figure out what the issue with my data is exactly, however. I want to use my Json data to create an order on my Django model once it has pulled through, however I can't get to that stage yet.
checkout.html script:
let bagContents = '{{ bag_products|safe }}';
const csrftoken = getCookie('csrftoken');
const paymentAmount = '{{ total | safe }}';
// Parse bagContents, then for each create a variable for name, id and quantity
let bag = JSON.parse(bagContents);
for (let i = 0; i < bag.length; i++) {
let itemName = bag[i].name;
let itemId = bag[i].id;
let itemQuantity = bag[i].quantity;
console.log(itemName);
console.log(itemId);
console.log(itemQuantity);
}
function completeOrder(){
let url = '{{ success_url }}'
fetch(url, {
method: 'POST',
headers:{
'Content-type':'application/json',
'X-CSRFToken': csrftoken,
},
body:JSON.stringify({'bagContents': 'bagContents'})
})
}
paypal.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [{
amount: {
value: paymentAmount
}
}]
});
},
// Finalize the transaction after payer approval
onApprove: (data, actions) => {
return actions.order.capture().then(function (orderData) {
// Successful capture! For dev/demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
const transaction = orderData.purchase_units[0].payments.captures[0];
completeOrder()
actions.redirect("{{ success_url }}");
// When ready to go live, remove the alert and show a success message within this page. For example:
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
</script>
{% endblock %}
Views.py:
def order_success(request):
"""
View that displays the successful order page after an order has been
processed.
"""
print(request.body)
body = json.loads(request.body)
print('BODY:', body)
return JsonResponse('Success!', safe=False)
Print Statements:
b'{"bagContents":"[{\\"name\\": \\"Teddy Bear\\", \\"id\\": 2, \\"quantity\\": 3}, {\\"name\\": \\"Bath Toys\\", \\"id\\": 1, \\"quantity\\": 1}, {\\"name\\": \\"Chew Toy\\", \\"id\\": 4, \\"quantity\\": 2}]"}'
b''
BODY: {'bagContents': '[{"name": "Teddy Bear", "id": 2, "quantity": 3}, {"name": "Bath Toys", "id": 1, "quantity": 1}, {"name": "Chew Toy", "id": 4, "quantity": 2}]'}
Any help would be greatly appreciated!
Been trying for days to implement login with the /token endpoint from fastAPI in my flutter app I have checked many tutorials online but none seems to show how to do it correctly when using JWT and OAuth. I decided to go with Dio uisng fullstacks tutorial on youtube i was able to understand Dio and implement it in my app. But i get this error in flutter when i hit the login button:
error: {detail: [{loc: [body, username], msg: field required, type: value_error.missing},
And this error on fastAPI:
"POST /token HTTP/1.1" 422 Unprocessable Entity
My flutter login.dart looks like this:
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import '../../dio/dio_client.dart';
import '../../dio/dio_token_manager.dart';
import 'logout.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final _controllerUsername = TextEditingController();
final _controllerPassword = TextEditingController();
var _username = '', _password = '';
#override
void initState() {
super.initState();
() async {
DioClient.dio.interceptors.add(TokenManager.instance);
await checkLogin();
}();
}
Future<void> checkLogin() async {
try {
var response = await DioClient.dio.get('http://10.0.2.2:8000/token');
if (response.statusCode == 200) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => const LogoutScreen()));
}
} on DioError catch (e) {
debugPrint("Status code: ${e.response?.statusCode}");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(labelText: 'Username'),
validator: (val) => val!.isEmpty ? 'Username Required' : null,
onSaved: (val) => _username = val!,
keyboardType: TextInputType.text,
controller: _controllerUsername,
autocorrect: false,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (val) => val!.isEmpty ? 'Password Required' : null,
onSaved: (val) => _password = val!,
controller: _controllerPassword,
keyboardType: TextInputType.text,
autocorrect: false,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
final form = _formKey.currentState;
if (form!.validate()) {
form.save();
final snackbar = SnackBar(
duration: const Duration(seconds: 30),
content: Row(
children: const [
CircularProgressIndicator(),
Text(" Logging In...")
],
),
);
ScaffoldMessenger.of(context).showSnackBar(snackbar);
await Future.delayed(const Duration(seconds: 2));
try {
final body = {
"username": _username,
"password": _password,
};
var response = await DioClient.dio.post(
'http://10.0.2.2:8000/token',
//data: jsonEncode(body),
data: {
"username": _username,
"password": _password,
},
);
if (response.statusCode == 200) {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const LogoutScreen()));
}
} on DioError catch (e) {
debugPrint("error: ${e.response?.data}");
}
ScaffoldMessenger.of(context).hideCurrentSnackBar();
}
},
child: const Text('Log In'),
)
],
),
),
),
);
}
}
From the fastAPI localhost:8000/docs, the /token endpoint returns the 200 OK response if you are testing the API on insomnia or postman but does not work when you try to implement the same logic on a frontend app like flutter. The fastAPI return the json with an access_token:
{
"access_token": "string",
"token_type": "string"
}
The code for the fastAPI endpoints comes from this default FastAPI Docs with username as johndoe
For the Dio_token_manager.dart :
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TokenManager extends Interceptor {
static final TokenManager _instance = TokenManager._internal();
static TokenManager get instance => _instance;
TokenManager._internal();
String? _token;
#override
void onResponse(
Response response,
ResponseInterceptorHandler handler,
) {
if (response.statusCode == 200) {
var data = Map<String, dynamic>.from(response.data);
if (data['set-token'] != null) {
saveToken(data['token']);
}
} else if (response.statusCode == 401) {
clearToken();
}
super.onResponse(response, handler);
}
#override
void onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) {
options.headers['Token'] = _token;
return super.onRequest(options, handler);
}
Future<void> initToken() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_token = prefs.getString('token');
}
void saveToken(String newToken) async {
debugPrint('new token $newToken');
if (_token != newToken) {
_token = newToken;
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('token', _token!);
}
}
So for the dio_client.dart
class DioClient {
static Dio dio = Dio();
static const baseUrl = "http://10.0.2.2:8000";
static const productsEndpoint = "$baseUrl/products";}
What i have tried so far:
I tried adding the jsonEncode to the data as can be seen from the commented code in the login code.
I tried adding headers to the dioClient.post but it still doesnt work.
The fastAPI login route:
#app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
The backend works just fine i think. Maybe there is something i am not doing right. Please help. Thank you.
OAuth2PasswordRequestForm expects its data as POST form variables, not as JSON.
You can change the format sent by referencing the example given in the dio documentation for how to "Send form data" instead:
var formData = FormData.fromMap({
'name': 'wendux',
'age': 25,
});
var response = await dio.post('/info', data: formData);
In your case this would reference the username/password variables instead:
final body = FormData.fromMap({
"username": _username,
"password": _password,
});
var response = await DioClient.dio.post(
'http://10.0.2.2:8000/token',
data: body,
);
I have a flask route that queries my DB for locations and services based on a radius. Testing and working with POSTMAN.
#bp.route('/provider-locations/<int:radius>', methods=['GET'])
def get_locations_from_radius(radius):
user_latitude = request.json['lat']
user_longitude = request.json['lng']
my_obj = {}
my_obj_container = []
locations = db_session.query(ProviderLocation).filter(\
func.acos(func.sin(func.radians(user_latitude)) \
* func.sin(func.radians(ProviderLocation.latitude)) + \
func.cos(func.radians(user_latitude)) * \
func.cos(func.radians(ProviderLocation.latitude)) * \
func.cos(func.radians(ProviderLocation.longitude) - \
(func.radians(user_longitude)))) * 6371 <= radius)
for location in locations:
services = db_session.query(ProviderService).select_from(ProviderService).join(\
ServiceLocationLink).filter(ServiceLocationLink.location_id == location.id).all()
my_obj = provider_location_list_schema.dump(location)
my_obj['services'] = [provider_service_list_schema.dump(service) for service in services]
my_obj_container.append(my_obj)
return jsonify(my_obj_container)
My error comes in trying to pass this req the expected params from my client (React). I keep receiving a 400 response.
export async function getLocationServicesByRadius(radius, user_address) {
try {
const body = {
lat: user_address.lat,
lng: user_address.lng
}
return await awsApiRequest({
method: 'GET',
path: `/provider-locations/${radius}`,
params: {
body: body
},
});
} catch (err) {
console.log(err.message)
}
}
const fetchLocationServices = async () => {
const userAddress = {
lat: 43.829640,
lng: -79.470310
}
const { data, success, errorMessage } = await getLocationServicesByRadius(userDistance, userAddress)
if (success) {
console.log('RADIUS =>', data)
} else {
console.log(errorMessage)
}
}
I must be missing something somewhere but can not figure out why the req is returning 400.
the body from the client looks as so:
{
lat: 43.82964
lng: -79.47031
}
In flask request.json is used to access POST request body, for GET requests use request.args.
While calling the python API from angular 10. I am getting multiple response. How to overcome it.
Python API Response from Angular Service call:
1. Object { type: 0 } # how to avoid this additional response
2. Object { headers: {…}, status: 201, statusText: "Created", url: "https://*********/1bcd2a20-dd60-4cfe-984f-7f3607f01e7c", ok: true, type: 4, body: "{\"status\":{}}" }
Angular Service Call:
postCall(identifier): Observable<HttpEvent<{}>> {
let token1 = localStorage.getItem('token');
const headerSettings: { [name: string]: string | string[]; } = {};
headerSettings['Authorization'] = 'Bearer ' + token1;
const req = new HttpRequest('GET', 'https://***********/'+identifier, null, {
reportProgress: false,
responseType: 'text'
});
const newHeader = new HttpHeaders(headerSettings);
let changedRequest = req.clone({
headers: newHeader
});
return this.http.request(changedRequest);
}
Angularjs code
var app = angular.module('myApp', []);
app.factory('httpSend', ['$http', '$q', function($http, $q) {
var app = {};
app.sendToServer = function(data) {
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-type': 'application/x-www-form.urlencoded;'
}
}).then(function(response) {
debugger
var result = data;
});
}
app.getfromServer = function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
return app;
}]);
app.controller('myCtrl', ['$scope', '$http', 'httpSend', '$filter', function($scope, $http, httpSend, $filter) {
$scope.names = ["ankit patidar", "adhishi ahari", "kritin joshi", "kautilya bharadwaj", "punita ojha", "manvi agarwal", "apeksha purohit", "shipra jain", "mansi nangawat", "praveen soni"];
$scope.data = [];
$scope.names.forEach(function(name) {
$scope.data.push({
name: name,
checkin: "",
checkout: ""
})
});
$scope.login = [];
$scope.check = function(name, doing) {
debugger
name[doing] = new Date();
name[doing] = $filter('date')(name[doing], 'dd-MM-yyyy hh:mm:ss');
$scope.login.push(angular.copy(name));
if (doing == "checkout") {
var q = JSON.stringify($scope.login);
httpSend.sendToServer(q);
}
}
$scope.getData = function() {
httpSend.getfromServer();
}
}]);
`
Python Code
def get(self):
logging.info('get is triggered')
obj = CheckIn.query().fetch()
emp_obj = []
for x in obj:
logging.info('I am inside for loop ')
emp_obj.append({
'name': x.name,
'Check_in': x.inDate,
'check_out': x.outDate
})
logging.info('I am inside emp_obj')
self.response.write(json.dumps(emp_obj))
i need to fetch all the data stored on ndb datastore on front end view thats why i m using http get method but error is showed method not allowed. can u please help e despite using query fetch and showing its response on python ad triggering get method, why error is coming, is there a mistake in control flow or something is missing in my get method, as for now i m able to post nd store data
Change your factory to the following. Don't use the same variable app that you are using for initialising your module for your controller logic.
app.factory('httpSend',['$http', '$q',function($http, $q){
return {
'sendToServer': function(data) {
var def = $q.defer();
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
debugger
var result = response.data;
def.resolve(result );
});
return def.promise;
},
'getfromServer': function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
}
}]);