Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.
| Ambdós costats versió prèvia Revisió prèvia Següent revisió | Revisió prèvia | ||
|
integracio_de_django_amb_react [2023/07/06 08:59] raquel_alaman_navas |
integracio_de_django_amb_react [2023/07/06 10:25] (actual) raquel_alaman_navas [Integració de Reactjs (FrontEnd)] |
||
|---|---|---|---|
| Línia 24: | Línia 24: | ||
| * **Account**: | * **Account**: | ||
| - | --> Proposta implementació Customer i Account# | + | --> Proposta |
| <file python models.py> | <file python models.py> | ||
| Línia 125: | Línia 125: | ||
| from rest_framework import serializers | from rest_framework import serializers | ||
| - | # import the todo data model | + | # import the Customer |
| from .models import Customer | from .models import Customer | ||
| Línia 175: | Línia 175: | ||
| # register the router | # register the router | ||
| - | router.register(r' | + | router.register(r' |
| urlpatterns = [ | urlpatterns = [ | ||
| Línia 189: | Línia 189: | ||
| Ara comprovem si estem avançant en la direcció correcta. Per tant, executeu el servidor i navegueu fins a l'URL següent: | Ara comprovem si estem avançant en la direcció correcta. Per tant, executeu el servidor i navegueu fins a l'URL següent: | ||
| + | < | ||
| localhost: | localhost: | ||
| + | </ | ||
| Si tot va bé, obtindrem el següent resultat: | Si tot va bé, obtindrem el següent resultat: | ||
| + | {{ ::api.jpg |}} | ||
| + | |||
| + | Com podeu veure, la nostra API està en marxa. Ara, si provem d' | ||
| + | < | ||
| + | localhost: | ||
| + | </ | ||
| + | {{ :: | ||
| + | |||
| + | Fins i tot, podem canviar el format dels resultats (per exemple, retornar en formar JSON): | ||
| + | {{ :: | ||
| + | |||
| + | ===== Integració de Reactjs (FrontEnd) ===== | ||
| + | |||
| + | 1. Crea una " | ||
| + | < | ||
| + | npx create-react-app frontend | ||
| + | </ | ||
| + | on npx significa //Node Package Executable// | ||
| + | |||
| + | <WRAP info> | ||
| + | Només funcionarà la sentència anterior amb versions de node.js superiors a la 14.0, així que si et dóna error, caldrà que l' | ||
| + | </ | ||
| + | |||
| + | 2. Instal·la reactstrap i bootstrap al projecte (per donar una mica d' | ||
| + | < | ||
| + | npm install reactstrap bootstrap | ||
| + | </ | ||
| + | |||
| + | 3. Des de la terminal, accedeix al directori de frontend i executa la següent instrucció, | ||
| + | < | ||
| + | npm start | ||
| + | </ | ||
| + | |||
| + | Si és així, et sortirà una pantalla similar a aquesta (en l' | ||
| + | |||
| + | {{ :: | ||
| + | 4. Obre el fitxer //App.js// a la carpeta del frontend. Elimina el codi existent i substitueix-lo pel codi següent: | ||
| + | |||
| + | <file javascript App.js> | ||
| + | import " | ||
| + | |||
| + | function App() { | ||
| + | return <div className=" | ||
| + | } | ||
| + | |||
| + | export default App; | ||
| + | </ | ||
| + | |||
| + | 5. El pas anterior era un exemple per validar l' | ||
| + | <file javascript App.js> | ||
| + | // import Component from the react module | ||
| + | import React, { Component } from " | ||
| + | import Modal from " | ||
| + | import axios from ' | ||
| + | |||
| + | class App extends Component { | ||
| + | constructor(props) { | ||
| + | super(props); | ||
| + | |||
| + | this.state = { | ||
| + | |||
| + | viewCompleted: | ||
| + | activeItem: { | ||
| + | title: "", | ||
| + | description: | ||
| + | completed: false | ||
| + | }, | ||
| + | |||
| + | customersList: | ||
| + | }; | ||
| + | } | ||
| + | |||
| + | |||
| + | componentDidMount() { | ||
| + | this.refreshList(); | ||
| + | } | ||
| + | |||
| + | refreshList = () => { | ||
| + | axios // | ||
| + | .get(" | ||
| + | .then(res => this.setState({ customersList: | ||
| + | .catch(err => console.log(err)); | ||
| + | }; | ||
| + | |||
| + | displayCompleted = status => { | ||
| + | if (status) { | ||
| + | return this.setState({ viewCompleted: | ||
| + | } | ||
| + | return this.setState({ viewCompleted: | ||
| + | }; | ||
| + | |||
| + | |||
| + | renderTabList = () => { | ||
| + | return ( | ||
| + | <div className=" | ||
| + | <span | ||
| + | onClick={() => this.displayCompleted(true)} | ||
| + | className={this.state.viewCompleted ? " | ||
| + | > | ||
| + | completed | ||
| + | </ | ||
| + | <span | ||
| + | onClick={() => this.displayCompleted(false)} | ||
| + | className={this.state.viewCompleted ? "" | ||
| + | > | ||
| + | Incompleted | ||
| + | </ | ||
| + | </ | ||
| + | ); | ||
| + | }; | ||
| + | |||
| + | renderItems = () => { | ||
| + | const { viewCompleted } = this.state; | ||
| + | const newItems = this.state.taskList.filter( | ||
| + | (item) => item.completed === viewCompleted | ||
| + | ); | ||
| + | return newItems.map((item) => ( | ||
| + | <li | ||
| + | key={item.id} | ||
| + | className=" | ||
| + | > | ||
| + | <span | ||
| + | className={`customer-title mr-2 ${ | ||
| + | this.state.viewCompleted ? " | ||
| + | }`} | ||
| + | title={item.description} | ||
| + | > | ||
| + | {item.title} | ||
| + | </ | ||
| + | < | ||
| + | <button | ||
| + | onClick={() => this.editItem(item)} | ||
| + | className=" | ||
| + | > | ||
| + | Edit | ||
| + | </ | ||
| + | <button | ||
| + | onClick={() => this.handleDelete(item)} | ||
| + | className=" | ||
| + | > | ||
| + | Delete | ||
| + | </ | ||
| + | </ | ||
| + | </li> | ||
| + | )); | ||
| + | }; | ||
| + | |||
| + | toggle = () => { | ||
| + | //add this after modal creation | ||
| + | this.setState({ modal: !this.state.modal }); | ||
| + | }; | ||
| + | |||
| + | handleSubmit = (item) => { | ||
| + | this.toggle(); | ||
| + | | ||
| + | if (item.id) { | ||
| + | // if old post to edit and submit | ||
| + | axios | ||
| + | .put(`http:// | ||
| + | .then((res) => this.refreshList()); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | axios | ||
| + | .post(" | ||
| + | .then((res) => this.refreshList()); | ||
| + | }; | ||
| + | |||
| + | handleDelete = (item) => { | ||
| + | alert(" | ||
| + | axios | ||
| + | .delete(`http:// | ||
| + | .then((res) => this.refreshList()); | ||
| + | }; | ||
| + | | ||
| + | createItem = () => { | ||
| + | const item = { title: "", | ||
| + | this.setState({ activeItem: item, modal: !this.state.modal }); | ||
| + | }; | ||
| + | |||
| + | editItem = (item) => { | ||
| + | this.setState({ activeItem: item, modal: !this.state.modal }); | ||
| + | }; | ||
| + | |||
| + | render() { | ||
| + | return ( | ||
| + | <main className=" | ||
| + | <h1 className=" | ||
| + | GFG Task Manager | ||
| + | </h1> | ||
| + | <div className=" | ||
| + | <div className=" | ||
| + | <div className=" | ||
| + | <div className=""> | ||
| + | <button onClick={this.createItem} className=" | ||
| + | Add task | ||
| + | </ | ||
| + | </ | ||
| + | {this.renderTabList()} | ||
| + | <ul className=" | ||
| + | {this.renderItems()} | ||
| + | </ul> | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | {this.state.modal ? ( | ||
| + | <Modal | ||
| + | activeItem={this.state.activeItem} | ||
| + | toggle={this.toggle} | ||
| + | onSave={this.handleSubmit} | ||
| + | /> | ||
| + | ) : null} | ||
| + | </ | ||
| + | ); | ||
| + | } | ||
| + | } | ||
| + | export default App; | ||
| + | </ | ||
| + | |||
| + | 6. Obre el fitxer // | ||
| + | |||
| + | <file css Index.css> | ||
| + | .customer-title { | ||
| + | cursor: pointer; | ||
| + | } | ||
| + | .completed-customer { | ||
| + | text-decoration: | ||
| + | } | ||
| + | .customer-list > span { | ||
| + | padding: 5px 8px; | ||
| + | border: 1px solid rgb(7, 167, 68); | ||
| + | border-radius: | ||
| + | margin-right: | ||
| + | cursor: pointer; | ||
| + | } | ||
| + | .customer-list > span.active { | ||
| + | background-color: | ||
| + | color: #fff; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 7. Crea una carpeta nova anomenada " | ||
| + | <file javascript Modal.js> | ||
| + | import React, { Component } from " | ||
| + | |||
| + | // importing all of these classes from reactstrap module | ||
| + | import { | ||
| + | Button, | ||
| + | Modal, | ||
| + | ModalHeader, | ||
| + | ModalBody, | ||
| + | ModalFooter, | ||
| + | Form, | ||
| + | FormGroup, | ||
| + | Input, | ||
| + | Label | ||
| + | } from " | ||
| + | |||
| + | class CustomModal extends Component { | ||
| + | constructor(props) { | ||
| + | super(props); | ||
| + | this.state = { | ||
| + | activeItem: this.props.activeItem | ||
| + | }; | ||
| + | } | ||
| + | // changes handler to check if a checkbox is checked or not | ||
| + | handleChange = e => { | ||
| + | let { name, value } = e.target; | ||
| + | if (e.target.type === " | ||
| + | value = e.target.checked; | ||
| + | } | ||
| + | const activeItem = { ...this.state.activeItem, | ||
| + | this.setState({ activeItem }); | ||
| + | }; | ||
| + | |||
| + | // rendering modal in the custommodal class received toggle and on save as props, | ||
| + | render() { | ||
| + | const { toggle, onSave } = this.props; | ||
| + | return ( | ||
| + | <Modal isOpen={true} toggle={toggle}> | ||
| + | < | ||
| + | < | ||
| + | |||
| + | < | ||
| + | |||
| + | {/* 3 formgroups | ||
| + | 1 title label */} | ||
| + | < | ||
| + | <Label for=" | ||
| + | <Input | ||
| + | type=" | ||
| + | name=" | ||
| + | value={this.state.activeItem.title} | ||
| + | onChange={this.handleChange} | ||
| + | placeholder=" | ||
| + | /> | ||
| + | </ | ||
| + | |||
| + | {/* 2 description label */} | ||
| + | < | ||
| + | <Label for=" | ||
| + | <Input | ||
| + | type=" | ||
| + | name=" | ||
| + | value={this.state.activeItem.description} | ||
| + | onChange={this.handleChange} | ||
| + | placeholder=" | ||
| + | /> | ||
| + | </ | ||
| + | |||
| + | {/* 3 completed label */} | ||
| + | < | ||
| + | <Label for=" | ||
| + | <Input | ||
| + | type=" | ||
| + | name=" | ||
| + | checked={this.state.activeItem.completed} | ||
| + | onChange={this.handleChange} | ||
| + | /> | ||
| + | Completed | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | {/* create a modal footer */} | ||
| + | < | ||
| + | <Button color=" | ||
| + | Save | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | ); | ||
| + | } | ||
| + | } | ||
| + | export default CustomModal | ||
| + | </ | ||
| + | 8. Fes els canvis indicats a continuació al fitxer // | ||
| + | <file javascript index.js> | ||
| + | import React from " | ||
| + | import ReactDOM from " | ||
| + | import " | ||
| + | import App from " | ||
| + | |||
| + | import " | ||
| + | |||
| + | ReactDOM.render( | ||
| + | < | ||
| + | <App /> | ||
| + | </ | ||
| + | document.getElementById(" | ||
| + | ); | ||
| + | </ | ||
| + | 9. Per fer les peticions als endpoints de l'API al servidor del framework de Django, necessitarem instal·lar l' | ||
| + | < | ||
| + | npm install axios | ||
| + | </ | ||
| + | |||
| + | I, amb aquest pas, ja tenim una aplicació Fullstack Django-React utilitzant el framework REST Django per establir la comunicació entre el frontend i el backend. | ||
| + | |||
| + | <WRAP todo> | ||
| + | **Exercici: | ||
| + | Aplica la serialització de manera que es puguin gestionar els comptes associats als clients. | ||
| + | </ | ||
| + | |||
| + | \\ | ||
| + | |||