nobrin / macaron

A simple O/R mapper for SQLite
http://nobrin.github.com/macaron/
MIT License
31 stars 8 forks source link

Problem in auto-jointure #45

Open FrViPofm opened 3 years ago

FrViPofm commented 3 years ago

Hi all,

Using Bottle and Macaron, I try to implement a kind of sponsorship with a self-jointure on the sql table 'user'

CREATE TABLE "user" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
    "pseudo" TEXT  NOT NULL,
    "sponsor_id" INTEGER  REFERENCES user (id) NOT NULL
    );

The Macaron implementation should be :

class User (macaron.Model):
    pseudo       = macaron.CharField( max_length=32 )
    sponsor_id   = macaron.IntegerField()
    sponsor      = macaron.ManyToOne( User, fkey="sponsor_id", ref_key="id", related_name="godchildren", on_delete="SET NULL", on_update="CASCADE" )

But Traceback returns : NameError: name 'User' is not defined So, I implement User.sponsor outside the class definition :

User.sponsor      = macaron.ManyToOne( User, fkey="sponsor_id", ref_key="id", related_name="godchildren", on_delete="SET NULL", on_update="CASCADE" )

It works well when I ask : User.get(id).sponsor

But not on : User.get(id).godchildren where I get the Exception : AttributeError("'User' object has no attribute 'godchildren'")

Is it the right way to implement such a jointure ? Is it a bug ? A limitation ?

Thanks in advance.

Have a good year.

nobrin commented 3 years ago

@FrViPofm Sorry, but my response is too late.

It may be fixed with latest commit. You can define self-relationships by using the model name.

I verify the behavior.

CREATE TABLE "user" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
    "pseudo" TEXT  NOT NULL,
    "sponsor_id" INTEGER  REFERENCES user (id) NOT NULL
    );
import macaron

class User(macaron.Model):
    pseudo = macaron.CharField(max_length=32)
    sponsor_id = macaron.IntegerField(null=True)
    sponsor = macaron.ManyToOne("User", fkey="sponsor_id", ref_key="id", related_name="godchildren", on_delete="SET NULL", on_update="CASCADE")

macaron.macaronage(dbfile="test.db")
sponsor = User.create(pseudo="Sponsor", sponsor_id=1)
user1 = User.create(pseudo="User1", sponsor=sponsor)
macaron.bake()
user1 = User.get(pseudo="User1")
print(user1)
print(user1.sponsor.godchildren)

Result,

<User object 2>
[<User object 1>, <User object 2>]
FrViPofm commented 3 years ago

Many thanks! I'll try in few days.