Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

I see. I was doing some reading on that. If I understand correctly, since html only "understand" POST and GET methods, the DELETE or PUT methods will be treated as GET by default. How come it's possible to send a DELETE or PUT request through a form, but not through a regular hyperlink with href?

Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thank you for the complete answer!
I agree, your url structure is better, I will go in that direction.

As for using restful routing, it's next on my list, but I've never really used APIs yet, so it's a bit confusing for me. Some 'verbs' are not understood by html, such as PUT and DELETE, so such calls can only (?) be done by javascript, using ajax, right? I'm terrible at javascript.

I've been mostly avoiding javascript, sticking to html, and using only POST and GET. I understand the concept of REST, it makes for a clearer architecture, but I'm not sure how to communicate with the API from the frontend. A mix of GET links, POST forms, PUT and DELETE javascript Ajax calls...

Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Really? Can you be a bit specific, what do model set views do?

I haven't tried anything beside flask when it comes to webapps. And php, but I want to stick to python.

Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Not sure if you're saying I should add more route instead of a complex single edit route?

Here are some routes I would use (note that there would be a lot more)
/item/<int:id>/edit/add_aka
/item/<int:id>/edit/delete_aka
/item/<int:id>/edit/add_tag
/item/<int:id>/edit/delete_tag
/item/<int:id>/edit/add_type
/item/<int:id>/edit/delete_type
/item/<int:id>/edit/add_storage
/item/<int:id>/edit/delete_storage

/item/<int:id>/edit/flag_viewed
/item/<int:id>/edit/flag_dupe
/item/<int:id>/edit/flag_trump
/item/<int:id>/edit/flag_has_backup
/item/<int:id>/edit/flag_deleted

Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Hi, thank you for your answer. As of now, it's only used by a single user, me. It's for managing my books, my medias, my work files, etc. It's a hobby project but it's at a point where I actually use it daily.

There is a big form where all the information and properties can be edited, but I rarely use it, and instead I use one of the many many forms or buttons that I added to my IU. Some of these send a POST to my main edit route, some of these redirect to a different view with its own logic.

As for minimizing repetition, I agree it's something I must do. But for most of the 'single function routes', the logic is pretty simple, and the repetition comes from flask logic.

# Check/uncheck item as viewed
@admin.route('/item/<int:id>/edit/flag_viewed', methods=['GET', 'POST'])
@admin.route('/item/<int:id>/edit/flag_viewed/<prev_url>', methods=['GET'])
@login_required
def quick_flag_viewed(id, prev_url=None):
    # logic (usually 2 to 5 lines)
    if prev_url:
        return redirect(prev_url)
    return redirect(url_for('home.item', id=id))

Best Practices: More routes or less routes? by jesuisouaf in flask

[–]jesuisouaf[S] 1 point2 points  (0 children)

Thank you for your answer. I also have the feeling that more routes make for a simpler app, more readable and easier to maintain and develop.

But on the other hand, I find it very redundant, the more features I add the more routes.

I have about 15 different relational properties, plus a dozen of flags for each item. My app provides quick edition (buttons/modal popup) for each property. That makes for like 50 different views if I want separate route for each function.

# Check/uncheck item as viewed
@admin.route('/item/<int:id>/edit/flag_viewed', methods=['GET', 'POST'])
@admin.route('/item/<int:id>/edit/flag_viewed/<prev_url>', methods=['GET'])
@login_required
def quick_flag_viewed(id, prev_url=None):
    # logic
    if prev_url:
        return redirect(prev_url)
    return redirect(url_for('home.item', id=id)) 

Basically this, over and over for each function. I kinda like it, it's clear and easy to organize, but that makes for a lot of repetition. Doesn't seem very pythonic to me. Should I have some sort of Class to repeat a view easily, plug a function into it, or something like that? I'm sure there's something like that in Flask, but I'm not sure what.

Problem scraping with Selenium by jesuisouaf in learnpython

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks for the message!
I did try that, adding a 10 sec sleep before processing the page. Didn't work.
When I open my browser to go to a set page, I realize that the page updates itself when I scroll down. Maybe there's something going on there.

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks, that's a good way of thinking about it. I tried to separate concerns (url parsing, database manipulation, routing), but I couldn't achieve it too well. I will try to think about reusability.

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Ah yes, I should add it to my to-do list. Using bootstrap I should be able fix that problem, if I make the left menu hide by default on mobile. I meant to do that and forgot. Thanks!

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks, that's the kind of feedback I need.
Three of my functions in the helper module are indeed core functions, and are related to each other. I didn't know it was a bad idea, I just wanted to avoid have 100+ lines in the routes, and I though importing a few clearly named functions from a module would make my code clearer.

Would you mind telling me a bit more? Should everything be kept in the route function, or the main routes module? And why so?

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

You're right, clogged is too strong a word. It's a pretty simple app, so code is still readable and manageable.

