portaldacalheta.pt
  • Κύριος
  • Επενδυτές & Χρηματοδότηση
  • Σχεδιασμός Διεπαφής Χρήστη
  • Τεχνολογία
  • Διαχείριση Έργου
Τεχνολογία

Εφαρμογές υψηλής απόδοσης με Python - Ένας οδηγός FastAPI



Τα καλά γλωσσικά πλαίσια προγραμματισμού διευκολύνουν την ταχύτερη παραγωγή ποιοτικών προϊόντων. Τα μεγάλα πλαίσια κάνουν ακόμη και όλη την εμπειρία ανάπτυξης ευχάριστη. Το FastAPI είναι ένα νέο πλαίσιο ιστού Python που είναι ισχυρό και ευχάριστο στη χρήση. Οι ακόλουθες δυνατότητες κάνουν το FastAPI να δοκιμάζεται:

  • Ταχύτητα: Το FastAPI είναι ένα από τα ταχύτερα πλαίσια Ιστού της Python. Στην πραγματικότητα, η ταχύτητά του είναι ίση με τα Node.js και Go. Ελεγχος αυτά τα δοκιμές απόδοσης.
  • Λεπτομερή και εύχρηστα έγγραφα προγραμματιστών
  • Πληκτρολογήστε τον κωδικό σας και λάβετε δωρεάν επικύρωση και μετατροπή δεδομένων.
  • Δημιουργήστε εύκολα προσθήκες χρησιμοποιώντας εξάρτηση εξάρτησης.

Δημιουργία εφαρμογής TODO

Για να εξερευνήσετε τις μεγάλες ιδέες πίσω από το FastAPI, ας δημιουργήσουμε μια εφαρμογή TODO, η οποία δημιουργεί λίστες υποχρεώσεων για τους χρήστες της. Η μικροσκοπική μας εφαρμογή θα παρέχει τις ακόλουθες δυνατότητες:



  • Εγγραφή και σύνδεση
  • Προσθήκη νέου προϊόντος TODO
  • Λάβετε μια λίστα με όλα τα TODO
  • Διαγραφή / Ενημέρωση ενός στοιχείου TODO

SQLAlchemy για μοντέλα δεδομένων

Η εφαρμογή μας έχει μόνο δύο μοντέλα: Χρήστη και TODO. Με τη βοήθεια του SQLAlchemy, της εργαλειοθήκης βάσης δεδομένων για την Python, μπορούμε να εκφράσουμε τα μοντέλα μας ως εξής:



class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True, index=True) lname = Column(String) fname = Column(String) email = Column(String, unique=True, index=True) todos = relationship('TODO', back_populates='owner', cascade='all, delete-orphan') class TODO(Base): __tablename__ = 'todos' id = Column(Integer, primary_key=True, index=True) text = Column(String, index=True) completed = Column(Boolean, default=False) owner_id = Column(Integer, ForeignKey('users.id')) owner = relationship('User', back_populates='todos')

Μόλις τα μοντέλα μας είναι έτοιμα, ας γράψουμε το αρχείο διαμόρφωσης για το SQLAlchemy έτσι ώστε να ξέρει πώς να δημιουργήσει σύνδεση με τη βάση δεδομένων.



