Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to make href links work properly #77

Closed
Hellisotherpeople opened this issue Jul 7, 2017 · 10 comments
Closed

Impossible to make href links work properly #77

Hellisotherpeople opened this issue Jul 7, 2017 · 10 comments

Comments

@Hellisotherpeople
Copy link

Hellisotherpeople commented Jul 7, 2017

I'm trying to make a web-page that displays a bunch of values from MongoDB, here is my code:

class LangCol(Col):             # This lets me get a webaddress into the table
    def td_format(self, content):
        parsed=urllib.parse.unquote(content)
        split = urlsplit(parsed)

        return ('<a href='+("".join(['http://',split.netloc, split.path]))+ '>'+content+'</a>')



class ItemTable(Table):
    ID = Col('IDs')
    type = Col("type")
    Job_URL = LangCol("URL")

items = mongodb.bdb.find({"OS" : "CentOS7.3"})
items2 = mongodb.bdb.find({"OS" : "RHEL7.3"})
# Get some objects
#class Item(object):
#    def __init__(self, name, description):
#        self.name = name
#        self.description = description
#items = [Item('Job1', 'Job1'),
#         Item('Job2', 'Job2'),
#         Item('Job3', 'Job3')]


app = Flask(__name__)

@app.route('/')
def index():
    table = ItemTable(items)
    table2 = ItemTable(items2)
    return table.__html__()

The relevant code is the return statement of LangCol
I've tried other returns, such as (the one I REALLY hoped would worked)

return ('<a href='+content+ '>'+content+'</a>')

Unfortunately, no matter what I do, I either get a URL that includes my hosted flask server
(like http://127.0.0.1:5000/http%3A//10.23.182.101%3A8080/job/%28CHPC%29%20Factory%20-%20CentOS%207.3%20x86_TS/57/)
or, if I unquote my weburl instead, it will truncate everything after part of my link
(like http://10.23.182.101:8080/job/(CHPC) )

This issue is very frustrating, because the closest thing to a solution I've found looks like it should, but doesn't work correctly.

https://stackoverflow.com/questions/17056408/flask-jinja2-href-not-linking-correctly

As we can see, content displays the exact URL correctly on the page. I want this exact URL to be a clickable hyperlink to the address that it prints. Unfortunately, this seems to be impossible.

screenshot from 2017-07-07 06-38-24

I'm an intern at a large tech company which probably makes your CPU, and I (along with my team) am very inexperienced with web technologies. Apologies if I'm doing something silly and don't notice it.

@plumdog
Copy link
Owner

plumdog commented Jul 8, 2017

Hi! I'm glad you're using flask table, and thanks for asking a question!

I suspect part of the problem here is that you haven't got quotes around the value for your href. Eg:

<a href="http://myurl.com/test thing">My link<a>

is different HTML to

<a href=http://myurl.com/test thing>My link<a>

as GitHub's HTML syntax highlighting nicely shows.

You get away with this if your URL doesn't have any spaces or things like < or > in, but using quotes is definitely best practice here regardless, and you definitely need them because your links have spaces in.

So I suspect that

return '<a href="' + content + '">' + content + '</a>'

will probably do it. However, you will still run into problems if your URLs ever have " in. So you can make use of the html helper in flask_table.

# with your imports:
from flask_table.html import element
...

# then in your td_format, just do:
return element('a', attrs=dict(href=content), content=content)
# to get an anchor with the given URL as the href and the displayed text

Also, the problem that you had where the flask application's URL at the start will be happen if you set the href to something that doesn't look like a full URL. Then your browser says "this isn't a proper URL, it must be relative to the current page".

This points towards a generally pretty good debugging strategy for stuff like this where it pays to check exactly what HTML you're actually producing - sometimes browsers fudge and patch up bits of HTML to try to make it work. Writing something that prints the HTML to your console, or - better still maybe - write a unit test is a great way of making sure your code is actually doing what you want it to.

@plumdog
Copy link
Owner

plumdog commented Jul 24, 2017

Hi @Rainsilves, I'm closing this issue as it's been a while without activity. But if you still have questions about the above, the please do reopen and ask.

@plumdog plumdog closed this as completed Jul 24, 2017
@Hellisotherpeople
Copy link
Author

I am sorry Plumdog, I ended up moving in a somewhat different direction with the project and will not use flask_table. I am very thankful for your long post explaining a solution!

@CheapB
Copy link

CheapB commented Nov 24, 2018

I am trying to do the same except I need the displayed value to be another fieldname from db.model - similar to using attr in LinkCol
`

class UrlCol(Col):
def td_format(self, content,attr):
return element('a', attrs=dict(href=content), content=attr)

class ProductStoreTable(Table):
store = LinkCol('Store', 'productstoreupsert', url_kwargs=dict(productid='productid',storeid='storeid'),attr='store')

Product = UrlCol('Product', 'url',attr='product')
`

I am getting "TypeError: init() got multiple values for argument 'attr'" What am I missing?

@plumdog
Copy link
Owner

plumdog commented Nov 24, 2018

@CheapB Hi!

What you're getting there is just a plain old Python error. Your UrlCol inherits from Col without overriding __init__, so it looks like:

def __init__(self, name, attr=None, ...

Your UrlCol('Product', 'url',attr='product') calls this __init__ with attr set twice.

Which of 'url' and 'product' do you want to be the attr? And what do you want the other one to be?

@CheapB
Copy link

CheapB commented Nov 24, 2018

Thanks for the fast response. What I am trying to do is '<a href="' + url+ '">' + product+ '</a>'
where both url and product are columns in my db.model.

@plumdog
Copy link
Owner

plumdog commented Nov 24, 2018

You perhaps want to use LinkCol for both of store = ... and Product = ...?

@CheapB
Copy link

CheapB commented Nov 24, 2018

You perhaps want to use LinkCol for both of store = ... and Product = ...?

It i understand it correctly LinkCol is only for urls native to the app and calls a function. I am looking to have an internet url (content of url) such as "https://www.totalwine.com/spirits/gin/monkey-47-schwarzwald-dry-gin/p/139532375?s=1501&igrules=true"

@plumdog
Copy link
Owner

plumdog commented Nov 24, 2018

@CheapB You are absolutely right.

I've added an example here: #116 that I think does what you want.

That example gives output that looks like

<table>
  <thead><tr><th>URL</th></tr></thead>
  <tbody>
    <tr><td><a href="https://google.com">Google</a></td></tr>
    <tr><td><a href="https://yahoo.com">Yahoo</a></td></tr>
  </tbody>
</table>

which becomes:

URL
Google
Yahoo

It might be worth flask_table growing a dedicated column class that does something like this.

@CheapB
Copy link

CheapB commented Nov 24, 2018

That is EXACTLY what I was going for. I am working on getting all my templates moved to Flask Table and this is a huge step in the right direction. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants