I think I may have all the definitions:

class Contact(Base):
    __tablename__ = "civicrm_contact"
    id = Column(Integer, primary_key=True)
    last_name = Column(String(20), nullable=False)
    first_name = Column(String(20), nullable=False)
class Contribution(Base):
    __tablename__ = "civicrm_contribution"
    id = Column(Integer, primary_key=True)
    contact_id = Column(Integer, nullable=False)
    receive_date = Column(DateTime,nullable=False)
    total_amount = Column(DECIMAL(precision=20,scale=2), nullable=False)
class Address(Base):
    __tablename__ = "civicrm_address"
    id = Column(Integer, primary_key=True)
    contact_id = Column(Integer, nullable=False)
    street_address = Column(String(96), nullable=False)
    city = Column(String(64), nullable=False)
    postalcode = Column(String(64), nullable=False)
    country_id = Column(Integer, nullable=False)
class Country(Base):
    __tablename__ = "civicrm_country"
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
class State(Base):
    __tablename__ = "civicrm_state_province"
    id = Column(Integer, primary_key=True)
    name = Column(String(64), nullable=False)
    abbreviation = Column(String(4), nullable=False)
    country_id = Column(Integer, nullable=False)
class Entity_Tag(Base):
    __tablename__ = "civicrm_entity_tag"
    id = Column(Integer, primary_key=True)
    entity_id = Column(Integer, nullable=False)
    tag_id = Column(Integer, nullable=False)

Now, how to create the equivalent SQL query?  I presume that this front-end 
overhead will pay back when I write more interesting scripts that use data 
from Civicrm. If this works then I can map the remainder of the (many) 
tables.

