Básicos del Lenguaje

1

Guía de instalación y conceptos básicos

2

Archivos y slides del curso práctico de Python

3

IMPORTANTE: Instalando Ubuntu Bash en Windows para facilitarte el seguimiento del curso desde Windows.

4

¿Qué es la programación?

5

¿Por qué programar con Python?

6

Operadores matemáticos

7

Variables y expresiones

8

Presentación del proyecto

9

Funciones

10

Usando funciones en nuestro proyecto

11

Operadores lógicos

12

Estructuras condicionales

Uso de strings y ciclos

13

Strings en Python

14

Operaciones con Strings en Python

15

Operaciones con strings y el comando Update

16

Operaciones con strings y el comando Delete

17

Operaciones con strings: Slices en python

18

For loops

19

While loops

20

Iterators and generators

Estructuras de Datos

21

Uso de listas

22

Operaciones con listas

23

Agregando listas a nuestro proyecto

24

Diccionarios

25

Agregando diccionarios a nuestro proyecto

26

Tuplas y conjuntos

27

Tuplas y conjuntos en código

28

Introducción al módulo collections

29

Python comprehensions

30

Búsquedas binarias

31

Continuando con las Búsquedas Binarias

32

Manipulación de archivos en Python 3

Uso de objetos y módulos

33

Decoradores

34

Decoradores en Python

35

¿Qué es la programación orientada a objetos?

36

Programación orientada a objetos en Python

37

Scopes and namespaces

38

Introducción a Click

39

Definición a la API pública

40

Clients

41

Servicios: Lógica de negocio de nuestra aplicación

42

Interface de create: Comunicación entre servicios y el cliente

43

Actualización de cliente

44

Interface de actualización

45

Manejo de errores y jerarquía de errores en Python

46

Context managers

Python en el mundo real

47

Aplicaciones de Python en el mundo real

Conclusiones finales

48

Python 2 vs 3 (Conclusiones)

Clases bonus

49

Entorno Virtual en Python y su importancia: Python en el mundo real

You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
11 Hrs
43 Min
53 Seg

Interface de create: Comunicación entre servicios y el cliente

42/49
Resources

How to list clients from client services?

There comes a crucial point in software development where we need to interact with our data effectively. In this case, it is about implementing a method that allows us to list customers from client services to better understand who our customers are. The way we manage our data can determine the success of our applications.

To implement the list method in client services, we must start by declaring a new method called list_clients, which does not need external arguments, only self. The main purpose is to open the file where the reference to our client table is stored in read mode (using r-mode to read).

How is the Reader used?

The data reading is done using a dict reader. This process is carried out quickly using DictReader which receives as parameters the file and the fieldnames extracted from client_skema. It is important to remember that the Reader is an iterable, and to convert it into a usable list, we use the global list function. Thus, the method returns a list of clients.

def list_clients(self): with open(self.filename,  mode='r') as f: reader = DictReader(f,  fieldnames=ClientSchema().FIELD_NAMES) return list(reader)

How to integrate the command interface to show the clients?

Once we have the method to list our clients, the next step is to present them in a friendly way in the console. To do this, it is necessary to create an interface in the commands.

How is the list command defined in the console?

First, we look for and identify where the commands are declared. In this case, the list command does not need additional arguments or options, unlike the create command. It starts by instantiating the ClientService class, passing the name of the corresponding table. Then, a table is generated to display the results:

  1. The headers are printed: ID, Name, Company, Email, and Position.
  2. A line is drawn to separate the headers from the data.
  3. Iterate over the list of customers, formatting a string for each one and displaying their data.

Why use click echo instead of print?

Using click echo ensures that the behavior of our console print is consistent across different operating systems, a problem that could occur with print. Therefore, we replace print calls with click echo to ensure this uniformity.

# Replacing print calls by click echoclick.echo('ID Name Company Email Position')click.echo('-' * 60)for client in client_list: click.echo('{} {} {} {} {} {} {} {}'.format( client['uid'], client['name'], client['company'], client['email'], client['position'] ))

How to run and test the program?

Finally, once we have correctly implemented and adapted the methods and commands, it is time to test the program:

  1. List is invoked using the command p b clients list, displaying the first client.
  2. A new client can be created, entering data such as name, company, email and position.
  3. Then, again by running p b clients list, we will see that the two clients are displayed, which shows that the program is working correctly.

This progress reflects a significant step forward, giving clarity on how to manage data in an application that slowly resembles what is needed in the industry. It's a great time to celebrate and keep learning!

Contributions 33

Questions 9

Sort by:

Want to see more contributions, questions and answers from the community?