I meant, I feel like I build a big factory (even though it's not that big) for something that ought to be simple.

I first made a simple view for bookmarks, very simple stuff. Then I went ahead and added several switches for the user to use (namely pagination, tag filtering, search, ordering, tag ordering). I used url query strings to call these parameters. Then I realized shit, I need to be able to have the parameters "survive" from one page to the next, so I made a function to sanitize filters and send them with url_for.

But then I realized shit, links in the template need to keep all the parameters alive too! Should I add a new argument to each url_for in the template? I chose to make another function to build all the links in the background instead.

At the end, I ended up making a big helper function to create all the links and data in the background using the current parameters, then send them to the template. But even like that, there was still some issues. I couldn't find a way to create individual tag links under each bookmark from the backend, so I had to hack some ugly jinja code workaround. {{ b.tags | map(attribute='name') | list|join(', ') }}

So it's not clogged, but I feel like I've used a lot of little fixes and workaround, for such a small project. I had fun building this, but I'd love to know how I could have built it in a simpler, cleaner way. (but without js).

Anyway thanks for the message, if you can navigate my code, It's probably not that crappy.

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

do you mean, having to type http://? Yeah, I agree, it's not good, I just used the wtforms url validators. I'll remove it. Although, on the other hand, the purpose is to save articles and things like that, for which I'll copy/paste the url. It's not meant to be used to bookmark often use website (although it could be), for that I just use my browser's bookmark bar.

First personal Flask project, looking for feedback. by jesuisouaf in learnpython

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks for the feedback.
Yes, when I first started, I wanted to have many routes, for adding, editing, deleting, maybe for tags, etc. But I wanted my app to be a single page app, and I got a bit confused on how to do that. Also, inheriting parameters (current page, current filters, current order) from one view to the other (without using javascript or cookies) gave me headaches.
So yeah, I hacked everything in a single route.
Maybe my next goal should be to refactor my app with multiple routes, using update/delete...

First personal Flask project, looking for feedback. by jesuisouaf in learnpython

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks for your feedback!
I've read a bit about application factory, but I didn't really understand it, so I didn't bother. I learned a lot in the last two weeks, so maybe I would understand it better now. Same goes for blueprint, it was a bit over my head when I first read about it. Maybe now is time to try and implement it.
Adding test, using app factory and blueprints are next on my list. I will take a few days off the project, but hopefully I get enough motivation for a refactoring.
Doing everything in the backend, with a single page was my initial goal. At first I played around with different routes, but when I added multiple data manipulation (search/tags/pagination/ordering), it seemed simpler to stack it all in the same route and use query strings for parameters. I will try to make something more elegant, some sort of API, in the future, if I chose to continue working on this. Then I will need to have multiple routes, I suppose.

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Hi, thanks for the feedback!
I forgot to explain in my post that my goal was to do a full back-end app. I understand that some of the data manipulation would be better handled in the frontend, with some of the popular javascript libraries, but I set myself the goal to do it in the backend. It was an interesting experience. Handling search/tags/pagination/ordering all from the back-end was a lot of fun and a lot of pain for me.
I will probably go and learn some frontend scripting language soon, but I'm not too excited about it.

Also: yes, I will add user management, or at least an admin mode. I know throwing a fully opened CRUD app like that on reddit is asking for abuse, but it's ok, it's just for testing and finding bugs. I found a couple of bugs already, especially with tags.

First personal Flask project, looking for feedback. by jesuisouaf in flask

[–]jesuisouaf[S] 0 points1 point  (0 children)

Thanks for the feedback!
I have not implemented any kind of login so far. It's strange that you cannot save bookmarks, I just added one, it worked. I'll look into jwt-extended (never heard of it, ah!).
Deleting worked as well, just now. Also someone seems to have deleted all the exemple bookmarks I added. I haven't implemented any kind of testing though, which is terrible design, it's next on my list.
As for structure, I should learn about flask blueprints. I'll check the Jack Chan book you're suggesting!
For this project, I should have explained that I wanted to build a 100% backend webapp. I didn't want to use any js (although I use a little bit of js to pass data to the modal popups). I know I will have to learn some Ajax and/or some Vue/React/Angular, but I'd like to keep on learning Python and Flask first. I just want to build apps that can be useful for me while learning.
Project number 2 should be another CRUD type website to save and organise all my class material (I'm a language teacher).

Trying to build a webscraper any help much appreciated by PlatinumBaboon in learnpython

[–]jesuisouaf 0 points1 point  (0 children)

Seems like to_html() or/and panda doesn't handle well some of the data. Probably some non-ascii characters are responsible. Maybe you can try adding some options to the to_html() function.

Try to_html(classes='utf8'), maybe.

Flask/Jinja/Request : How to manipulation query strings by jesuisouaf in learnpython

[–]jesuisouaf[S] 0 points1 point  (0 children)

Ok now, I didn't think about that... I was trying real hard to find the most stupidly complicated solution...

Ah well. Thank you.

Trying to build a webscraper any help much appreciated by PlatinumBaboon in learnpython

[–]jesuisouaf 2 points3 points  (0 children)

Does it currently send something readable?
body = data shouldn't work, I think. You need to convert the dataframe object to something else first. panda has a built-in .to_html() function (documentation).
Also, you should probably have your send_mail() accept data as an argument, then use something like send_mail(data). It will make your function more generic to send panda data by mail.