Passing variables from Jinja to database - python

I'm trying to figure out a way to pass a dynamic URL with webpy that will render a Jinja template with information about the information that was passed. Specifically I have a item database that should be able to take whatever item ID is in the URL and render a template with further information about that item.
To simply the problem, I've hardcoded the value 1043374545 for demonstrations purposes, but I'm hoping that this line will be come dynamic once this initial problem is solved.
urls = ('/1043374545', 'view_item')
class view_item:
def GET(self, itemID):
item_info = sqlitedb.detailInfo(request)
return render_template('view_item.html', item = item_info)
As of now I isolated the issue to having to do with something related to passing the value 1043374545 into the view_item function. Any thoughts on how I can pass a dynamic number within a URL into view_item?

simply put:
urls = (('/([0-9]*)', 'view_item'),)
[0-9]* will tell webpy to only accept numbers after the "/".
Then you can use that value in your GET function, it will be under itemID as you specified in your GET parameter.
class view_item:
def GET(self, itemID):
item_info = sqlitedb.detailInfo(itemID)
return render_template('view_item.html', item = item_info)
check this link for more details:
http://webpy.org/cookbook/url_handling

Related

How to get the url before render it

I would like to build a system which need to detect which urls the user opened and count the opened times.
There are several different urls shared the same WaitView(TemplateView), so I want to count the numbers for each url when user click it.
I added a dic in the urls and hope it can return the correct url the user opened to the context1 in Waitview.
But I couldn't find a correct way to obtain the correct url, (I tried to use HttpRequest.get_full_path() but it continues error.
"TypeError: get_full_path() missing 1 required positional argument: 'self'")
Moreover, I hope the WaitView could received the correct url and count times and then show the times on the opened page.(need the correct url before render it)
So I wander if you have some suggestions on this.
Really appreciate for your kind help.
# urls.py
'''
urlpatterns = [
re_path('get_times/.+', WaitView.as_view(), {"url": ***CORRECT_URL***})
]
'''
# views.py
'''
class WaitView(TemplateView):
template_name = 'wait.html'
def get_context_data(self, **kwargs):
context1 = kwargs.items()
print(context1)
'''
The request object is stored in the .request attribute of a View. You thus can access it with self.request in the view methods, and you thus can obtain the url with:
class WaitView(TemplateView):
template_name = 'wait.html'
def get_context_data(self, **kwargs):
print(self.request.get_full_path())
return super().get_context_data(**kwargs)
You can use the .build_absolute_uri() method [Django-doc] to generate the absolute URI (so including the protocol, hostname, etc.).
so there is no need to add a parameter to the context.

How to count occurences in list with template filters in django and pass them to the template

I have a django app in which I am counting the clicked urls. I am saving the clicked urls in a list in my view. Now I want to iterate through the list and count each occurence (of the urls). Then I want to show each url with the counted number in the template. What I am doing so far looks like this:
My view:
class AnalyticsIndexView(StaffRequiredMixin, ListView):
template_name = 'analytics_list.html'
model = UrlTime
def get_context_data(self, **kwargs):
context = super(AnalyticsIndexView, self).get_context_data(**kwargs)
context['url_views_list'] = UrlTime.objects.all()
context['total_views'] = UrlTime.objects.all().count
context['home_view'] = UrlTime.objects.filter(associated_url='/').count()
context['job_list'] = UrlTime.objects.filter(associated_url='/jobs/').count()
context['job_detail'] = UrlTime.objects.filter(associated_url='/jobs/{How to pass id??}').count()
context['job_'] = UrlTime.objects.filter(associated_url='/jobs/{???id?????}').count()
return context
Now that works. But I don't want to hardcode the links obviously, also because I don't know which urls will be in it. (that handles my custom middleware). I would like to capture each url in the list, count it, and show link and linkcount in the template. I already tried with Collections but it didn't work as I wanted it. Also with the harcoding I don't know how to do that with links that have a dynamic id....
Anyone has any suggestions? Help is very much appreciated. Thanks!
You need to do a GroupBy and Count aggregation. Try overriding get_query_set method with the following query:
def get_queryset():
return UrlTime.objects.values('associated_url').annotate(
url_count=Count('associated_url')
)

Django template tag to insert or replace URL parameter