import os from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = os.environ['SQLALCHEMY_DATABASE_URL'] engine = create_engine( SQLALCHEMY_DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base()

Απελευθερώστε τη δύναμη των συμβουλών τύπου

Ένα μεγάλο μέρος οποιουδήποτε έργου API αφορά τα συνηθισμένα πράγματα, όπως επικύρωση δεδομένων και μετατροπή. Ας το αντιμετωπίσουμε προτού προχωρήσουμε στο χειρισμό γραπτών αιτημάτων. Με το FastAPI, εκφράζουμε το σχήμα των εισερχόμενων / εξερχόμενων δεδομένων μας χρησιμοποιώντας pydantic μοντέλα και στη συνέχεια χρησιμοποιούμε αυτά τα pydantic μοντέλα για να πληκτρολογήσετε υπόδειξη και να απολαύσετε δωρεάν επικύρωση και μετατροπή δεδομένων. Λάβετε υπόψη ότι αυτά τα μοντέλα δεν σχετίζονται με τη ροή εργασίας της βάσης δεδομένων μας και καθορίζουν μόνο το σχήμα των δεδομένων που ρέουν μέσα και έξω από τη διεπαφή REST. Για να γράψετε pydantic μοντέλα, σκεφτείτε όλους τους τρόπους με τους οποίους οι πληροφορίες χρήστη και TODO θα εισέρχονται και εξέρχονται.

Παραδοσιακά, ένας νέος χρήστης θα εγγραφεί στην υπηρεσία TODO μας και ένας υπάρχων χρήστης θα συνδεθεί. Και οι δύο αυτές αλληλεπιδράσεις αφορούν τις πληροφορίες χρήστη, αλλά το σχήμα των δεδομένων θα είναι διαφορετικό. Χρειαζόμαστε περισσότερες πληροφορίες από τους χρήστες κατά την εγγραφή και ελάχιστες (μόνο email και κωδικός πρόσβασης) κατά τη σύνδεση. Αυτό σημαίνει ότι χρειαζόμαστε δύο pydantic μοντέλα για να εκφράσουμε αυτά τα δύο διαφορετικά σχήματα πληροφοριών χρήστη.



Στην εφαρμογή TODO, ωστόσο, θα αξιοποιήσουμε την ενσωματωμένη υποστήριξη OAuth2 στο FastAPI για ροή σύνδεσης βάσει JSON Web Tokens (JWT). Πρέπει απλώς να ορίσουμε ένα UserCreate σχήμα εδώ για να καθορίσετε δεδομένα που θα ρέουν στο τελικό σημείο εγγραφής και ένα UserBase σχήμα για επιστροφή ως απόκριση σε περίπτωση που η διαδικασία εγγραφής είναι επιτυχής.

from pydantic import BaseModel from pydantic import EmailStr class UserBase(BaseModel): email: EmailStr class UserCreate(UserBase): lname: str fname: str password: str

Εδώ, επισημάνουμε το επώνυμο, το όνομα και τον κωδικό πρόσβασης ως συμβολοσειρά, αλλά μπορεί να ενισχυθεί περαιτέρω χρησιμοποιώντας το pydantic περιορισμένες χορδές που επιτρέπουν ελέγχους όπως το ελάχιστο μήκος, το μέγιστο μήκος και τους regexes.



Για να υποστηρίξουμε τη δημιουργία και την καταχώριση στοιχείων TODO, ορίζουμε το ακόλουθο σχήμα:

class TODOCreate(BaseModel): text: str completed: bool

Για να υποστηρίξουμε την ενημέρωση ενός υπάρχοντος στοιχείου TODO, ορίζουμε ένα άλλο σχήμα:



class TODOUpdate(TODOCreate): id: int

Με αυτό, τελειώσαμε με τον καθορισμό σχημάτων για όλες τις ανταλλαγές δεδομένων. Τώρα στρέφουμε την προσοχή μας στους αιτούντες χειριστές όπου αυτά τα σχήματα θα χρησιμοποιηθούν για να κάνουν όλη τη βαριά άρση της μετατροπής και επικύρωσης δεδομένων δωρεάν.

Αφήστε τους χρήστες να εγγραφούν

Αρχικά, ας επιτρέψουμε στους χρήστες να εγγραφούν, καθώς όλες οι υπηρεσίες μας πρέπει να έχουν πρόσβαση από έναν πιστοποιημένο χρήστη. Γράφουμε το χειριστή πρώτου αιτήματος χρησιμοποιώντας το UserCreate και UserBase σχήμα που ορίζεται παραπάνω.



@app.post('/api/users', response_model=schemas.User) def signup(user_data: schemas.UserCreate, db: Session = Depends(get_db)): '''add new user''' user = crud.get_user_by_email(db, user_data.email) if user: raise HTTPException(status_code=409, detail='Email already registered.') signedup_user = crud.create_user(db, user_data) return signedup_user

Υπάρχουν πολλά πράγματα σε αυτό το σύντομο κομμάτι κώδικα. Χρησιμοποιήσαμε έναν διακοσμητή για να καθορίσουμε το ρήμα HTTP, το URI και το σχήμα επιτυχημένων απαντήσεων. Προκειμένου να διασφαλιστεί ότι ο χρήστης έχει υποβάλει τα σωστά δεδομένα, πληκτρολογήσαμε την υπόδειξη του σώματος αιτήματος με ένα προηγούμενο καθορισμένο UserCreate σχήμα. Η μέθοδος καθορίζει μια άλλη παράμετρο για τη λήψη μιας λαβής στη βάση δεδομένων - αυτή είναι η εξάρτηση εξάρτησης σε δράση και συζητείται αργότερα σε αυτό το σεμινάριο.

Εξασφάλιση του API μας

Θέλουμε τα ακόλουθα χαρακτηριστικά ασφαλείας στην εφαρμογή μας:



  • Κατακερματισμός κωδικού πρόσβασης
  • Έλεγχος ταυτότητας με βάση το JWT

Για κατακερματισμό κωδικού πρόσβασης, μπορούμε να χρησιμοποιήσουμε το Passlib. Ας καθορίσουμε τις λειτουργίες που χειρίζονται τον κατακερματισμό του κωδικού πρόσβασης και ελέγχουμε αν ο κωδικός πρόσβασης είναι σωστός

from passlib.context import CryptContext pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto') def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password): return pwd_context.hash(password) def authenticate_user(db, email: str, password: str): user = crud.get_user_by_email(db, email) if not user: return False if not verify_password(password, user.hashed_password): return False return user

Για να ενεργοποιήσουμε τον έλεγχο ταυτότητας με βάση το JWT, πρέπει να δημιουργήσουμε JWT καθώς και να τα αποκωδικοποιήσουμε για να λάβουμε διαπιστευτήρια χρήστη. Ορίζουμε τις ακόλουθες λειτουργίες για να παρέχουμε αυτήν τη λειτουργικότητα.

# install PyJWT import jwt from fastapi.security import OAuth2PasswordBearer SECRET_KEY = os.environ['SECRET_KEY'] ALGORITHM = os.environ['ALGORITHM'] def create_access_token(*, data: dict, expires_delta: timedelta = None): to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=15) to_encode.update({'exp': expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt def decode_access_token(db, token): credentials_exception = HTTPException( status_code=HTTP_401_UNAUTHORIZED, detail='Could not validate credentials', headers={'WWW-Authenticate': 'Bearer'}, ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) email: str = payload.get('sub') if email is None: raise credentials_exception token_data = schemas.TokenData(email=email) except PyJWTError: raise credentials_exception user = crud.get_user_by_email(db, email=token_data.email) if user is None: raise credentials_exception return user

Έκδοση κουπονιών κατά την επιτυχή σύνδεση

Τώρα, θα ορίσουμε ένα τελικό σημείο σύνδεσης και θα εφαρμόσουμε τη ροή κωδικού πρόσβασης OAuth2. Αυτό το τελικό σημείο θα λάβει ένα email και έναν κωδικό πρόσβασης. Θα ελέγξουμε τα διαπιστευτήρια έναντι της βάσης δεδομένων και, κατά την επιτυχία, θα εκδώσουμε ένα διακριτικό ιστού JSON στον χρήστη.

Για να λάβουμε τα διαπιστευτήρια, θα χρησιμοποιήσουμε το OAuth2PasswordRequestForm, το οποίο αποτελεί μέρος των βοηθητικών προγραμμάτων ασφαλείας της FastAPI.

@app.post('/api/token', response_model=schemas.Token) def login_for_access_token(db: Session = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends()): '''generate access token for valid credentials''' user = authenticate_user(db, form_data.username, form_data.password) if not user: raise HTTPException( status_code=HTTP_401_UNAUTHORIZED, detail='Incorrect email or password', headers={'WWW-Authenticate': 'Bearer'}, ) access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token(data={'sub': user.email}, expires_delta=access_token_expires) return {'access_token': access_token, 'token_type': 'bearer'}

Χρήση του Dependency Injection για πρόσβαση στο DB και προστασία των τελικών σημείων

Έχουμε ρυθμίσει το τελικό σημείο σύνδεσης που παρέχει JWT σε έναν χρήστη κατά την επιτυχή σύνδεση. Ο χρήστης μπορεί να αποθηκεύσει αυτό το διακριτικό στον τοπικό χώρο αποθήκευσης και να το δείξει στο πίσω μέρος μας ως κεφαλίδα Εξουσιοδότησης. Τα τελικά σημεία που αναμένουν πρόσβαση μόνο από συνδεδεμένους χρήστες μπορούν να αποκωδικοποιήσουν το διακριτικό και να μάθουν ποιος είναι ο αιτών. Αυτό το είδος εργασίας δεν συνδέεται με ένα συγκεκριμένο τελικό σημείο, αλλά είναι κοινή λογική που χρησιμοποιείται σε όλα τα προστατευμένα τελικά σημεία. Είναι καλύτερο να ρυθμίσετε τη λογική αποκωδικοποίησης διακριτικών ως εξάρτηση που μπορεί να χρησιμοποιηθεί σε οποιονδήποτε χειριστή αιτημάτων.

Στο FastAPI-speak, οι λειτουργίες λειτουργίας διαδρομής (χειριστές αιτήσεων) θα εξαρτηθούν τότε από get_current_user. Το get_current_user η εξάρτηση πρέπει να έχει σύνδεση με τη βάση δεδομένων και να συνδέεται με το FastAPI | _ _ _ | λογική για να αποκτήσετε ένα διακριτικό. Θα επιλύσουμε αυτό το ζήτημα κάνοντας OAuth2PasswordBearer εξαρτάται από άλλες λειτουργίες. Με αυτόν τον τρόπο, μπορούμε να ορίσουμε αλυσίδες εξάρτησης, που είναι μια πολύ ισχυρή ιδέα.

get_current_user

Οι συνδεδεμένοι χρήστες μπορούν να CRUD TODOs

Πριν γράψουμε τις λειτουργίες λειτουργίας διαδρομής για TODO Δημιουργία, Ανάγνωση, Ενημέρωση, Διαγραφή (CRUD), καθορίζουμε τις ακόλουθες βοηθητικές συναρτήσεις για την εκτέλεση πραγματικών CRUD στο db.

def get_db(): '''provide db session to path operation functions''' try: db = SessionLocal() yield db finally: db.close() def get_current_user(db: Session = Depends(get_db), token: str = Depends(oauth2_scheme)): return decode_access_token(db, token) @app.get('/api/me', response_model=schemas.User) def read_logged_in_user(current_user: models.User = Depends(get_current_user)): '''return user settings for current user''' return current_user

Αυτές οι συναρτήσεις επιπέδου db θα χρησιμοποιηθούν στα ακόλουθα τελικά σημεία REST:

def create_todo(db: Session, current_user: models.User, todo_data: schemas.TODOCreate): todo = models.TODO(text=todo_data.text, completed=todo_data.completed) todo.owner = current_user db.add(todo) db.commit() db.refresh(todo) return todo def update_todo(db: Session, todo_data: schemas.TODOUpdate): todo = db.query(models.TODO).filter(models.TODO.id == id).first() todo.text = todo_data.text todo.completed = todo.completed db.commit() db.refresh(todo) return todo def delete_todo(db: Session, id: int): todo = db.query(models.TODO).filter(models.TODO.id == id).first() db.delete(todo) db.commit() def get_user_todos(db: Session, userid: int): return db.query(models.TODO).filter(models.TODO.owner_id == userid).all()

Γράψτε δοκιμές

Ας γράψουμε μερικές δοκιμές για το API TODO. Το FastAPI παρέχει ένα @app.get('/api/mytodos', response_model=List[schemas.TODO]) def get_own_todos(current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)): '''return a list of TODOs owned by current user''' todos = crud.get_user_todos(db, current_user.id) return todos @app.post('/api/todos', response_model=schemas.TODO) def add_a_todo(todo_data: schemas.TODOCreate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)): '''add a TODO''' todo = crud.create_meal(db, current_user, meal_data) return todo @app.put('/api/todos/{todo_id}', response_model=schemas.TODO) def update_a_todo(todo_id: int, todo_data: schemas.TODOUpdate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)): '''update and return TODO for given id''' todo = crud.get_todo(db, todo_id) updated_todo = crud.update_todo(db, todo_id, todo_data) return updated_todo @app.delete('/api/todos/{todo_id}') def delete_a_meal(todo_id: int, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)): '''delete TODO of given id''' crud.delete_meal(db, todo_id) return {'detail': 'TODO Deleted'} τάξη που βασίζεται στη δημοφιλή βιβλιοθήκη αιτημάτων και μπορούμε να εκτελέσουμε τις δοκιμές με το Pytest.