On Tuesday, August 20, 2019 at 5:15:36 PM UTC-4, Ira Fuchs wrote:
>
> OK, fixed the case:
>
> class Contact(Base):
>     __tablename__ = "civicrm_contact"
>     id = Column(Integer, primary_key=True)
>     last_name = Column(String(20), nullable=False)
>     first_name = Column(String(20), nullable=False)
> class Contribution(Base):
>     __tablename__ = "civicrm_contribution"
>     id = Column(Integer, primary_key=True)
>     contact_id = Column(Integer, nullable=False)
>     receive_date = Column(DateTime,nullable=False)
>     total_amount = Column(DECIMAL(precision=20,scale=2), nullable=False)
>
> On Tuesday, August 20, 2019 at 3:59:55 PM UTC-4, Ira Fuchs wrote:
>>
>> OK, I made some progress (see screenshot).  I don't need the full model 
>> to be represented as I will not need many of the columns in each of the 
>> tables. If I could flesh this out enough so that I can do the query posted 
>> above I can probably use that as a template to move forward.
>>
>> On Monday, August 19, 2019 at 7:11:59 AM UTC-4, Peter Schutt wrote:
>>>
>>> Cool, how about we walk through creating a model for your schema as an 
>>> example. As we go I can point you to the relevant sections of the 
>>> tutorials/docs as they are great and will explain the details much better 
>>> than I can, and I'll try to address any questions you have along the way.
>>>
>>> The first thing you need is your Base class, all of your ORM models will 
>>> inherit from this:
>>>
>>> from sqlalchemy.ext.declarative import declarative_base
>>>
>>> Base = declarative_base()
>>>
>>>
>>> Your models need to inherit from Base, need a __tablename__ class 
>>> attribute and at least a primary key column. For example, a class to 
>>> represent your "db_contact" table might look like this:
>>>
>>> from sqlalchemy import Column, Integer, String
>>>
>>> class Contact(Base):
>>>
>>>     __tablename__ = "db_contact"
>>>
>>>     id = Column(Integer, primary_key=True)
>>>     last_name = Column(String(20), nullable=False)
>>>     first_name = Column(String(20), nullable=False)
>>>
>>> Some things to note this far along:
>>>
>>>    - In this example, the name of the Column in the database is 
>>>    inferred from the name of the class attribute that the Column is 
>>> assigned 
>>>    to.
>>>    - Column constructors take arguments that define specifics of how 
>>>    the column is defined in the database. E.g. `primary_key=True`, 
>>>    `nullable=False`. By declaring a single integer column as primary key, 
>>> it 
>>>    will automatically be specified as autoincrement in the schema, as well 
>>> as 
>>>    the primary key. Setting nullable=False on other columns declares that a 
>>>    NOT NULL constraint should be set on those columns.
>>>    - As you are using MySQL, String types (which represent VARCHAR type 
>>>    in the database) require a length. If you were creating models for other 
>>>    backends such as SQLite or postgres, then that isn't required.
>>>
>>> Nothing that I've covered here isn't covered in the early stages of the ORM 
>>> Tutorial 
>>> <https://docs.sqlalchemy.org/en/13/orm/tutorial.html#declare-a-mapping>. 
>>> Also, you can read the Column API 
>>> <https://docs.sqlalchemy.org/en/13/core/metadata.html#sqlalchemy.schema.Column>
>>>  to 
>>> get a feel for the arguments that you can pass to Column in order to define 
>>> your schema.
>>>
>>> One more important element is the Foreign Key. I'll use your 
>>> "db_entity_tag" table to give you an example of that:
>>>
>>> from sqlalchemy import ForeignKey
>>>
>>> class EntityTag(Base):
>>>
>>>     __tablename__ = "db_entity_tag"
>>>
>>>     id = Column(Integer, primary_key=True)
>>>     entity_id = Column(
>>>         Integer, 
>>>         ForeignKey('db_contact.id', ondelete="CASCADE"), 
>>>         nullable=False,
>>>     )
>>>
>>> Pass the name of the related column to the ForeignKey object (note that 
>>> this isn't "Class.attributename", it is "tablename.columnname") and pass 
>>> the ForeignKey object as a positional argument to the Column constructor 
>>> _after_ the column type argument. ForeignKey api is documented here 
>>> <https://docs.sqlalchemy.org/en/13/core/constraints.html#sqlalchemy.schema.ForeignKey>
>>>  and 
>>> touched on in the orm tutorial here 
>>> <https://docs.sqlalchemy.org/en/13/orm/tutorial.html#building-a-relationship>
>>> .
>>>
>>> Have a go at filling in the columns that I've missed in those models 
>>> above and defining the rest of the tables in your schema and once you get 
>>> that done we can move on. Happy to try to answer any questions you might 
>>> have along the way.
>>>
>>>
>>> On Monday, 19 August 2019 12:36:21 UTC+10, Ira Fuchs wrote:
>>>>
>>>> Thanks for your reply and offer to help. I am able to create an Engine 
>>>> and connect to the MySQL db. I can execute simple sql queries although I 
>>>> wasn't able to get the query I posted to work due to a syntax error 
>>>> (probably having to do with the quotes). I have not mapped any tables to 
>>>> classes.
>>>>
>>>> On Sunday, August 18, 2019 at 8:54:57 PM UTC-4, Peter Schutt wrote:
>>>>>
>>>>> Hi Ira, I'd be happy to help you find your feet with the SQLAlchemy 
>>>>> ORM.
>>>>>
>>>>> In general when creating an application that uses the SQLAlchemy ORM, 
>>>>> you would start with an Engine (for connecting to the db), a declarative 
>>>>> base class (maps db table to python class) and a Session instance (for 
>>>>> using a connection to issue queries). Do you have any familiarity with 
>>>>> those concepts?
>>>>>
>>>>>
>>>>> On Monday, 19 August 2019 02:34:05 UTC+10, Ira Fuchs wrote:
>>>>>>
>>>>>> I am new to sqlalchemy and I would like to begin using it to create 
>>>>>> scripts with some sql queries that I have been using but need to change 
>>>>>> from time to time. It would help a lot if someone could translate one of 
>>>>>> these queries to python sqlalchemy using an ORM (not simply executing 
>>>>>> the 
>>>>>> query as is) so that I could use this as a template for other queries, 
>>>>>> or 
>>>>>> at least learn from it.
>>>>>>
>>>>>> One of my queries looks like this:
>>>>>>
>>>>>> SELECT DISTINCT last_name, first_name, street_address, city, a.name, 
>>>>>> postal_code, f.name as country FROM db_contact c, db_entity_tag d , 
>>>>>> db_address e, db_state_province a, db_country f WHERE c.id = 
>>>>>> d.entity_id and tag_id = 6 and c.id = e.contact_id AND 
>>>>>> state_province_id = a.id  and e.country_id = f.id and  display_name 
>>>>>> not in ( SELECT display_name FROM db_contribution, db_contact c, 
>>>>>> db_entity_tag d WHERE receive_date > '2005-07-01' and contact_id = 
>>>>>> c.id and c.id = entity_id and tag_id = 6 )
>>>>>>
>>>>>> Thanks for any help.
>>>>>>
>>>>>>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/e442aa66-55ee-4f4f-949d-df3d8145c4c9%40googlegroups.com.

Reply via email to