Struktura projektu dla Google App Engine


119

Uruchomiłem aplikację w Google App Engine zaraz po jej pojawieniu się, aby pobawić się technologią i pracować nad projektem zwierzaka, o którym myślałem od dawna, ale nigdy nie udało mi się rozpocząć. Rezultatem jest BowlSK . Jednak wraz z rozwojem i dodawaniem nowych funkcji porządkowanie stało się naprawdę trudne - głównie ze względu na fakt, że jest to mój pierwszy projekt w Pythonie i nie wiedziałem o nim nic, dopóki nie zacząłem pracować.

Co ja mam:

  • Poziom główny zawiera:
    • wszystkie pliki .py (nie wiedziałem, jak sprawić, by pakiety działały)
    • wszystkie szablony .html dla stron głównych
  • Podkatalogi:
    • osobne foldery na css, images, js itp.
    • foldery zawierające szablony .html dla adresów URL typu subdirecty

Przykład:
http://www.bowlsk.com/ mapuje na HomePage (pakiet domyślny), szablon pod adresem „index.html”
http://www.bowlsk.com/games/view-series.html?series=7130 mapuje na ViewSeriesPage (ponownie pakiet domyślny), szablon w „games / view-series.html”

To jest paskudne. Jak przeprowadzić restrukturyzację? Miałem 2 pomysły:

  • Główny folder zawierający: appdef, indexes, main.py?

    • Podfolder na kod. Czy to musi być moja pierwsza paczka?
    • Podfolder na szablony. Heirarchia folderów będzie odpowiadać hierarchii pakietów
    • Indywidualne podfoldery dla css, obrazów, js itp.
  • Główny folder zawierający appdef, indeksy, main.py?

    • Podfolder na kod + szablony. W ten sposób mam klasę handlera tuż obok szablonu, ponieważ na tym etapie dodam wiele funkcji, więc modyfikacje jednej oznaczają modyfikacje drugiej. Ponownie, czy nazwa tego folderu musi być pierwszą nazwą pakietu dla moich zajęć? Chciałbym, aby folder był „src”, ale nie chcę, aby moje klasy to „src.WhthingPage”

Czy istnieje najlepsza praktyka? Mając Django 1.0 na horyzoncie, czy jest coś, co mogę teraz zrobić, aby poprawić moją zdolność do integracji z nim, gdy stanie się on oficjalnym silnikiem szablonów GAE? Zacząłbym po prostu wypróbowywać te rzeczy i zobaczyć, co wydaje się lepsze, ale obsługa refaktoryzacji pyDev nie wydaje się zbyt dobrze radzić sobie z przenoszeniem pakietów, więc prawdopodobnie nietrywialnym zadaniem będzie ponowne uruchomienie tego wszystkiego.

Odpowiedzi:


104

Najpierw proponuję przyjrzeć się „ Szybkiemu programowaniu za pomocą Python, Django i Google App Engine

GvR opisuje ogólny / standardowy układ projektu na stronie 10 swojej prezentacji slajdów .

Tutaj opublikuję nieco zmodyfikowaną wersję układu / struktury z tej strony. Sama podążam za tym wzorem. Wspomniałeś również, że masz problemy z pakietami. Po prostu upewnij się, że każdy z podfolderów ma plik __init__.py. W porządku, jeśli jest pusty.

Pliki kotłowe

  • Te prawie nie różnią się między projektami
  • app.yaml: kieruj wszystkie niestatyczne żądania do main.py
  • main.py: zainicjuj aplikację i wyślij do niej wszystkie żądania

Układ projektu

  • static / *: pliki statyczne; obsługiwane bezpośrednio przez App Engine
  • myapp / *. py: kod Pythona specyficzny dla aplikacji
    • views.py, models.py, tests.py, __init__.py i nie tylko
  • templates / *. html: templates (lub myapp / templates / *. html)

Oto kilka przykładów kodu, które również mogą pomóc:

main.py

import wsgiref.handlers

from google.appengine.ext import webapp
from myapp.views import *

application = webapp.WSGIApplication([
  ('/', IndexHandler),
  ('/foo', FooHandler)
], debug=True)

def main():
  wsgiref.handlers.CGIHandler().run(application)

myapp / views.py

import os
import datetime
import logging
import time

from google.appengine.api import urlfetch
from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from models import *

class IndexHandler(webapp.RequestHandler):
  def get(self):
    date = "foo"
    # Do some processing        
    template_values = {'data': data }
    path = os.path.join(os.path.dirname(__file__) + '/../templates/', 'main.html')
    self.response.out.write(template.render(path, template_values))

class FooHandler(webapp.RequestHandler):
  def get(self):
    #logging.debug("start of handler")

myapp / models.py

from google.appengine.ext import db

class SampleModel(db.Model):