Για να βεβαιωθούμε ότι μόνο οι συνδεδεμένοι χρήστες μπορούν να δημιουργήσουν ένα TODO, μπορούμε να γράψουμε κάτι σαν αυτό:

TestClient

Η ακόλουθη δοκιμή ελέγχει το τελικό σημείο σύνδεσης και δημιουργεί ένα JWT εάν παρουσιάζεται με έγκυρα διαπιστευτήρια σύνδεσης.

from starlette.testclient import TestClient from .main import app client = TestClient(app) def test_unauthenticated_user_cant_create_todos(): todo=dict(text='run a mile', completed=False) response = client.post('/api/todos', data=todo) assert response.status_code == 401

Συνοψίζοντας

Έχουμε ολοκληρώσει την εφαρμογή μιας πολύ απλής εφαρμογής TODO χρησιμοποιώντας το FastAPI. Μέχρι τώρα, έχετε δει τη δύναμη των υποδείξεων τύπου να χρησιμοποιούνται σωστά στον καθορισμό του σχήματος των εισερχόμενων και εξερχόμενων δεδομένων μέσω της διεπαφής REST. Ορίζουμε τα σχήματα σε ένα μέρος και αφήνουμε στο FastAPI να εφαρμόζει επικύρωση και μετατροπή δεδομένων. Το άλλο αξιοσημείωτο χαρακτηριστικό είναι η έγχυση εξάρτησης. Χρησιμοποιήσαμε αυτήν την ιδέα για να συσκευάσουμε την κοινή λογική της απόκτησης σύνδεσης βάσης δεδομένων, αποκωδικοποίησης του JWT για λήψη του τρέχοντα συνδεδεμένου χρήστη και υλοποίησης του απλού OAuth2 με κωδικό πρόσβασης και φορέα. Είδαμε επίσης πώς μπορούν οι αλυσίδες να συνδέονται μεταξύ τους.