Tablas con mejor formato
¡Hola a todos! Les comparto una mejora que le hice al código para que la tabla tenga un mejor formato.
Utilicé un módulo llamado Tabulate, que pueden encontrar en la página oficial de PyPI o solo instalarlo con $ pip install tabulate.

El código del método list queda así:

from tabulate import tabulate

@clients.command()
@click.pass_context
def list(ctx):
    """List all clients"""
    client_service = ClientService(ctx.obj['clients_table'])
    clients_list = client_service.list_clients()

    headers = [field.capitalize() for field in Client.schema()]
    table = []

    for client in clients_list:
        table.append(
            [client['name'],
             client['company'],
             client['email'],
             client['position'],
             client['uid']])

    print(tabulate(table, headers))

El resultado:

Les recomiendo leer un poco más acerca del funcionamiento del módulo aquí.

Deberían compartir el código por que el mio no funciona y no tengo con que compararlo…

Muy interesante, lástima que a muchos no nos haya servido.
Al ejecutar no aparece nada. 😐
Un poco de calma, sobretodo al principio, hubiese sido de mucha ayuda.

Qué diferencia hay entre:
mode=‘a’ y mode=‘w’?
Uno añade y el otro escribe, pero si escribes no estás añadiendo?

Yo implementé asi el for:

 for client in client_list:
        name, company, email, position, id = list(client.values()) # Guarda los valores.
        print(f"{id} | {name} | {company} | {email} | {position}")

Con PrettyTable también es posible formatear la tabla en la consola.

from prettytable import PrettyTable

@clients.command()
@click.pass_context
def list(ctx):
    """List all clients"""
    client_service = ClientService(ctx.obj['clients_table'])
    clients = client_service.list_clients()

    table = PrettyTable()

    table.field_names = [c.upper() for c in Client.schema()]
    for client in clients:
        table.add_row([
            
            client['name'],
            client['company'],
            client['email'],
            client['position'],
            client['uid'],
        ])

    click.echo(table)

Me generó una inquietud y es que el profesor colocó una función en el archivo commands.py la cual tiene como nombre list y pues se supone que es una keyword reservada de Python, lo extraño es que no le haya fallado.

🙋Aqui:
👉Archivos de la clase 43:
commands.py
services.py

al ejecutar mi programa me manda el siguiente error :

