hey yacine, friends,

indeed the problem came partly because i haven't followed the traces of elixir
close enough: i've used backref instead of inverse for manytoone relations.

the only drawback of using inverse, is that it requires the inverse relation to
really exist, hence it can't be implied.

here comes to light an elixir extension i've made a time ago (inverse_orphans),
that would create an inverse relation on the onetomany side when it is missing.

for your interest, the plugin is attached. i'd extend this plugin to take kwargs
too.

best regards,
alex

On 09/12/2010 10:37 AM, chaouche yacine wrote:
> Yes, except I wanted the children *not* to be deleted but raise an 
> integrity_error exception instead, because what was done is that they were 
> not deleted but their FK (pointing to the parent) were set to NULL and they 
> were raising a non-null constraint related exception. 
>
>
>
>
> --- On Sun, 9/12/10, alex bodnaru <alexbodn.gro...@gmail.com> wrote:
>
>> From: alex bodnaru <alexbodn.gro...@gmail.com>
>> Subject: Re: [elixir] problem with cascade deletes
>> To: sqleli...@googlegroups.com
>> Date: Sunday, September 12, 2010, 1:21 AM
>>  hello yacine,
>>
>> elixir isn't known to reinvent sa, but please point me to
>> things you would
>> change for a pure approach.
>> part of the lower level stuff is needed to turn foreign
>> keys on in sqlite.
>>
>> in the mean time, i did a declarative example which fails
>> like elixir.
>>
>> btw. this is the same problem you have also previously
>> reported on this list.
>>
>> alex
>>
>> On 09/12/2010 09:58 AM, chaouche yacine wrote:
>>> hello alex,
>>>
>>> In your elixir program, you are mixing some imports
>> from sqlalchemy (create_engine from example) with imports
>> from elixir. Did you try an elixir only approach ?
>>> Y.Chaouche
>>>
>>>
>>>
>>> --- On Sat, 9/11/10, alex bodnaru <alexbodn.gro...@gmail.com>
>> wrote:
>>>> From: alex bodnaru <alexbodn.gro...@gmail.com>
>>>> Subject: [elixir] problem with cascade deletes
>>>> To: sqleli...@googlegroups.com
>>>> Date: Saturday, September 11, 2010, 6:31 AM
>>>>
>>>> hello friends,
>>>>
>>>> there seems to be a flaw in elixir with cascade
>> deletes.
>>>> i have a program that does it with sqlalchemy orm,
>> and a
>>>> similar one to do it
>>>> with elixir.
>>>> instead of deleting the elixir program only nulls
>> the keys
>>>> in the child.
>>>>
>>>> the programs are attached.
>>>>
>>>> best regards,
>>>> alex
>>>>
>>>> -- 
>>>> You received this message because you are
>> subscribed to the
>>>> Google Groups "SQLElixir" group.
>>>> To post to this group, send email to sqleli...@googlegroups.com.
>>>> To unsubscribe from this group, send email to
>> sqlelixir+unsubscr...@googlegroups.com.
>>>> For more options, visit this group at 
>>>> http://groups.google.com/group/sqlelixir?hl=en.
>>>>
>>>>
>>>        
>>>
>> -- 
>> You received this message because you are subscribed to the
>> Google Groups "SQLElixir" group.
>> To post to this group, send email to sqleli...@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> sqlelixir+unsubscr...@googlegroups.com.
>> For more options, visit this group at 
>> http://groups.google.com/group/sqlelixir?hl=en.
>>
>>
>
>       
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

"""
inverse_orphans Elixir Statement Generator

===============
inverse_orphans
===============

i am using an identity model module from a third party, 
having, among others, an User class. 
this model file might well be upgraded by it's supplier. 
in another model file, which imports the identity model entities, 
i have a Person class, which has a ManyToOne relationship with the User table. 
However i'd like to also know the Person which references a given User, adding 
OneToMany relationships to User, will need to be maintained everytime the 
supplier upgrades identity model. 
to implement this, i am giving an inverse name on the ManyToOne side, and 
adding an after_mapper action to create the OneToMany relationship.
"""

from elixir.statements import Statement
from elixir import OneToOne, OneToMany, ManyToOne, ManyToMany

__all__ = ['inverse_orphans']
__doc_all__ = __all__


#TODO: inherit from entity builder
class inverse_orphans_entity_builder(object):
    """An inverse_orphans Elixir Statement object"""
    
    def __init__(self, entity):
        self.entity = entity

    def before_table(self):
        '''
        if we name an inverse relationship which is not already defined on the
        target, here we create the inverse relationship on the target.
        should run this for each relationship property.
        '''
        for r in self.entity._descriptor.relationships:
            desc = r.target._descriptor
            if r.inverse_name and desc.find_relationship(r.inverse_name) is None:
                if type(r) == ManyToOne:
                    # should probably test uselist
                    if 'unique' in r.column_kwargs and r.column_kwargs['unique']:
                        invclass = OneToOne
                    else: invclass = OneToMany
                elif type(r) == ManyToMany:
                    invclass = ManyToMany
                else: invclass = None
            else: invclass = None
            if invclass:
                invprop = invclass(r.entity.__name__, inverse=r.name)
                invprop._target = r.entity
                setattr(r.target, r.inverse_name, invprop)
                invprop.attach(r.target, r.inverse_name)


inverse_orphans = Statement(inverse_orphans_entity_builder)
from elixir import *
from elixir.ext.inverse_orphans import inverse_orphans

metadata.bind = "sqlite:///:memory:"
metadata.bind.echo = False

class Movie(Entity):
    title = Field(Unicode(30))
    year = Field(Integer)
    description = Field(Text)
#    director = ManyToOne('Director', inverse='movies')
#    main_genre = ManyToOne('Genre', inverse='movies_with_main')
#    inverse_orphans()
    director = ManyToOne('Director', backref='movies')
    main_genre = ManyToOne('Genre', backref='movies_with_main')

    def __repr__(self):
        return '<Movie "%s" (%d)>' % (self.title, self.year)

class Director(Entity):
    name = Field(Unicode(60))
    #movies = OneToMany('Movie', inverse='director')

    def __repr__(self):
        return '<Director "%s">' % self.name

class Genre(Entity):
    name = Field(Unicode(15), primary_key=True)
    abbrev = Field(Unicode(15), primary_key=True)
    movies = ManyToMany('Movie', backref='genres')
    inverse_orphans()
    
    def __repr__(self):
        return '<Genre "%s">' % self.name
    
setup_all(True)
#create_all()

scifi = Genre(name="Science-Fiction", abbrev='sf')
western = Genre(name='Western', abbrev='we')

rscott = Director(name="Ridley Scott")
glucas = Director(name="George Lucas")
alien = Movie(title="Alien", year=1979, director=rscott, 
              genres=[scifi, Genre(name="Horror", abbrev='hr')],
              main_genre=scifi)
swars = Movie(title="Star Wars", year=1977, director=glucas, genres=[scifi],
              main_genre=scifi)
brunner = Movie(title="Blade Runner", year=1982, director=rscott, genres=[scifi],
                main_genre=western)

#rscott.movies.append(brunner)
#rscott.movies.append(alien)
#swars.director = glucas


print 'movies by rscott:', rscott.movies
print 'movies by glucas:', glucas.movies
print 'genres of alien:', alien.genres
print 'movies with main_genre scifi:', scifi.movies_with_main
print 'movies with main_genre western:', western.movies_with_main
print 'movies of glucas:', glucas.movies

Reply via email to