Μπορούμε εύκολα να εφαρμόσουμε αυτήν την ιδέα για να προσθέσουμε χαρακτηριστικά όπως η πρόσβαση βάσει ρόλου. Εκτός αυτού, γράφουμε συνοπτικό και ισχυρό κώδικα χωρίς να μάθουμε τις ιδιαιτερότητες ενός πλαισίου. Με απλά λόγια, το FastAPI είναι μια συλλογή ισχυρών εργαλείων που δεν χρειάζεται να μάθετε επειδή είναι απλώς μοντέρνα Python. Καλα να περνατε.

Κατανόηση των βασικών

Τι είναι το FastAPI;

Το FastAPI είναι ένα πλαίσιο Python και ένα σύνολο εργαλείων που επιτρέπει στους προγραμματιστές να χρησιμοποιούν μια διεπαφή REST για να καλούν λειτουργίες που χρησιμοποιούνται συνήθως για την εφαρμογή εφαρμογών. Έχει πρόσβαση μέσω ενός REST API για να καλέσει κοινά δομικά στοιχεία για μια εφαρμογή. Σε αυτό το παράδειγμα, ο συγγραφέας χρησιμοποιεί το FastAPI για τη δημιουργία λογαριασμών, τη σύνδεση και τον έλεγχο ταυτότητας.

