Zauważyliśmy że trzeba większa uwagę poświęcić na modelowaniu danych. Ale najlepszym mechanizmem do nauki jest interaktywna konsola
http://localhost:8080/_ah/admin/interactive
Robimy analizę przykładu 1:1. Wystarczy poniższy kod skopiować w interaktywną konsole i uruchomić.
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
# tworzymy obiekt Jacka
jack = Human(name="Jack")
# tworzymy obiekt mercedesa
mercedes = Car(brand="Mercedes")
# przypisujemy obiekt mercedesa jako pojazd Jacka
jack.drives = mercedes.put()
#wstawiamy dane do obiektu Jacka
jack.put()
# wyświetlamy dane
print >> sys.stdout, "Jack ma samochod marki "+jack.drives.brand
# Jacek ma samochód marki Mercedes
Trzeba być ostrożnym bo modelowanie klasyczne jeden do jednego wcale nie jest takie automatyczne obsługiwane przez ORM
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
jack = Human(name="Jack")
mike = Human(name="Mike")
mercedes = Car(brand="Mercedes")
mercedesid = mercedes.put()
jack.drives = mercedesid
jack.put()
mike.drives = mercedesid
mike.put()
print >> sys.stdout, "Mike ma samochod marki "+mike.drives.brand
#Mike ma samochod marki Mercedes
Ważne jest rozróżnienie odesłania do własnej klasy w kodzie: czyli model odwołuje sie do własnego modelu np: człowiek odwołuje sie do innego człowieka albo albo wynika z oczywistości, że mąż ma żonę co w praktyce oznacza że model model ma odniesienie do siebie samego.
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
# one-to-one self
bob = Human(name="Bob")
jane = Human(name="Jane")
bob.spouse = jane.put()
bob.put()
b_spouse = Human.get(bob.spouse.key())
print >> sys.stdout, "Bob's spouse is "+b_spouse.name
# Bob's spouse is Jane
Relacja wzajemności. Oto przykład
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
bob = Human(name="Bob")
jane = Human(name="Jane")
bob.spouse = jane.put()
jane.spouse = bob.put()
jane.put()
j_spouse = Human.get(jane.spouse.key())
print >> sys.stdout, "Jane's spouse is "+j_spouse.name
b_spouse = Human.get(bob.spouse.key())
print >> sys.stdout, "Bob's spouse is "+b_spouse.name
# Jane's spouse is Bob
# Bob's spouse is Jane
Problem w tym, że nikt nie sprawdza poprawności tych relacji.
Relacja jeden do wielu. W programowaniu oznacza, że dany model ma przodka bądź rodzica. Popatrzmy na poniższy kod:
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
# one-to-many using parent
bmw = Car(brand="BMW")
bmw.put()
lf = Wheel(parent=bmw,position="left_front")
lf.put()
lb = Wheel(parent=bmw,position="left_back")
lb.put()
rf = Wheel(parent=bmw,position="right_front")
rf.put()
# uh, snap, the 4th wheel is broken!
rb = Wheel(parent=bmw,position="right_back",isBroken=True)
rb.put()
# from car to wheels
bmwWheels = Wheel.all().ancestor(bmw)
print >> sys.stdout, "The BMW has the wheels: "
for wheel in bmwWheels:
print >> sys.stdout, "- "+wheel.position
# The BMW has the wheels:
# - left_front
# - right_back
# - right_front
# - left_back
# from wheel to car
brokenWheels = Wheel.gql("WHERE isBroken = :broken",
broken=True)
print >> sys.stdout, "The following cars are broken: "
for wheel in brokenWheels:
print >> sys.stdout, "- "+wheel.parent().brand
# The following cars are broken:
Co jest ciekawego w tym kodzie? Użycie GQL jako zapytania w modelu
w razie czego proponuję poczytać o tym
http://code.google.com/appengine/docs/datastore/entitiesandmodels.html
Teraz weźmiemy kolejny przykład
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
class OwnedCar(db.Model):
brand = db.StringProperty(required=True)
owner = db.ReferenceProperty(Human, required=True)
paul = Human(name = "Paul")
paul.put()
pauls_bmw = OwnedCar(brand = "BMW", owner = paul)
pauls_bmw.put()
pauls_mercedes = OwnedCar(brand="Mercedes", owner=paul)
pauls_mercedes.put()
pauls_cars = paul.ownedcar_set
print >> sys.stdout, "Paul's cars: "
for car in pauls_cars:
print >> sys.stdout, "- "+car.brand
Relacje jeden do wielu można zrealizować przy pomocy listy
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
class OwnedCar(db.Model):
brand = db.StringProperty(required=True)
owner = db.ReferenceProperty(Human, required=True)
# one-to-many using list
dodge = Car(brand="Dodge")
w1 = Wheel(position="left_front")
w2 = Wheel(position="left_back")
w3 = Wheel(position="right_front")
w4 = Wheel(position="right_back")
dodge.wheels = [w1.put(),w2.put(),w3.put(),w4.put()]
dodge.put()
dodgeWheels = Wheel.get(dodge.wheels)
print >> sys.stdout, "The Dodge has the wheels: "
for wheel in dodgeWheels:
print >> sys.stdout, "-"+wheel.position
Możemy dalej analizować przykłady relacji wielu do wielu
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
class OwnedCar(db.Model):
brand = db.StringProperty(required=True)
owner = db.ReferenceProperty(Human, required=True)
# many-to-many using list+db.Key
jack = Human(name="Jack")
bob = Human(name="Bob")
vw = Car(brand="VW")
chevy = Car(brand="Chevy")
carpool = [vw.put(),chevy.put()]
jack.owns = carpool
jack.put()
bob.owns = carpool
bob.put()
chrysler = Car(brand="Chrysler")
jack.owns.append(chrysler.put())
jack.put()
jackOwns = Car.get(jack.owns)
print >> sys.stdout, "Jack owns: "
for car in jackOwns:
print >> sys.stdout, "- "+car.brand
# Jack owns:
# - VW
# - Chevy
# - Chrysler
whoOwnsTheChevy = Human.gql("WHERE owns = :car",car=chevy)
print >> sys.stdout, "These humans own the Chevy: "
for who in whoOwnsTheChevy:
print >> sys.stdout, "- "+who.name
# These humans own the Chevy:
# - Jack
Powyższe przykłady nie zapewniały unikalności odesłań co może sprawić że dany obiekt może należeć do róznych obiektów tego samego modelu. Zanim dodamy nowy model spawdzimy czy juz istnieje.
from django.db import models
from google.appengine.ext import db
class Car(db.Model):
brand = db.StringProperty(required=True)
wheels = db.ListProperty(db.Key)
class Human(db.Model):
name = db.StringProperty(required=True)
drives = db.ReferenceProperty(reference_class=Car)
spouse = db.SelfReferenceProperty()
owns = db.ListProperty(db.Key)
class Wheel(db.Model):
isBroken = db.BooleanProperty(default=False)
position = db.StringProperty(choices=set(["left_front",
"left_back",
"right_front",
"right_back"]))
class OwnedCar(db.Model):
brand = db.StringProperty(required=True)
owner = db.ReferenceProperty(Human, required=True)
# many-to-many using list+db.Key
jack = Human(name="Jack")
bob = Human(name="Bob")
vw = Car(brand="VW")
chevy = Car(brand="Chevy")
carpool = [vw.put(),chevy.put()]
jack.owns = carpool
jack.put()
bob.owns = carpool
bob.put()
chrysler = Car(brand="Chrysler")
jack.owns.append(chrysler.put())
jack.put()
def unique(lst):
d = {}
for item in lst:
d[item] = 1
return d.keys()
jeep = Car(brand="Jeep")
jack.owns = unique(jack.owns + [jeep.put()])
jack.put()
jackOwns = Car.get(jack.owns)
print >> sys.stdout, "Jack owns: "
for car in jackOwns:
print >> sys.stdout, "- "+car.brand
# Jack owns:
# - VW
# - Chevy
# - Chrysler
whoOwnsTheChevy = Human.gql("WHERE owns = :car",car=chevy)
print >> sys.stdout, "These humans own the Chevy: "
for who in whoOwnsTheChevy:
print >> sys.stdout, "- "+who.name
# These humans own the Chevy:
# - Jack
Możliwości modelowania w GAE są o wiele większe niż to co jest opisane na tych przykładach.
1 komentarz:
Świetny artykuł, bardzo mi się przydał :) Dzięki!
Prześlij komentarz