File “C:\platzi-ventas\lib\site-packages\click\decorators.py”, line 71, in _make_command
raise TypeError('Attempted to convert a callback into a '
TypeError: Attempted to convert a callback into a command twice.

Alguien sabe a que se refiere ?

Fantástico el uso del Framework Click para la creación de API’s
La función click.echo(), que en muchos sentidos funciona como la declaración print o función de Python. La principal diferencia es que funciona igual en Python 2 y 3, detecta inteligentemente los flujos de salida mal configurados y nunca fallará (excepto en Python 3)

Para las personas que quieran practicar con una clase para mejorar la visualización de la data, les comparto este package
https://pypi.org/project/beautifultable/
Tanto su documentación como varios ejemplos de uso aparecen allí.

Implementacion inicial de lista de clientes
se modificos 2
services.py
se agrego funcion list_clients //metodo para leer csv a un objeto lista usando
//el metodo estatico de clase client
command.py
se modifico el metodo list_clients
se intancia la clase ClientServices con los paremetro nombre de la tabla de contexto
en la variable client_service se hace referencia a nuestra clase Client_service
//trae el listado de clientes
en la variable lista client_list se accesa al metodo de la variable client_service
instanciada al metodo list_clients
//se crea encabezado de datos a mostrar
//iteramos a lo largo de nuestra lista de clientes

Commands.py

import click
from clients.services import ClientServices
from clients.models import Client


@click.group()
def clients():
    """ Manages the clients lifecycle"""
    pass


@clients.command()
@click.option('-n', '--name',
                type=str,
                prompt=True,
                help='The client name')

@click.option('-c', '--company',
                type=str,
                prompt=True,
                help='The client Company')
                

@click.option('-e', '--email',
                type=str,
                prompt=True,
                help='The client email')


@click.option('-p', '--position',
                type=str,
                prompt=True,
                help='The client position')



@click.pass_context
def create(ctx, name, company, email, position):
    """Create a new client """
    client = Client(name, company, email, position)
    client_service = ClientServices(ctx.obj['clients_table'])

    client_service.create_client(client)


@clients.command()
@click.pass_context
def list_clients(ctx):
    """List all clients"""
    client_services = ClientServices(ctx.obj['clients_table'])
    client_list = client_services.list_clients()

    click.echo('  ID  |  NAME  |  COMPANY  |  EMAIL  |  POSITION')
    click.echo('*'*50)

    for client in client_list:
        print('{uid}  |  {name}  |  {company}  |  {email}  |  {position}'.format(
            uid = client['uid'],
            name = client['name'],
            company = client['company'],
            email = client['email'],
            position = client['position']
        ))

@clients.command()
@click.pass_context
def update(ctx, client_name):
    """Update a client """


@clients.command()
@click.pass_context
def delete(ctx, client_name):
    """Delete a client"""
    pass

all = clients

services.py

import csv
from clients.models import Client

class ClientServices:
    def __init__(self, table_name):
        self.table_name = table_name
    

    def create_client(self, client):
        with open(self.table_name, mode='a') as f:
            write = csv.DictWriter(f, fieldnames=Client.schema())
            write.writerow(client.to_dict())
    

    def list_clients(self):
        with open(self.table_name, 'r') as f :
            reader = csv.DictReader(f, fieldnames=Client.schema())

            return list(reader)

Aunque realmente click no se vaya a usar mucho en la carrera, pues no creo que haya usuarios finales ejecutando desde la terminal, pero para los programadores si vale la pena como para que se vea más especial 🙆‍♂️y de paso se pone en práctica decoradores.

los engañe min 6:00 jajajajaja tan chistoso :v

quedo buenisimo con la libreria tabulate

from email import header
import click
from tabulate import tabulate

from clients.services import ClientService
from clients.models import ClientModel

@click.group()
def clients():
    """Manages the clients lifecycle"""
    pass


@clients.command()
@click.option('-n', '--name',    # nombre y su abreviacion para acceder a este comando.
                type = str,      # tipo String es lo que almacena
                prompt = True,   # si no me lo dan en la funcion se lo pedimos al usuario
                help = 'The client\'s name') # mostrar ayuda
@click.option('-c', '--company',
                type = str,
                prompt = True,
                help = 'The client\'s company')
@click.option('-e', '--email',
                type = str,
                prompt = True,
                help = 'The client\'s email')
@click.option('-p', '--position',
                type = str,
                prompt = True,
                help = 'The client\'s position')


@click.pass_context
def create(ctx, name, company, email, position):
    """Create a new client """
    client =  ClientModel(name, company, email, position)
    client_service = ClientService(ctx.obj['clients_table'])
    client_service.create_client(client)


@clients.command()
@click.pass_context
def list(ctx,):
    """List all clients"""
    client_service = ClientService(ctx.obj['clients_table'])
    clients_list = client_service.list_clients()
    #click.echo(' ID | NAME | COMPANY | EMAIL | POSITION')
    headers = [field.capitalize() for field in ClientModel.schema()]
    #click.echo("-"*100)
    body = []
    for client in clients_list:
        """
        click.echo('{uid} | {name} | {company} | {email} | {position}'.format(
            uid= client['uid'],
            name = client['name'],
            company =  client['company'],
            email = client['email'],
            position = client['position']))
        """
        body.append(
            [client['name'],
             client['company'],
             client['email'],
             client['position'],
             client['uid']])
    click.echo(tabulate(body ,headers))

@clients.command()
@click.pass_context
def update(ctx,client_uid):
    """Updates a client"""
    pass


@clients.command()
@click.pass_context
def delete(ctx, client_uid):
    """Delete a client"""
    pass


all = clients

hay convenciones para dar ejemplos de nombres, pueden nombres pequeños o también fu y var.

print tiene diferentes ejecuciones en los sistemas operativos, por lo que para imprimir algo es mucho mejor utilizar click.echo

Interesante me llamo mucho la atencion ese metodo .echo hice una pequeña investigacion de el y encontre este post esta genial practicamente se puede reemplazar por un print

Click documentation

genial u.u., toca repasar el curso

me aparece este error cuando trato de crear un nuevo usuario desde cmd
TypeError: init() got an unexpected keyword argument ‘promp’

Super

cuando creo un cliente desde cmd con pv clients create no me permite crearlo

Estoy usando git bash desde windows y me generó algunos problemas el caractér de nueva línea cuando python maneja los archivos. Para solucionarlo definí el parámetro de newline en el comando open de la siguiente manera:

open(self.table_name, mode='r', newline='')

Creo que todos los que usen Windows les afecta, pero no estoy seguro.

Amigos, necesito algo de ayuda, inicialicé el ambiente e instalé el módulo pv, pero no estoy pudiendo utilizar el programa pv, me comenta que:

/Users/davidbehar/David: bad interpreter: No such file or directory

me aparece este error cuando trato de crear un usuario o cuando escribo en cmd pv clients help

Traceback (most recent call last):
File “C:\Users\LeoVanXavi\Documents\programas_en_python\platzi-ventas\pv.py”, line 4, in <module>
from clients import commands as clients_commands
File “C:\Users\LeoVanXavi\Documents\programas_en_python\platzi-ventas\clients\commands.py”, line 62, in <module>
@click.pass_context
File “C:\Users\LeoVanXavi\Documents\programas_en_python\platzi-ventas\env\lib\site-packages\click\decorators.py”, line 173, in decorator
_param_memo(f, OptionClass(param_decls, **option_attrs))
File “C:\Users\LeoVanXavi\Documents\programas_en_python\platzi-ventas\env\lib\site-packages\click\core.py”, line 1547, in init
Parameter.init(self, param_decls, type=type, **attrs)
TypeError: init() got an unexpected keyword argument ‘promp’

Interfaz para la lista de los cliente:

@clients.command()
@click.pass_context
def list(ctx):
  """List all clients"""
  client_service = ClientService(ctx.obj['clients_table'])

  client_list = client_service.list_clients()

  click.echo(' ID  | NAME  | COMPANY | EMAIL | POSITION  ')
  click.echo('*' * 100)

  for client in client_list:
    click.echo(f'''{client['uid']} | {client['name']} | {client['company']} | {client['email']} | {client['position']}''')

En las primeras clases, indica que hay una convención muy interesante en Python. Es muy recomendable leerlo, puesto que uno de ellos habla de la cantidad de caracteres que debe haber por línea.

Es genial, como va tomando forma todo el proyecto. Pese a que aún quedan algunas dudas, lo mejor es leer. Ya me decía un profesor RTFM.

Al ejecutarlo me decía que un Group objeto no es iterable por lo que tuve que cambiar el for así:

@clients.command()
@click.pass_context
def list(ctx):
	"""List all clients"""
	client_service=ClientService(ctx.obj['clients_table'])
	client_list=client_service.list_clients()
	click.echo('ID  |  NAME  |  COMPANY  |  EMAIL  |  POSITION')
	click.echo('*'*100)
	
	for client in client_list:
		click.echo('{uid} | {name} | {company} | {email} | {position}'.format(
			uid=client['uid'],
			name=client['name'],
			company=client['company'],
			email=client['email'],
			position=client['position']) )```

a seguir practicando, ya va tomando forma. y captando mejor

si hago el comando para ver la lista de clientes y la ventana de la consola es pequeña, me muestra la lista completa, pero cuando la pongo pantalla completa, quita el ultimo cliente(si ya habia hecho el comando con la ventana pequeña)
que curioso ._., creeria que no es por mi codigo, si alguien mas le pasa me gusaria saber
NOTA: utilizo Linux

commands.py

<import click

from clients.services import ClientServices
from clients.models import Client

@click.group()
def clients():
    """Manages the clients lifecycle"""
    pass


@clients.command()
@click.option('-n', '--name',
                type=str,
                prompt=True,
                help='The client name')
@click.option('-c', '--company',
                type=str,
                prompt=True,
                help='The client company')
@click.option('-e', '--email',
                type=str,
                prompt=True,
                help='The client email')
@click.option('-p', '--position',
                type=str,
                prompt=True,
                help='The client position')
@click.pass_context
def create(ctx, name, company, email, position):
    """Creates a new client"""
    client = Client(name, company, email, position)
    client_service = ClientServices(ctx.obj['clients_table'])

    client_service.create_client(client)


@clients.command()
@click.pass_context
def list(ctx):
    """Lists all clients"""
    client_services = ClientServices(ctx.obj['clients_table'])

    client_list = client_services.list_clients()

    click.echo(' ID | NAME | COMPANY | EMAIL | POSITION ')
    click.echo('*' * 100)

    for client in client_list:
        click.echo('{uid} | {name} | {company} | {email} | {position}'.format(uid=client['uid'],
        name=client['name'],
        company=client['company'],
        email=client['email'],
        position=client['position']))


@clients.command()
@click.pass_context
def update(ctx, client_uid):
    """Updates a client"""
    pass


@clients.command()
@click.pass_context
def delete(ctx, client_uid):
    """Deletes a client"""
    pass


"""all points out to clients function"""
all = clients
>

services.py

<import csv

from clients.models import Client


class ClientServices:

    def __init__(self, table_name):
        self.table_name = table_name
    

    def create_client(self, client):
        with open(self.table_name, mode='a') as f:
            writer = csv.DictWriter(f, fieldnames=Client.schema())
            writer.writerow(client.to_dict())

    
    def list_clients(self):
        with open(self.table_name, mode='r') as f:
            reader = csv.DictReader(f, fieldnames=Client.schema())

            return list(reader)
>

en el modo de apertura, tenemos a de append, r de reader y w de writer.