Is anyone aware of a Django template tag that takes the current path and query string and inserts or replaces a query string value?
e.g. given a request to /some/custom/path?q=how+now+brown+cow&page=3&filter=person
The call {% urlparam 'page' 4 %} would generate /some/custom/path?q=how+now+brown+cow&page=4&filter=person.
This wouldn't be too difficult to write from scratch, but as this seems like a very common task, I would expect a tag like this to be built-in. However, after reading through the docs and googling, I can't seem to find anyone's who's publicized such a tag.
Since I haven't used these tools by my own, I'll just refer you:
django-url-tools has url_params template tag that seems to do what you want
django-more-template-tags-and-filters has some helper tags for manipulating urls and parameters
FYI, I've personally used jsurl library for this kind of url manipulations in javascript.
Hope that helps.
Here's how I did it on a Django 1.3 project. Like you I expected to find this built in, but ended up coding it in the view:
def remove_url_param(url, params):
if not isinstance(params, list):
params = [params,]
if isinstance(url, unicode):
# urlencode doesn't like unicode
url = url.encode('utf8')
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url)
param_dict = parse_qs(query)
for p in params:
try:
del(param_dict[p])
except KeyError:
pass
query = urllib.urlencode(param_dict, True)
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
Then I used this to create base URLs:
page_url_unordered = putils.remove_url_param( request.get_full_path(), ['order', 'ajax'] )
Then in the template:
Price
Size
I want to render a series of pagination links on a search page. The
URL contains several query parameters (like in my example). The
pagination code that renders the pagination links shouldn't have to be
explicitly given all these parameters. Django's admin seems to have
this behavior everywhere.
This is enabled by adding django.core.context_processors.request to TEMPLATE_CONTEXT_PROCESSORS (its not enabled by default). This will add a request variable to your templates, which is the HttpRequest object.
From there, you can use {{ request.get_full_path }} to get the current URL with the complete query string, and then append your custom query to it.
If your page is /search?q=foo+bar, and you want a new link to be /search?q=foo+bar&page=4, page 4.

Filtering QuerySet based on captured URL parameters in Django?

I'm making a generic template that will be displaying a list of objects from a queryset:
{% for o in objects %}
{{ o.name }}
{% endfor %}
I want to be able to use the template in multiple situations, where different sorts of filtering and ordering need to be done. I have created a view function for this:
def display_objects(request, filters, orders, template_name):
objects = Object.objects.all()
for filter in filters:
objects = objects.filter(('%s__%s' % (filter['field'], filter['relationship']), filter['value']))
for order in orders:
objects = objects.order_by('-' if 'descending' in order else '' + order['field'])
# render objects to template with context
pass
I'm not sure if what I have done so far will even work, but I've run into an issue. I don't know if it's feasible to filter the query set by a parameter captured in the URL with my current function.
For example, if I wanted to display objects pertaining to a certain user I would do something like:
(r'^user/(?P<account_username>[^/]+)/$', display_objects, dict(filters=[{'field':'account__username','relationship':'iexact','value':account_username}], orders=[{'field':'foobar'}], template_name='user.html'))
Obviously, account_username isn't a defined field until the URL is parsed and dispatched to the display_objects function. It would be easy enough to make a view function that takes an account_username parameter, but I want to be able to use the function for displaying other object query sets that will be filtered with different captured parameters.
Is there some way I can pass captured URL parameters to a view function to dynamically filter or order a query set to be displayed?
Here's one way you can do this:
in urls.py:
(r'^user/(?P<account_username>[^/]+)/$', display_objects, dict(filters=[{'field':'account__username','relationship':'iexact'}], orders=[{'field':'foobar'}], template_name='user.html'))
And then in views.py:
def display_objects(request, filters, orders, template_name, **kwargs):
objects = Object.objects.all()
for filter in filters:
objects = objects.filter(('%s__%s' % (filter['field'], filter['relationship']), kwargs.get(filter['field'])))
for order in orders:
objects = objects.order_by('-' if 'descending' in order else '' + order['field'])
# render objects to template with context
pass
Although honestly I'm not sure if this is a good way of doing things...
You can't pass a string directly to the filter method. You need to translate it into kwargs.
query_string = '%s__%s' % (filter['field'], filter['relationship'])
objects = objects.filter(**{query_string: filter['value']}))

Django middleware process_template_response method not being called

I have the following middleware class:
class CommonContextMiddleware:
def process_template_response(self, request, response):
# Get the context and top videos
context = response.context_data
...
# Add most_recent and most_viewed to the context...
context['most_recent'] = top_videos['most_recent'][:3]
context['most_viewed'] = top_videos['most_viewed'][:3]
# ...then continue rendering
return response
However, no matter what I put in the function, it's never being called. I presumed that this method would be called for every single template response generated, am I wrong?
Thanks in advance.
I assume when you're talking about "template response", you are actually returning a TemplateResponse from your Django view?
This isn't really the best place for this sort of thing. If you just want to add variables into every template context, the best place to do it is in a context processor.

Categories