im trying use Django rest + angular 10, i will show a list of providers in the browser, could someone explain to me why my django api rest objects are not rendering? appear in console but not in html.
im using angular 10, django 2.7, cors, and my localhost.
this is my code.
// app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
const routes: Routes = [];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
//app.component.html
<div *ngFor='let provider of providers'>
<h2>{{ provider.name | uppercase }}</h2>
<p>{{ provider.procedence }}</p>
<p>{{ provider.email }}</p>
<p>{{ provider.telephone }}</p>
</div>
// app.component.ts
import { Component, OnInit } from '#angular/core';
import { ProviderService } from './provider.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'conexion';
providers: any[] = [];
constructor(
protected ProviderService: ProviderService
) {
}
ngOnInit() {
this.ProviderService.getProviders()
.subscribe(
(data) => { // Success
this.providers = data['results'];
console.warn(data)
},
(error) => {
console.error(error);
}
);
}
}
// app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule} from '#angular/common/http';
import { ProviderService } from './provider.service';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [ProviderService],
bootstrap: [AppComponent]
})
export class AppModule { }
// provider.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ProviderService {
constructor(protected http: HttpClient) { }
getProviders() {
return this.http.get('http://127.0.0.1:8000/provider?format=json');
}
}
To debug Use Async and learn how to use it, it's less code and less mistakes. Smart/Dumb components and OnPush Change Detection
Define
public providers$: Observable<any>;
ngOnInit
this.providers$ = this.ProviderService.getProviders();
Template
{{ providers$ | async | json }}
Related
Currently working on a website using Django and I encountered a problem. Upon row-clicking on the table row, I want it to open a new page called "doctor_qr.html" for that particular row. Does anyone know how does that work?
I would greatly appreciate any help or advice. Thank you!
<doctor_emr.html>
{% verbatim %}
<div id="app2" class="container">
<div class="emr-table">
<el-table
ref="multipleTable"
:data="list"
stripe
style="width: 50%"
#row-click="handle"
#selection-change="handleSelectionChange">
<el-table-column
prop="id"
label="Index">
</el-table-column>
<el-table-column
prop="order_id"
label="Order ID">
</el-table-column>
<el-table-column
prop="ward_number"
label="Ward No.">
</el-table-column>
<el-table-column
prop="prop"
label="Scan QR"
width="width">
</el-table-column>
</el-table>
</div>
</div>
{% endverbatim %}
<script>
new Vue({
el: '#app2',
data() {
return {
list: []
}
},
mounted() {
this.getemrList()
},
methods: {
getemrList() {
// Obtain EMR list
axios.post(ToDJ('emrList'), new URLSearchParams()).then(res => {
if (res.data.code === 0) {
console.log(res.data.data)
this.list = res.data.data
} else {
this.NotifyFail(res.data.data)
}
})
},
// Purpose: For the row click
handle(row, event, column) {
console.log(row, event, column)
axios.post(ToDJ('medicineRequestSelect'), new URLSearchParams()).then(res => {
if (res.data.code === 0) {
console.log(res.data.data)
this.list = res.data.data
let index = this.list.findIndex(item => {
return item.id == row.id
})
if (index == -1) {
this.$refs.multipleTable.toggleRowSelection(row, true);
this.list.push(row)
} else {
this.$refs.multipleTable.toggleRowSelection(row, false);
this.list.splice(index, 1)
}
} else {
this.NotifyFail(res.data.data)
}
})
},
// Success notification
NotifySuc(str) {
this.$message({
message: str,
type: 'success'
})
},
// Error notification
NotifyFail(str) {
this.$message({
message: str,
type: 'warning'
})
}
}
})
</script>
{% endblock %}
<urls.py>
from hospital import view_admin
from hospital import view_doctor
from hospital import view_nurse
from hospital import view_medicine
from hospital import view_department
from hospital import view_doctor_history
from django.urls import path
from . import views
urlpatterns = [
# Main Page
path('', views.login, name='login'),
path('login/', views.login),
path('admin/', views.admin_department, name='admin_department'),
path('admin_department/', views.admin_department),
path('admin_doctor/', views.admin_doctor),
path('admin_nurse/', views.admin_nurse),
path('admin_medicine/', views.admin_medicine),
path('doctor/', views.doctor_history),
path('doctor_history/', views.doctor_history),
path('doctor_emr/', views.doctor_emr),
]
This question already has answers here:
Reactjs, Super expression must either be null or a function
(2 answers)
Closed 5 years ago.
So I'm new to React and even though I've found multiple others having the same issue, I still haven't found the error in my code. Therefore I turn to you stackoverflow, you're my only hope!
I am learning, so I wanted to create a simple ReactJS application that handles a HTTP-request. After finishing the code I encountered the error:
Uncaught TypeError: Super expression must either be null or a function, not object
at exports.default (inherits.js?0578:21)
at eval (app.js?71f7:22)
The error persists even though I've tried a lot of different changes and I am fairly certain that it's related to imports/exports as this is what a lot of other sources tell me, although double-checking imports etc. hasn't yielded any results.
The code:
app.js ( handles the rendering of a simple button and should execute a simple GET request on click )
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { createServerSagaRequest } from '../saga/serverSaga'
import { incrRequestAmount, requestSelector } from '../reducer/requestReducer'
const mapStateToProps = (state) => {
return {
getRequestAmount: requestSelector.requests(state),
}
}
const mapDispatchToProps = (dispatch) => {
return {
open: (url, data, action, method) => dispatch(createServerSagaRequest((url, data, action, method))),
requests: () => dispatch(incrRequestAmount()),
}
}
class App extends React {
constructor(props){
super(props)
}
_buttonClick() {
this.props.requests()
this.props.open("http://mvctestproject.local/GetData", "TestDataFraGet", action, "GET")
}
render(){
return (
<button
className="btn btn-default"
onClick={this._buttonClick()}>{this.props.getRequestAmount()}
</button>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
serverSaga.js (my saga which can access the reducer and service)
import React, { Component } from 'react'
import { put, call, take, fork, select } from 'redux-saga/effects'
import { callServer } from '../service/serverService'
import { incrRequestAmount, requestSelector } from '../reducer/requestReducer'
export function createServerSagaRequest() {return { type: CREATE_REQUEST }}
function* handleRequest(url, data, action, method, success){
incrRequestAmount()
return yield executeRequest(url, data, action, method, success)
}
function* executeRequest(url, data, action, method, success) {
let response = yield call(callServer, url, method, data)
let responseSuccess = response && response.Succeeded
return
}
export default function* serverSaga(){
yield [
fork(function*(){
yield call (CREATE_REQUEST, handleRequest)
}),
]
}
rootSaga.js ( grouping sagas - in case I made more )
import { fork } from 'redux-saga/effects'
import serverSaga from './serverSaga'
export default function* rootSaga(){
yield [
fork(serverSaga)
]
}
requestReducer.js ( only function is to increment a variable after each request)
import { fromJS } from 'immutable'
export function incrRequestAmount() {return {type: 'INCR_REQUESTS'}}
const initialState = {
requestAmount: 0
}
function requestReducer(state = fromJS(initialState), action){
switch(action.type){
case 'INCR_REQUESTS':
return state.updateIn(["requestAmount"], (requests) => requests++)
default:
return state
}
}
export const requestSelector = {
amount: state => state.requests.get('requestAmount')
}
export default requestReducer
reducers.js ( grouping reducers - in case i made more )
import { combineReducers } from 'redux'
import React, { Component } from 'react'
import requests from './requestReducer'
export default combineReducers({
requests,
})
serverService.js ( handles calls to the server (GET/POST)
import React, { Component } from 'react'
export function callServer(url, bodyData, method){
let methodType = method.toLowerCase()
return new Promise((resolve, reject) => {
let r;
switch (methodType){
case 'post':
r = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(bodyData)
}
break;
case 'get':
r = {
method: 'GET'
}
break;
}
if (r) {
console.log("URL: ", url)
fetch(url, r)
.then((response) => {
console.log("Resp: ", url, response)
return response.json()
})
}
})
}
You need to extend React.Component to create a component, not React itself:
class App extends React {
should be
class App extends React.Component {
, or since you imported Component directly
class App extends Component {
I am trying to create real-time chat between Django backend and Angular 4 frontend using PostgreSQL database. Let's assume that I would like to create chatbot for instance like A.L.I.C.E. I am not sure but it seems to me that the most optimal solution would be to use websockets? I am trying to get data from frontend, add it to the PostgreSQL database and then return a response. Content at this moment is not important, I would like to focus only on connection. I am trying to do this in the way shown below without positive results. Any suggestions? In console in Safari I get:
Django:
settings.py:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "backend.routing.channel_routing",
},
}
routing.py:
from channels.routing import route
from backend.consumers import ws_add, ws_message, ws_disconnect
channel_routing = [
route("websocket.connect", ws_add),
route("websocket.receive", ws_message),
route("websocket.disconnect", ws_disconnect),
]
consumers.py:
# In consumers.py
from channels import Group
# Connected to websocket.connect
def ws_add(message):
# Accept the connection
message.reply_channel.send({"accept": True})
# Add to the chat group
Group("chat").add(message.reply_channel)
# Connected to websocket.receive
def ws_message(message):
Group("chat").send({
"text": "[user] %s" % message.content['text'],
})
# Connected to websocket.disconnect
def ws_disconnect(message):
Group("chat").discard(message.reply_channel)
Angular 4:
websocket.service.ts:
import { Injectable } from '#angular/core';
import * as Rx from 'rxjs/Rx';
#Injectable()
export class WebsocketService {
constructor() { }
private subject: Rx.Subject<MessageEvent>;
public connect(url): Rx.Subject<MessageEvent> {
if (!this.subject) {
this.subject = this.create(url);
console.log("Successfully connected: " + url);
}
return this.subject;
}
private create(url): Rx.Subject<MessageEvent> {
let ws = new WebSocket(url);
let observable = Rx.Observable.create(
(obs: Rx.Observer<MessageEvent>) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = obs.complete.bind(obs);
return ws.close.bind(ws);
})
let observer = {
next: (data: Object) => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
}
}
return Rx.Subject.create(observer, observable);
}
}
chat.service.ts:
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './websocket.service';
const CHAT_URL = 'http://0.0.0.0:8000/';
export interface Message {
author: string,
message: string
}
#Injectable()
export class ChatService {
public messages: Subject<Message>;
constructor(wsService: WebsocketService) {
this.messages = <Subject<Message>>wsService
.connect(CHAT_URL)
.map((response: MessageEvent): Message => {
let data = JSON.parse(response.data);
return {
author: data.author,
message: data.message
}
});
}
}
My solution was to change const CHAT_URL = 'http://0.0.0.0:8000/'; toconst CHAT_URL = 'ws://localhost:8000/';
I am trying to create a simple blog application using Angular2 with Django Rest Framework.
I am implementing pagination in Django, but I do not know how to rendering it in Angular.
API has the following structure.
Entries are paginated every 5 entries.
ng2app/src/app/models/entries.model.ts
export interface IEntries {
count: any,
next: any,
previous: any,
results: IResults[]
}
export interface IResults {
title: string,
body: string,
created_at: any,
updated_at: any
}
ng2app/src/app/services/entries.service.ts
import { Injectable } from "#angular/core";
import { Http } from "#angular/http";
import 'rxjs/add/operator/toPromise';
import { IEntries } from '../models/entries.model';
#Injectable()
export class EntriesService {
constructor(
private http: Http
){
}
getEntries(page: number){
return this.http
.get(`http://127.0.0.1:8000/api/entries/?limit=5&offset=` +((page * 5)-5))
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
private handleError(error: any) {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
ng2app/src/app/services/entries.component.ts
import { Component, OnInit } from '#angular/core';
import { EntriesService } from '../services/entries.service';
import { IEntries } from '../models/entries.model';
#Component({
selector: 'my-entries',
templateUrl: '../templates/entries.component.html',
styleUrls: ['../static/entries.component.css']
})
export class EntriesComponent implements OnInit{
title = 'entries';
entries: IEntries[] = [];
error: any;
public constructor(
private entriesService: EntriesService,
){}
getEntires(page :number) {
this.entriesService
.getEntries(page)
.then(entries => this.entries = entries)
.catch(error => this.error = error);
}
ngOnInit() {
this.getEntires(1);
}
}
ng2app/src/app/templates/entries.component.html
<div class="container">
<h2>{{title}}</h2>
<div class="panel panel-default" *ngFor="let results of entries.results">
<div class="panel-heading">{{ results.title }}</div>
<div class="panel-body pre-wrap" ng-bind="multiLineText">{{ results.body }}</div>
<div class="panel-footer">{{ results.created_at | date}}</div>
</div>
<nav *ngIf="entries.count > 5">
(I want to display pagination here)
</nav>
</div>
In such a case, please help how to implement Pagination.
After implementing pagination in the Django backend, querying the backend would return results in the following format:
"data": {
"count": ,
"next": "",
"previous": "",
"results": []
}
count: The total number of items returned.
next: The URL to the next items after performing pagination
previous: The URL to the previous items after you have navigated to the next. set of items
results: The items requested for from the backend, paginated obviously i.e if pagination was set to 10 items and 15 were returned, results would return 10 items on the first request, then after navigating to the URL in next, results would return the remaining 5.
Service
#Injectable({
providedIn: "root"
})
export class OurService {
constructor(private http: HttpClient) {}
// Here,we make our request to the backend API, this observer takes in the backend
// api url as a parameter and performs a GET request
getAllTransactions(APIUrl: string): Observable<any> {
return this.http.get<>(APIUrl);
}
}
Component
#Component({
selector: "app-transactions",
templateUrl: "./transactions.component.html",
styleUrls: ["./transactions.component.scss"]
})
export class TransactionsComponent implements OnInit {
transactions: Transacton[];
transactionsUrl = "http://.../api/v1/transactions/"; //url to query for the transactions
next: string;
previous: string;
constructor(private transactionService: TransactionService) {}
ngOnInit(): void {
// On component initialization, load the transactions on the page
this.getTransactions(this.transactionsUrl);
}
getTransactions(url: string) {
this.transactionService.getAllTransactions(url).subscribe(res => {
this.transactions = res.data.results;
if (res.data.next) {
// set the components next transactions here from the response
this.next = res.data.next;
}
if (res.data.previous) {
// set the components previous transactions here from the response
this.previous = res.data.previous;
}
});
}
// function fetches the next paginated items by using the url in the next transactions
fetchNext() {
this.getTransactions(this.next);
}
// function fetches the previous paginated items by using the url in the previous transactions
fetchPrevious() {
this.getTransactions(this.previous);
}
HTML
<div class="page-buttons">
<button class="btn prev" (click)="fetchPrevious()">
</button>
<button class="btn next" (click)="fetchNext()">
</button>
</div>
You can try ngx-pagination for pagination in Angular 2+.
I need to pass from AngularJS to python a JSON object. JSON structure would be:
{ "name": "Bob",
"address": "Springfield",
"cars": [
{ "model": "Renault C15", "year": "1965" },
...
{ "model": "Ford Ka", "year": "1998" } ]
}
This is a fragment of my AngularJS controller. All parameters are input from an HTML form (in this case the array "cars" has been created manually, to show you the way I have it programmed)
$scope.cars= [];
var car1 = { model: 'Renault C15', year: '1965' };
var car2 = { model: 'Ford Ka', year: '1998' };
$scope.cars.push(car1);
$scope.cars.push(car2);
...
$scope.newForm = function() {
var dataToSend= {
name: $scope.name,
address: $scope.address,
cars: $scope.cars
};
$http({
method: 'POST',
url: '/myUrl/something',
data: $.param(dataToSend),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
...
}
If I inspect the POST request I see the following parameters:
name Bob
address Springfield
cars[0][model] Renault C15
cars[0][year] 1965
cars[1][model] Ford Ka
cars[1][year] 1998
Initially, I will not know how many items will have the array "cars".
Now, this is the header of a python function. I know how to store the normal arguments but I don't know how to do the same thing with array "cars". I would store it as a python list or dictionary.
def something(self, **params):
...
name=params['name']
address=params['address']
...
How can I store the array?
I won't tell you about AngularJS part as it's out of my interest, but I can tell you about CherryPy. It is be much easier for you to send and process your data as application/json, so I suggest you to avoid application/x-www-form-urlencoded and search how to send JSON with your client library. With CherryPy, of course, you can handle both ways.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
class App:
#cherrypy.expose
def index(self):
return '''<!DOCTYPE html>
<html>
<head>
<title>CherryPy demo</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
<script type='text/javascript'>
var data = {
"name": "Bob",
"address": "Springfield",
"cars": [
{ "model": "Renault C15", "year": "1965" },
{ "model": "Ford Ka", "year": "1998" }
]
};
$(document).ready(function()
{
$('#send-json').on('click', function()
{
$.ajax({
'type' : 'POST',
'dataType' : 'JSON',
'contentType' : 'application/json',
'url' : '/jsonin',
'data' : JSON.stringify(data),
'success' : function(response)
{
console.log(response);
}
});
});
$('#send-form').on('click', function()
{
$.ajax({
'type' : 'POST',
'dataType' : 'JSON',
'url' : '/formin',
'data' : data,
'success' : function(response)
{
console.log(response);
}
});
});
});
</script>
</head>
<body>
<p><a href='#' id='send-json'>Send JSON</a></p>
<p><a href='#' id='send-form'>Send form</a></p>
</body>
</html>
'''
#cherrypy.expose
#cherrypy.tools.json_out()
def formin(self, **kwargs):
# You can just print a variable a see it in the terminal
# where CherryPy is executed
print(kwargs)
# You would see
# {
# 'cars[1][year]': u'1998',
# 'name': u'Bob',
# 'cars[0][model]': u'Renault C15',
# 'address': u'Springfield',
# 'cars[0][year]': u'1965',
# 'cars[1][model]': u'Ford Ka'
# }
return kwargs.items()
#cherrypy.expose
#cherrypy.tools.json_in()
#cherrypy.tools.json_out()
def jsonin(self):
data = cherrypy.request.json # just the same structure
return data.items()
if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)