Myślę, że ten układ świetnie sprawdza się w nowych i stosunkowo małych i średnich projektach. W przypadku większych projektów sugerowałbym podzielenie widoków i modeli, aby mieć własne podfoldery z czymś takim:

Układ projektu

  • static /: pliki statyczne; obsługiwane bezpośrednio przez App Engine
    • js / *. js
    • images / *. gif | png | jpg
    • css / *. css
  • myapp /: struktura aplikacji
    • modele / *. py
    • widoki / *. py
    • testy / *. py
    • szablony / *. html: szablony

2
Czy po osiągnięciu 20 lub 30 wyświetleń i kilku „widoków”, które obsługują posty, a następnie przekierowują, dzielisz je na osobne pliki? Być może w myapp / views / view1.py, myapp / views / view2.py? Albo że prześwituje tylko moje tło Java / C #?
Chris Marasti-Georg,

1
Edytowałem swój post, aby zająć się większymi projektami. Mam nadzieję że to pomogło. Pamiętaj, że w niektórych przypadkach będzie to wezwanie do sądu.
fuentesjr

1
Mam podobny układ, ale używam „app” zamiast „myapp”.
Alexander Kojevnikov,

Czy ktoś mógłby podać przykład roboczy dla takiego układu projektu? Nie znalazłem nic odpowiedniego.
herrherr

16

Mój zwykły układ wygląda mniej więcej tak:

  • app.yaml
  • index.yaml
  • request.py - zawiera podstawową aplikację WSGI
  • lib
    • __init__.py - wspólna funkcjonalność, w tym klasa bazowa modułu obsługi żądań
  • kontrolery - zawiera wszystkie programy obsługi. request.yaml importuje te pliki.
  • szablony
    • wszystkie szablony django używane przez kontrolery
  • Model
    • wszystkie klasy modeli magazynu danych
  • statyczny
    • pliki statyczne (css, obrazy itp.). Zmapowany do / statyczny przez app.yaml

Mogę podać przykłady tego, jak wyglądają moje app.yaml, request.py, lib / init .py i przykładowe kontrolery, jeśli nie jest to jasne.


5
Cześć Nick, zrób to! Muszę też porównać różne rozwiązania :) Dziękuję!
Hoang Pham

2
Cześć, chciałbym też zobaczyć kilka przykładów, jeśli to możliwe. Dzięki.

11

Zaimplementowałem dzisiaj standardowy szablon silnika aplikacji Google i sprawdziłem go na githubie. Jest to zgodne z wytycznymi opisanymi powyżej przez Nicka Johnsona (który wcześniej pracował dla Google).

Skorzystaj z tego linku gae-boilerplate


1
Czy możesz trochę rozwinąć tę odpowiedź? Link do github jest dobry i dobry, aby wspierać twoją odpowiedź, ale powinieneś przynajmniej spróbować go trochę wprowadzić.
Shog9,

1
README.md w katalogu głównym gae-boilerplate wyjaśnia wszystko. github.com/droot/gae-boilerplate/blob/master/README.md
Ed Randall,

7

Myślę, że pierwsza opcja jest uważana za najlepszą praktykę. I uczyń folder z kodem swoim pierwszym pakietem. Projekt Rietveld opracowany przez Guido van Rossuma to bardzo dobry model do nauki. Spójrz na to: http://code.google.com/p/rietveld

Jeśli chodzi o Django 1.0, sugeruję, abyś zaczął używać kodu trunkingowego Django zamiast GAE wbudowanego w port django. Ponownie zobacz, jak to się robi w Rietveld.


Jaki jest najlepszy powód, aby używać Django? Używam WebApp i dobrze mi to służy. Poza tym mam nadzieję, że Google wkrótce zaoferuje lepszą integrację tych dwóch. Jakie są wady używania wbudowanego portu Django?
jamtoday

3

Lubię webpy, więc zaadaptowałem go jako szablonowy framework w Google App Engine.
Moje foldery z pakietami są zwykle zorganizowane w następujący sposób:

app.yaml
application.py
index.yaml
/app
   /config
   /controllers
   /db
   /lib
   /models
   /static
        /docs
        /images
        /javascripts
        /stylesheets
   test/
   utility/
   views/

Oto przykład.


1

Nie jestem do końca na bieżąco z najnowszymi najlepszymi praktykami, i tak dalej, jeśli chodzi o układ kodu, ale kiedy robiłem moją pierwszą aplikację GAE, użyłem czegoś w drugiej opcji, w której kod i szablony są obok siebie.

Były ku temu dwa powody - po pierwsze, trzymał kod i szablon w pobliżu, a po drugie miałem układ katalogów naśladujący układ strony internetowej - co (dla mnie) było trochę łatwiejsze do zapamiętania, gdzie wszystko się znajduje.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.