Πώς εκτελείτε το FastAPI;

Όπως όλες οι διεπαφές REST, το FastAPI καλείται από τον κωδικό σας. Προσφέρει λειτουργίες όπως υποδείξεις τύπου για δεδομένα που έχουν μεταφερθεί, έγχυση εξάρτησης και έλεγχο ταυτότητας, ώστε να μην χρειάζεται να γράψετε τις δικές σας λειτουργίες.

Είναι το FastAPI έτοιμο για παραγωγή;

Ενώ ένα πλαίσιο ανοιχτού κώδικα, το FastAPI είναι πλήρως έτοιμο για παραγωγή, με εξαιρετική τεκμηρίωση, υποστήριξη και εύχρηστη διεπαφή. Μπορεί να χρησιμοποιηθεί για τη δημιουργία και εκτέλεση εφαρμογών που είναι τόσο γρήγορες όσο αυτές που γράφονται σε άλλες γλώσσες δέσμης ενεργειών.

ποιο από τα παρακάτω θα ήταν παράδειγμα ελέγχου ταυτότητας που βασίζεται σε διακριτικά;

Είναι η Python καλή γλώσσα για την εφαρμογή διεπαφής API;

Μπορεί να είναι εάν αυτή η διεπαφή είναι καλά καθορισμένη και ο υποκείμενος κώδικας έχει βελτιστοποιηθεί. Η τεκμηρίωση ισχυρίζεται ότι το FastAPI αποδίδει καθώς και το Node.js και το Go.

