I have answer this two times in the past 2 days on IRC, which i think
is something that could be back ported or at least write some
documentation.
The issue at hand is that people want to prepopulate either test data
or default SQL rows values, to their models.
a long time ago I don't even remember how I found out that doing.
$ tg-admin shell < myscript.py
will execute any SO commands in that script, I even have some SO code
that will drop all tables, and rebuild them as necessary.
I assume this trick also works for SA. But it's a weird thing and as
far as I know it isn't documented anywhere.
either way I think this should be a tg-admin command. What do you think?
sa commands is a good place to put any setup specific command ala websetup...
If you document a method please document this one which is the
cleaner. I recommend naming the entry point bootstrap
(myapp-bootstrap). If you need more info to begin writing docs on this
method don't hesitate I'll gladly help.
Florent.
sorry I meant: yourapp.commands
I have written an example command.py that provides a "bootstrap"
function for a console script "bootstrap-<yourpkg>", which creates all
tables and optionally creates a user.
http://paste.turbogears.org/paste/10038
The example is SQLAlchemy, but I have also written a patch against
current TG 1.1 HEAD that adds support for this in commands.py in the
default quickstart template and which also works for SQLObject-based
projects.
http://trac.turbogears.org/ticket/2013
Would this be something that should be added to the default quickstart
template or will this make the code in commands.py too complex?
Chris
Ticket 2013 seems to be a duplicate of #1793. I like the technique
that Chris Z. posted in the first link listed in that ticket [1].
Basically, he recommends putting a initdb() function in model.py.
Would you be willing to consider a hybrid that puts the actual logic
in model.py, but also adds a command wrapper to call it? I think
this would be more visible to people who aren't used to looking in
their project's commands.py.
I don't have a patch, but could put one together if you'd like.
Two minor notes:
* A command-based solution won't work with AppEngine, where there is
no command line access to the DB. Of course we have a lot of other,
bigger, issues with GAE, but this will be one more.
* Why not go ahead and add the bootstrap line to the project's
startup.py instead of having it be a separate step for the user?
-Ken
[1] http://groups.google.com/group/turbogears/browse_thread/thread/d6cd864216343dca
Well, #1793 is the documentation ticket and #2013 the implementation.
Even if we commit this, we still need to document it (and ideally also
some other techniques for pre-populating the db). But I just added some
cross-references to both tickets.
> I like the technique
> that Chris Z. posted in the first link listed in that ticket [1].
> Basically, he recommends putting a initdb() function in model.py.
Yes, the 'initdb' function he suggests is basically the 'bootstrap'
function in my patch minus the option parsing stuff.
> Would you be willing to consider a hybrid that puts the actual logic
> in model.py, but also adds a command wrapper to call it?
Yes, I don't like it to have the database-related code in commands.py
either, hence my doubt about adding too much complexity to commands.py,
but I didn't know where to put it best. Honestly, I didn't think of
model.py, but now that you suggest it, it seems the obvious choice.
> I don't have a patch, but could put one together if you'd like.
Thanks, but I'll update the patch myself.
> Two minor notes:
> * A command-based solution won't work with AppEngine, where there is
> no command line access to the DB. Of course we have a lot of other,
> bigger, issues with GAE, but this will be one more.
Well, you could change the dburi, so you can execute the script
remotely. But does SQAlchemy/SQLObject even work with GAE's database
engine? If not, I don't really care about this point, since the whole
code of the patch is dependent on SA/SO.
> * Why not go ahead and add the bootstrap line to the project's
> startup.py instead of having it be a separate step for the user?
It is already there, the user just needs to uncomment it. I didn't
enable it by default, because with this script and the configuration
file, anybody who can access the script can wipe the database. So I
thought it better to have a safe default. But I'll be easily convinced
otherwise, if you have good arguments.
Chris
Ok, cool.
>
>> Two minor notes:
>> * A command-based solution won't work with AppEngine, where there is
>> no command line access to the DB. Of course we have a lot of other,
>> bigger, issues with GAE, but this will be one more.
>
> Well, you could change the dburi, so you can execute the script
> remotely. But does SQAlchemy/SQLObject even work with GAE's database
> engine? If not, I don't really care about this point, since the whole
> code of the patch is dependent on SA/SO.
>
GAE wants people to drink the BigTable kool-aide, so SA & SO won't
support it anytime soon. So I agree that you're position is
reasonable.
>> * Why not go ahead and add the bootstrap line to the project's
>> startup.py instead of having it be a separate step for the user?
>
> It is already there, the user just needs to uncomment it. I didn't
> enable it by default, because with this script and the configuration
> file, anybody who can access the script can wipe the database. So I
> thought it better to have a safe default. But I'll be easily convinced
> otherwise, if you have good arguments.
>
Well, the arguments would be (1) that they could also create & drop
the tables already via "tg-admin sql", and (2) that this is such a
common function that it should be as easy & obvious as possible.
I'll let you decide if those are good enough. For whatever it's
worth, you have my +1.
>
> Chris
thanks,
-Ken
So everything goes in commands except create_default_user which will
go in quickstart and after it something of the likes of.
#provide boostrap functions with default data to be inserted into the database,
#each of this should create an instance and take care of saving it
tg.commands.bootstrap.add(create_default_user)
then of course bootstrap will store that in a list and execute them
after create_tables.
>
> Chris
>
> >
>
Which file do you mean by "quickstart"?
Do you mean that we should add a new module "commands" to the TG core?
Do you mean that the bootstrap functions should already be executed at
the end of the "tg-admin quickstart" command?
> #provide boostrap functions with default data to be inserted into the database,
> #each of this should create an instance and take care of saving it
> tg.commands.bootstrap.add(create_default_user)
> then of course bootstrap will store that in a list and execute them
> after create_tables.
To be consistent with turbogears.view.variable_providers and
turbogears.startup.call_on_startup these should be module-globals lists,
to which the user can append with:
turbogears.commands.bootstrap_commands.append(some_callable)
Chris
Jorge Vargas schrieb:
> that is awesome. In fact it's less obscure than how websetup.py works.Which file do you mean by "quickstart"?
> I think most of it should go inside TG, and we should write docs on
> how to modify it, for that part I think the best will be to provide a
> callback by means of a callable to add more stuff to the default
> initialization.
>
> So everything goes in commands except create_default_user which will
> go in quickstart and after it something of the likes of.
Do you mean that we should add a new module "commands" to the TG core?
Do you mean that the bootstrap functions should already be executed at
the end of the "tg-admin quickstart" command?
To be consistent with turbogears.view.variable_providers and
> #provide boostrap functions with default data to be inserted into the database,
> #each of this should create an instance and take care of saving it
> tg.commands.bootstrap.add(create_default_user)
> then of course bootstrap will store that in a list and execute them
> after create_tables.
turbogears.startup.call_on_startup these should be module-globals lists,
to which the user can append with:
turbogears.commands.bootstrap_commands.append(some_callable)
Chris