toggle_params
How about adding a toggle_params
template tag? This would be useful for switch-type options (e.g. filters on views, etc). A simple implementation is:
@register.simple_tag
def toggle_params(url, **kwargs):
url = UrlHelper(url)
for param, value in kwargs.items():
value = unicode(value)
if value in url.query_dict.getlist(param):
url.del_params(**{param: value})
else:
url.overload_params(**{param: value})
return url.get_full_path()
return ''
Usage is similar to overload_params
, but if the query dict already has the param=value
, then they are removed instead.
Comments (5)
-
-
reporter Reading your code I assumed you were trying to keep the logic in
UrlHelper
, my implementation was really just meant to be conceptual and, as you've already pointed out, not well tested! I just dumped my own implementation (for a simpler use case - one parameter) and tweaked it to fit.Surely UrlHelper already has all the info it needs to track on/off state? A
toggle_params
method in UrlHelper could be (once again, untested)def toggle_params(self, **kwargs): for param, value in kwargs.items(): value = unicode(value) if value in self.query_dict.getlist(param): self.del_params(**{param: value}) else: self.overload_params(**{param: value})
However, that doesn't mean that a higher API wouldn't be better!
I have also implemented my own
{% ifhasparams %}
conditional tag, which I'll can post if you're interested. Alternatively I can work on a fork and send a pull request. That would at least allow me to write some proper tests. -
Yeah, logic for manipulating URLs, but not business logic, of how you use the URL. I hope I'm making sense. Of course, it's still possible that I don't.
So, thinking outloud, there are two scenarios that I had in mind when it comes to how you use this whole package. One is to manipulate URLs in the controller and templatetags code (in Python). The other is to manipulate URLs in string format within the templates using template tags and filters. The complete API must support all functionality in both scenarios. So,
toggle_param
should be anUrlHelper
method like the one you provided in the comment, and then you write a very simple filter or tag that exposes it.Now, while the solution you proposed works, I'm not happy with the way you need to pass kwargs to it. It raises questions like what happens if the parameter is there, but has a different value? It won't get removed. Is that what user expects? There could be cases for both complete removal of all params of the same name, and there could be cases if you just need to toggle a specific name-value pair. The API is too ambiguous, I think, and there is no mechanism to say what should happen in case of multiple parameters of the same name.
So my thought is to provide an more high-level API that would be something like the forms framework for Django. You define all the params you want, and maybe provide an interface so users can do something with the params.
Let's consider this (just tossing it out for discussion):
class QueryHelper(UrlHelper): togglable_params = {} def toggle_param(self, param): # some logic to toggle params here class MyQuery(QueryHelper): togglable_params = { 'include_all': ('allowed', 'on', 'values',) } q = MyQuery(url) q.toggle('include_all')
Since it's a subclass of
UrlHelper
, it will have all the methods of the UrlHelper, but it will also add properties that are specific to your application's business logic. With this in place, we can then proceed to provide a logical API fortoggle_params
tag/filter.What do you think? Does this make sense?
-
- changed status to resolved
-
- changed milestone to 0.0.7 COMPLETE
- Log in to comment
It's not a bad thing to have, for sure. However, my original idea was that
UrlHelper
should have all the features that you get with template tags. Now, my gut feeling tells me that adding toggle_params to UrlHelper is not such a good idea. The API would be a bit ugly without letting UrlHelper instance know about the on-off states of different params.On the other hand, letting UrlHelper know about such states, is well outside the scope of simply manipulating URLs. This calls for a higher-level API that would encapsulate various business logic patterns. A new higher-level API would open a whole new world of possibilities for working with URLs, too. Once that's done, we can talk about adding template tags that expose such functionality to the template. I'll give it some though and post ideas here.
Meanwhile, I'm on vacation until 15th, so I'm not sure about the timeline for the new design. Very likely after 15th.
As for your implementation, I'm not sure that
return url.get_full_path()
should be in the for loop. I think replacingreturn ''
withreturn url.get_full_path()
would be a better idea. If there are no arguments, it would simply return the original URL intact that way.