角度post数据不会发送到Django REST API
我使用的是角度post数据不会发送到Django REST API,django,angular,django-rest-framework,angular6,Django,Angular,Django Rest Framework,Angular6,我使用的是angular6和Django REST框架 DRF的观点是 class AmountGivenViewSet(viewsets.ModelViewSet): serializer_class = AmountGivenSerializer permission_classes = (IsAuthenticated, AdminAuthenticationPermission,) def get_queryset(self): return A
angular6
和Django REST框架
DRF的观点是
class AmountGivenViewSet(viewsets.ModelViewSet):
serializer_class = AmountGivenSerializer
permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)
def get_queryset(self):
return AmountGiven.objects.filter(
contact__user=self.request.user
)
def perform_create(self, serializer):
save_data = {}
print(self.request.POST)
# validate user and to save_data dictionary
contact_pk = self.request.POST.get('contact', None)
print(contact_pk)
if not contact_pk:
raise ValidationError({'contact': ['Contact is required']})
contact = Contact.objects.filter(
user=self.request.user,
pk=contact_pk
).first()
if not contact:
raise ValidationError({'contact': ['Contact does not exists']})
# add contact to save_data dictionary
save_data['contact'] = contact
# process mode_of_payment is in request
mode_of_payment_pk = self.request.POST.get('mode_of_payment', None)
if mode_of_payment_pk:
mode_of_payment = ModeOfPayment.objects.get(pk=mode_of_payment_pk)
if not mode_of_payment:
raise ValidationError({'mode_of_payment': ['Not a valid mode of payment']})
# add mode_of_payment to save_data dictionary
save_data['mode_of_payment'] = mode_of_payment
# pass save_data dictionary to save()
serializer.save(**save_data)
序列化程序.py中的AmountGivenSerializer
class AmountGivenSerializer(serializers.ModelSerializer):
class Meta:
model = AmountGiven
depth = 1
fields = (
'id', 'contact', 'amount', 'interest_rate', 'duration', 'given_date', 'promised_return_date',
'mode_of_payment', 'transaction_number', 'interest_to_pay', 'total_payable', 'amount_due',
'total_returned', 'comment', 'modified', 'created'
)
在角分量中
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {AmountGiven} from '../amount-given.model';
import {AmountGivenService} from '../amount-given.service';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-amount-given-add',
templateUrl: './amount-given-add.component.html',
styleUrls: ['./amount-given-add.component.css']
})
export class AmountGivenAddComponent implements OnInit {
addMoneyForm: FormGroup;
submitted = false;
contact_id: string;
amountGiven: AmountGiven;
constructor(
private formBuilder: FormBuilder,
private amountGivenService: AmountGivenService,
private route: ActivatedRoute
) { }
ngOnInit(): void {
this.route.params.subscribe(
param => {
this.contact_id = param['contact_id'];
}
);
this.addMoneyForm = this.formBuilder.group({
amount: new FormControl('', [
Validators.required
]),
interest_rate: new FormControl(),
duration: new FormControl(),
given_date: new FormControl(),
promised_return_date: new FormControl(),
transaction_number: new FormControl(),
mode_of_payment: new FormControl(),
comment: new FormControl()
});
}
get f() {
return this.addMoneyForm.controls;
}
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.addMoneyForm.invalid) {
console.log('invalid');
return;
}
const data = this.addMoneyForm.value;
data.contact = this.contact_id;
this.amountGivenService.add(data).subscribe(res => {
console.log('req completed', res);
});
}
}
import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {ResourceProviderService} from './resource-provider.service';
export interface IRequestOptions {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
body?: any;
}
export function appHttpClientCreator(http: HttpClient, resource: ResourceProviderService) {
return new AppHttpClient(http, resource);
}
@Injectable({
providedIn: 'root'
})
export class AppHttpClient {
private api_url = this.resource.url + '/api/';
constructor(
public http: HttpClient,
private resource: ResourceProviderService
) {
}
public Post<T>(endPoint: string, params: Object, options?: IRequestOptions): Observable<T> {
return this.http.post<T>(this.api_url + endPoint, params, options)
.pipe(
catchError(this.handleError('post', endPoint, null))
);
}
private handleError<T> (operation = 'operation', endpoint = '', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
console.log(error.message);
console.log(operation);
console.log(endpoint);
return of(result as T);
};
}
}
但当表单提交时,它会从服务器返回联系人字段的验证错误
{"contact":["Contact is required"]}
请求标头具有contact参数
从邮递员发送相同的请求可以正常工作。邮递员请求的Javascript XHR代码为
var data = new FormData();
data.append("amount", "5000");
data.append("contact", "65827a1f-003e-4bb3-8a90-6c4321c533e6");
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://koober-production.herokuapp.com/api/amount-given/");
xhr.setRequestHeader("Authorization", "Bearer ATjIuQ6hLzc55wHaXIzHmcKafEzk1B");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("Postman-Token", "28d9d33a-f0a6-431c-8936-da4f6565ece4");
xhr.send(data);
无法理解此问题与Angular或Django有关,因为邮差请求与Djano配合良好,Angular正在参数中发送请求
编辑2:AmountGivenService
从'@angular/core'导入{Injectable};
从“../../resource provider.service”导入{ResourceProviderService};
从“../../auth/auth.service”导入{AuthService};
从'rxjs'导入{可观察的};
从“./amount given.model”导入{AmountGiven};
从“../../app http client”导入{AppHttpClient};
@注射的({
providedIn:'根'
})
导出类AmountGivenService{
私有url='给定金额/';
建造师(
私有http:AppHttpClient
) { }
添加(数据):可观察{
返回this.http.Post(this.url,data);
}
}
这是使用AppHttpClient提供的
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {AmountGiven} from '../amount-given.model';
import {AmountGivenService} from '../amount-given.service';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-amount-given-add',
templateUrl: './amount-given-add.component.html',
styleUrls: ['./amount-given-add.component.css']
})
export class AmountGivenAddComponent implements OnInit {
addMoneyForm: FormGroup;
submitted = false;
contact_id: string;
amountGiven: AmountGiven;
constructor(
private formBuilder: FormBuilder,
private amountGivenService: AmountGivenService,
private route: ActivatedRoute
) { }
ngOnInit(): void {
this.route.params.subscribe(
param => {
this.contact_id = param['contact_id'];
}
);
this.addMoneyForm = this.formBuilder.group({
amount: new FormControl('', [
Validators.required
]),
interest_rate: new FormControl(),
duration: new FormControl(),
given_date: new FormControl(),
promised_return_date: new FormControl(),
transaction_number: new FormControl(),
mode_of_payment: new FormControl(),
comment: new FormControl()
});
}
get f() {
return this.addMoneyForm.controls;
}
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.addMoneyForm.invalid) {
console.log('invalid');
return;
}
const data = this.addMoneyForm.value;
data.contact = this.contact_id;
this.amountGivenService.add(data).subscribe(res => {
console.log('req completed', res);
});
}
}
import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {ResourceProviderService} from './resource-provider.service';
export interface IRequestOptions {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
body?: any;
}
export function appHttpClientCreator(http: HttpClient, resource: ResourceProviderService) {
return new AppHttpClient(http, resource);
}
@Injectable({
providedIn: 'root'
})
export class AppHttpClient {
private api_url = this.resource.url + '/api/';
constructor(
public http: HttpClient,
private resource: ResourceProviderService
) {
}
public Post<T>(endPoint: string, params: Object, options?: IRequestOptions): Observable<T> {
return this.http.post<T>(this.api_url + endPoint, params, options)
.pipe(
catchError(this.handleError('post', endPoint, null))
);
}
private handleError<T> (operation = 'operation', endpoint = '', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
console.log(error.message);
console.log(operation);
console.log(endpoint);
return of(result as T);
};
}
}
从'@angular/core'导入{Injectable};
从'@angular/common/http'导入{HttpClient,HttpHeaders,HttpParams};
从'rxjs'导入{可观察的};
从“rxjs/operators”导入{catchError};
从“./resource provider.service”导入{ResourceProviderService};
导出接口IRequestions{
标题?:HttpHeaders;
观察?:“身体”;
参数?:HttpParams;
reportProgress?:布尔值;
responseType?:'json';
withCredentials?:布尔值;
身体?:任何;
}
导出函数appHttpClientCreator(http:HttpClient,资源:ResourceProviderService){
返回新的AppHttpClient(http,资源);
}
@注射的({
providedIn:'根'
})
导出类AppHttpClient{
私有api_url=this.resource.url+'/api/';
建造师(
公共http:HttpClient,
私有资源:ResourceProviderService
) {
}
公共Post(端点:字符串,参数:对象,选项?:IRequestOptions):可观察{
返回this.http.post(this.api_url+端点、参数、选项)
.烟斗(
catchError(this.handleError('post',endPoint,null))
);
}
私有句柄错误(操作='operation',端点='',结果?:T){
返回(错误:任意):可观察=>{
控制台错误(error);
console.log(错误消息);
控制台日志(操作);
日志(端点);
返回(结果为T);
};
}
}
我现在还不确定是否要添加这个作为答案,但感觉您需要添加以下内容:
<form method="POST" action="url/to/your-DRF-endpoint" enctype="application/x-www-form-urlencoded">
....
</form>
....
无论是在模板中还是在Angular POST请求代码中,您都需要确保数据以application/x-www-form-urlencoded的形式发布
基本上,Django期望
application/x-www-form-urlencoded
,没有它,您的self.request.POST
对象将为空,因此self.request.POST.get('contact',None)
将为空,默认为None
问题是您试图访问:
self.request.POST.get('contact', None)
在DRF中,您需要执行以下操作:
self.request.data.get('contact', None)
它从postman开始工作,因为您正在构造一个FormData对象,它与您将要发送的JSON体有着本质的不同,这是像DRF这样的RESTful API所期望的
从更一般的角度来看,在DRF中,序列化程序应该使用内置验证器执行请求验证,而不是在视图中手动验证。我们可以看到
AmountGivenService
的代码吗?嗨,Anuj,您可能需要向表单元素添加以下内容(我不确定这样做的角度),但我知道Django需要x-www-form-urlencoded
,所以根据Angular处理此问题的方式,您需要一些复制的东西:
@R.Richards用请求的代码更新问题。Django需要标准表单,DRF需要Angular发送的JSON正文,问题是他如何尝试访问视图中的数据。通过改装将android连接到drfrequest.POST
可以正常工作,但为什么不能使用angular?为什么我们必须使用request.data
??