MetaDapper: Η χαρτογράφηση δεδομένων και η μετατροπή γίνονται εύκολα με τα σωστά εργαλεία

Επιστήμη Δεδομένων Και Βάσεις Δεδομένων

MetaDapper: Η χαρτογράφηση δεδομένων και η μετατροπή γίνονται εύκολα με τα σωστά εργαλεία
Η συνομιλία συνομιλίας - όταν αποτυγχάνει ένα Chatbot

Η συνομιλία συνομιλίας - όταν αποτυγχάνει ένα Chatbot

Σχεδιασμός Για Κινητά

Δημοφιλείς Αναρτήσεις
Scaling Scala: Τρόπος Dockerize χρησιμοποιώντας Kubernetes
Scaling Scala: Τρόπος Dockerize χρησιμοποιώντας Kubernetes
Μείωση του κόστους σε ένα ψηφιακό μέλλον πετρελαίου και φυσικού αερίου
Μείωση του κόστους σε ένα ψηφιακό μέλλον πετρελαίου και φυσικού αερίου
Το GWT Toolkit: Δημιουργήστε ισχυρές διεπαφές JavaScript χρησιμοποιώντας Java
Το GWT Toolkit: Δημιουργήστε ισχυρές διεπαφές JavaScript χρησιμοποιώντας Java
Επισκόπηση των δημοφιλών δημιουργών στατικών ιστότοπων
Επισκόπηση των δημοφιλών δημιουργών στατικών ιστότοπων
Γνωρίστε το Volt, ένα πολλά υποσχόμενο Ruby Framework για δυναμικές εφαρμογές
Γνωρίστε το Volt, ένα πολλά υποσχόμενο Ruby Framework για δυναμικές εφαρμογές
 
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό - Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό - Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Η Ψυχολογία του Σχεδιασμού και η Νευροεπιστήμη του Amazing UX
Η Ψυχολογία του Σχεδιασμού και η Νευροεπιστήμη του Amazing UX
APIs στα κοινωνικά δίκτυα: Η διαδικτυακή πύλη στον πραγματικό κόσμο
APIs στα κοινωνικά δίκτυα: Η διαδικτυακή πύλη στον πραγματικό κόσμο
Οδηγός επένδυσης Family Office: Μια εναλλακτική λύση στο επιχειρηματικό κεφάλαιο
Οδηγός επένδυσης Family Office: Μια εναλλακτική λύση στο επιχειρηματικό κεφάλαιο
Αρχές Σχεδιασμού - Εισαγωγή στην Οπτική Ιεραρχία
Αρχές Σχεδιασμού - Εισαγωγή στην Οπτική Ιεραρχία
Δημοφιλείς Αναρτήσεις
  • διαφορά μεταξύ ai και vi
  • πώς να εφαρμόσετε το bootstrap σε html
  • σχεδιασμός πολυμέσων έναντι γραφιστικής
  • λάβετε javascript ημερομηνία και ώρα
  • ποιοι είναι οι κοινοί περιορισμοί που τίθενται σε ένα προϊόν
  • Παράδειγμα φύλλου όρων επιχειρηματικού κεφαλαίου
Κατηγορίες
  • Επενδυτές & Χρηματοδότηση
  • Σχεδιασμός Διεπαφής Χρήστη
  • Τεχνολογία
  • Διαχείριση Έργου
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt