SORU
13 AĞUSTOS 2013, Salı


SQLAlchemy neler yapabileceğini ve Django ORM örnek olamaz

Son zamanlarda bir çok araştırma Django geçerli bir uygulama tutmak SQLAlchemy karşı olan Piramit kullanarak yapıyorum. Tek başına bütün bir tartışma konusudur, ama bunu tartışmak için gelmedim.

Bilmek istiyorum ne, neden SQLAlchemy evrensel Django ORM daha iyi olarak kabul edilir. Her değilse hemen hemen her ikisi arasında buldum karşılaştırma SQLAlchemy yanadır. SQLAlchemy yapısı çok daha sorunsuz SQL çevirmek sağlar performans olarak büyük bir şey sanırım.

Ama, aynı zamanda daha zor görevlerle, Django ORM kullanmak neredeyse imkansız olduğunu duydum. Bu nasıl dışarı kapsam istiyorum. Nedenlerinden biri, Django ORM artık sizin ihtiyaçlarınıza uygun zaman olduğunu SQLAlchemy geçmek için okuyorum.

, SQLAlchemy yapabilir, ama Django ORM olabilir, ek ham SQL ekleme olmadan Kısacası, birileri bir sorgu (SQL sözdizimi gerçek olmak zorunda değil) sağlayabilir?

Güncelleme:

Ben bu soruyu ilk sorana oldukça ilgisini çekti izliyorum, ekstra benim iki kuruş atmak istiyorum.

Sonunda SQLAlchemy kullanarak bitirdik ve karardan mutlu olduğumu söylemeliyim.

Bu soru, şimdiye kadar, Django ORM çoğaltmak mümkün oldum değil SQLAlchemy ek bir özellik sağlamak için tekrar düşünüyordum. Eğer birisi bunu yapmak için nasıl bir örnek verebilir eğer seve seve sözlerimi yerim.

Diyelim ki kullanmak istediğiniz bazı postgresql gibi işlev benzerliği () sağlayan bir bulanık karşılaştırma (bkz: Finding similar strings with postgresql quickly - tl;dr giriş iki dize getir geri bir yüzde benzerlik).

Bu Django ORM kullanarak nasıl arama yapılır ve hiçbir şey onların belgelerden belli olduğu gibi ham sql kullanarak dışında bulduk: https://docs.djangoproject.com/en/dev/topics/db/sql/.

yani

Model.objects.raw('SELECT * FROM app_model ORDER BY \
similarity(name, %s) DESC;', [input_name])

Burada anlatıldığı gibi SQLalchemy, ancak işlev (),: http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.func

from sqlalchemy import desc, func
session.query(Model).order_by(func.similarity(Model.name, input_name))

Bu tanımladığınız sql/postgresql/etc herhangi bir fonksiyon için sql oluşturmak ve ham sql gerektirmez sağlar.

CEVAP
13 AĞUSTOS 2013, Salı


Bu yapıcı olmayan olmak için tehlikeli bir şekilde bulunur, ama ısırırım.

Diyelim ki, farklı hesaplar bir dizi için belirli öğeleri stoklar korumak gerekir sanırım. DDL şöyle:

CREATE TABLE account (
    id serial PRIMARY KEY,
    ...
);

CREATE TABLE item (
    id serial PRIMARY KEY,
    name text NOT NULL,
    ...
);

CREATE TABLE inventory (
    account_id integer NOT NULL REFERENCES account(id),
    item_id integer NOT NULL REFERENCES item(id),
    amount integer NOT NULL DEFAULT 0 CHECK (amount >= 0),
    PRIMARY KEY (account_id, item_id)
);

Öncelikle Django ORM bileşik birincil anahtarlar ile çalışamaz. Evet, her zaman yedek anahtar ve benzersiz bir kısıtlaması ekleyebilirsiniz, ama bir daha fazla sütun ve gerçekten ihtiyacınız birden fazla dizin. Sütunlar küçük bir sayı ile büyük bir tablo için bu fark boyut ve performans yükü eklemek istiyorum. Ayrıca, ORMs genellikle kimlik eşleme bir şey birincil anahtar kullanarak sorun var.

Şimdi, izin verilen hesap stok miktarını eşliğinde her öğe sorgu, ama aynı zamanda tüm öğeleri 0 miktar ayarla ile yok orada eklemek istiyoruz diyelim. Ve o miktara göre azalan sırada bu sıralama. SQL ilgili:

SELECT item.id, item.name, ..., coalesce(inventory.amount, 0) AS amount
    FROM item LEFT OUTER JOIN inventory
        ON item.id = inventory.item_id AND inventory.team_id = ?
    ORDER BY amount DESC;

Dış özel durumu katılın Django ORM ifade etmek için bir yol yoktur. Evet, iki basit ayrı sorgular ve gerçekleştirmek katılmak Python döngü içinde elle yapabilirsiniz. Ve performansı muhtemelen daha kötüye gitmezbu özel durumda. Ama bu sonuçlar, çünkü konumuz bu değilhersorgu uygulama yan SELECTs sadece temel kullanarak yeniden olabilir.

SQLAlchemy İle:

class Account(Base):
    __tablename__ = 'account'
    id = Column(Integer, primary_key=True)
    ...

class Item(Base):
    __tablename__ = 'item'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    ...

class Inventory(Base):
    __tablename__ = 'inventory'
    account_id = Column(Integer, ForeignKey('account.id'), primary_key=True,
            nullable=False)
    account = relationship(Account)
    item_id = Column(Integer, ForeignKey('item.id'), primary_key=True,
            nullable=False)
    item = relationship(Item)
    amount = Column(Integer, CheckConstraint('amount >= 0'), nullable=False,
            default=0)

account = session.query(Account).get(some_id)
result = (session
    .query(Item, func.coalesce(Inventory.amount, 0).label('amount'))
    .outerjoin(Inventory,
        and_(Item.id==Inventory.item_id, Inventory.account==account))
    .order_by(desc('amount'))
    .all())

Bir yan not olarak, SQLAlchemy sözlük tabanlı koleksiyonları çok kolay hale getirir. Inventory ile ilişkisi ne olarak görünmesini sağlarsınız Account modeli için aşağıdaki kodu ilavesi ile: miktarı için öğeleri eşleme.

items = relationship('Inventory',
    collection_class=attribute_mapped_collection('item_id'))
inventory = association_proxy('items', 'amount',
    creator=lambda k, v: Inventory(item_id=k, amount=v))

Bu gibi kod yazmak sağlar:

account.inventory[item_id]  = added_value

bu şeffaf ekler veya günceller inventory tabloda girdiler.

Kompleks birleşimler, alt sorgular, pencere toplamları — Django ORM böyle bir şey ile başa çıkmak için ham SQL düşen geri başarısız olur.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • backyardjay

    backyardjay

    8 ŞUBAT 2009
  • Kanaal van Dj0fifty

    Kanaal van D

    28 EKİM 2011
  • Vintendo Power

    Vintendo Pow

    2 Ocak 2007