Feedback needed #1351
Replies: 49 comments
|
Hi! First, thanks for this project! I started using piccolo on a new project and I really like the SQL like syntax, auto migrations, modularization and the overall simplicity without doing too much under the hood. After playing with it some hours, here are some issues I encountered :
Long life to piccolo ;) |
|
Hi Matthieu! Thanks for the feedback, it's much appreciated. With regards to your first point - good catch, that is a typo, which I will fix shortly. There is currently a limitation with auto migrations when adding a new column to an existing table, it has to be set to With the person = Person(name="Bob")
await person.save().run()
print(person.id)
>>> 1If you want to fetch the instance from the database: person = await Person.objects().where(Person.name == "Bob").first().run()
# We can then update it:
person.name = "Fred"
await person.save().run()
print(person.name)
>>> FredWith a schema like this: class Company(Table):
name = Varchar()
class Person(Table):
name = Varchar()
company = ForeignKey(Company)You can handle foreign keys as follows: company = Company(name="Widget Co")
await company.save().run()
person = Person(name="Bob", company=company.id)
await person.save().run()
print(person.company)
>>> 1You can also get the referenced table instance as follows: person = await Person.objects().where(Person.name == "Bob").first()
manager = await person.get_related('manager').run()
print(manager.name)
>>> Widget CoHopefully that helps - any other questions, feel free to ask. |
|
Thanks for your explanation about the Some other questions that comes up to me :
|
|
I'd recommend using foreign keys to other tables, rather than inheritance at this time. Inheritance should still work, but there are some tricky edge cases. Take this example - Piccolo auto migrations don't currently know that class NameMixin(Table):
name = Varchar()
class Person(NameMixin):
passThe workaround for now is to use tags. Full text search isn't currently supported, but you do have quite a bit of control over text filtering using like and ilike. await Person.objects().where(Person.name.like("%Jones%")).run()For any query features not currently supported, you can drop down to raw SQL: await Person.raw('my custom query').run() |
|
Hi Daniel! You can view the simple website at https://github.com/sinisaos/starlette-piccolo-orm. Thanks for a great project! |
|
@sinisaos Thanks for trying the project out - I'm really impressed with the app you've built. I haven't tried it with Heroku yet. When I use SSL with a version of Postgres I've installed myself it seems OK, so I need to investigate further. With the admin, did you create the user using Have you posted your project on the Encode forums? I think other people would be interested to see a complete Starlette app like this. I'll also put a link to it in the Piccolo docs. |
|
First of all thank you for liking app, I really appreciate it. Yes. I used Feel free to use anything from the github repo if you find something interesting. Thanks for putting the link in the piccolo docs (it's my honor), maybe it be useful to someone. |
|
@sinisaos I ran it locally, and it worked great for me. I just updated the requirements file slightly - have opened a pull request. The admin is a bit vague if login fails. I'll try and make it more helpful. |
|
I see that you have cleaned and updated the requirements.txt (I'm just pip freeze my whole virtualenv), but for example I need bcrypt for auth non admin users. Maybe we did not understand each other but like I previously wrote admin works perfectly locally but does't work on Heroku. |
|
@sinisaos Ah, I see! My bad. Feel free to ignore that pull request. Time for me to get a Heroku account! |
|
@dantownsend No problem and thanks for your time to investigating. Heroku is really good for free account and you can deploy 5 apps. |
|
@dantownsend When I have time I will try to deploy piccolo-admin example to Heroku. There may be a conflict between piccolo authentication and my user authentication although it doesn't make sense because picollo-admin is standalone asgi app mount to starlette app. |
|
@sinisaos Thanks. It might be that Heroku is stripping or malforming the headers, and CSRF is failing as a result. This can happen when a request gets redirected. I'll have a look. |
|
@sinisaos Thanks for that. I see the problem now - it's with the CSRF middleware. When serving under HTTPS, the CSRF middleware requires an |
|
So, here's what's happening. I wanted to test if the migrations are working correctly when I add a new class To test this, I added Todo to tables.py in addition to Task and Post as below - My tables.py now looks as below I then ran - This created home_2023_03_20t05_41_22_594033.py in piccolo_migrations folder as below However, when I now run The command fails as below Please note that I previously had home_2023_03_20t04_57_20_322489.py in my piccolo_migrations folder (prior to adding Todo model), so the piccolo_migrations listing is as follows |
|
@arunabhdas Something weird has happened. It might be worth just starting from scratch - delete the migration files, recreate the database, and try again. What's the contents of the |
|
Contents of home_2023_03_20t04_57_20_322489.py file - So it seems to me that the command is creating the migration for Task which already exists in the DB. It should be skipping over the migrations for Task since Task already exists in the DB right? |
|
@arunabhdas When Piccolo creates migrations, it doesn't look at what tables are already in the database. It looks at what's in If the tables already exist in the database because they were added manually, you can fake apply the migrations. |
|
A bit confused. What would be the correct way to start from scratch in a way that doesn't generate the default Task model? When I initially ran It generated the Task model in tables.py automatically. So how can I avoid Task model gettting generated by default? Also, what should my FastAPIWrapper block in app.py look like? Currently, it looks like Please note that I plan to add the following models - Post, Note, Idea and others incrementally and would prefer to use FastAPIWrapper, so as not to have to write each CRUD operation manually by hand? Appreciate your quick response |
|
@arunabhdas When you use In your case something weird happened with the database where it can't apply the migrations because they already exist in the database for some reason. I'd do the following if I was you:
This tutorial might be helpful. |
|
Thanks @dantownsend That works when I delete Task from tables.py and re-run the migrations for the new classes. Maybe you might want to add that to the docs somewhere (just a suggestion) The FastAPIWrapper is working as well. Thanks for your prompt help!! I'll try to go through the docs and come up with ideas for improving it a bit more. Thanks again for your quick responses and great support @dantownsend !! |
|
@dantownsend : One more question. Would you happen to have any docs / guidance or video tutorial on how to create one-to-many relationships using Piccolo? Also, any docs or tutorial on how to have JWT authentication using Piccolo / FastAPIWrapper? |
|
@arunabhdas You can do many-to-one using a ForeignKey, or many-to-many using M2M. For JWT authentication, we have some middleware / endpoints for that. I don't use JWT much though - I tend to use token auth or plain session auth. To wrap Create a discussion here if you need more info, because this thread is getting pretty long. |
|
Thanks @dantownsend Do you mind taking a quick look at my question posted on discussions if possible? |
|
Even though this request for feedback is a bit old it is still open so it seemed appropriate to add this here, otherwise let me know. Recently evaluated piccolo for use in an existing application of mine which is currently using FastApi and Tortoise Orm (among other things). I was considering trying out Litestar instead and since they currently only have examples for sqlalchemy and piccolo I looked at your library. In an earlier version I used sqlalchemy, I also revisited that and must say I really (still) dislike how their documentation is organized and that they have so many overlapping API’s, but that is maybe for another forum. So here is what I found during a quick initial conversion from Tortoise to Piccolo for an existing project, first the good and then stuff I did not like as much. Spoilers I generally really liked it, I can easily see myself using it in the future. The good
Stuff I am missing or did not like
Again thanks for the awesome work, I hope to see more of this project in the future :) |
|
@janusheide Thanks a lot for the feedback - I appreciate you taking the time to write it, and it's really helpful. For point 10, this workaround might help: class MyTable(Table):
count_ = Varchar(db_column_name="count")
await MyTable.select(MyTable.count_) |
|
Hi,
|
|
@haaavk Thanks a lot for the feedback - those are all great suggestions! |

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Piccolo is now used in production on several projects. The API is pretty stable. I'd appreciate any beta testers, who will install the library, provide feedback on the docs, and highlight any issues they have.
All reactions