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.
Related
i have a table which include all users and two columns at the end (Edit,Delete) and i just enabled the delete column, the issue is when i click on the delete icon the record will be deleted but the url will stuck on the delete function even if i used return render(request,'getUsersInfo.html') which is get all records function
Model Name: Users
urls:
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns = [
path('signup.html',views.signup,name=''),
path('getUsersInfo.html',views.getAllUsers,name=''),
url(r'^deleteUser/(?P<fullname>\D+)/$',views.deleteUser, name='deleteUser'),
# this is how to call a function without parameters url(r'^deleteUser/$',views.deleteUser, name='deleteUser'),
in the same view i have 3 functions (singup "add user", getAllUsers "get all the records to the table,deleteUser)
views:
def getAllUsers(request):
print("getAllUsers")
thesearchValue = ''
if 'SearchValue' in request.GET:
thesearchValue = request.GET['SearchValue']
print(request.GET['SearchValue'])
allUsers = User.objects.filter(fullname__icontains=thesearchValue)#all()
# return render(request,'getUsersInfo.html',{'allUsers':allUsers})
return render(request,'getUsersInfo.html',{'allUsers':allUsers})
else:
print("Empty")
allUsers = User.objects.all()
return render(request,'getUsersInfo.html',{'allUsers':allUsers})
def deleteUser(request,fullname):
print('delete the user')
todelete = User.objects.filter(fullname=fullname)
todelete.delete()
return render(request,'getUsersInfo.html')
Notice that i used return render(request,'getUsersInfo.html') which should call getAllUsers(request): but the url stuck on http://127.0.0.1:8000/deleteUser/John/
Rendering the same template as another view does not mean that you will somehow call other views. A template is nothing more than a tool to specify how to convert context data to a string, that is passed as HTTP response. You can use the same template in multiple views, and a view can render multiple templates.
You can make use of redirect(..) [Django-doc] to return a HTTP redirect response (302):
from django.shortcuts import redirect
def deleteUser(request,fullname):
print('delete the user')
todelete = User.objects.filter(fullname=fullname)
todelete.delete()
return redirect(getAllUsers)
Note: A GET request is not supposed to have side-effects, hence removing
objects when a user makes a GET request, is not compliant with the HTTP
standard. Therefore it might be better to remove a User with a POST request.
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')
)
I have urls that take a parameter called board_slug. Before getting the template the view will replace the slug if its name is wrong and redirect it. I have already made the code for fixing the slug but do not know how insert the fixed board_slug into the new url. This code is run across multiple views so it has to work with all the following kinds urls:
url(r'^boards/(?P<board_slug>[^/]+)/$', views.BoardView.as_view(), name='board'),
url(r'^/front-thing/boards/(?P<board_slug>[^/]+)/new/$', views.BoardView.as_view(), name='new_board'),
url(r'^boards/(?P<board_slug>[^/]+)/etc...$', views.BoardView.as_view(), name='anything_with_board'),
class BoardView(View):
template_name = 'forums/board.html'
def get(self, request, board_slug):
if wrong:
url = get_django_url
url.board_slug = 'new-slug'
return redirect(url)
else:
return template
I've the following URL that i created:
urls.py
url(r'^authors', GenericView.as_view(model=Author, context_object_name='authors_list',
success_url=reverse_lazy('author_link'),
template_name='app/authors.html'), name='author_url_name'),
And i want to have access to the URL's name on the view, passed in a variable. In this case, 'author_url_name'.
The view function where i need it, is the following:
views.py
def get_context_data(self, **kwargs):
context = super(AuthorClass, self).get_context_data(**kwargs)
context['action'] = reverse_lazy('author_url_name')
return context
This works, but i want to replace the 'author_url_name' for some method that gives me exactly that.
Thanks for your time!!
https://stackoverflow.com/a/17614086/183948 has your answer for you.
As of Django 1.5, this can be accessed from the request object
current_url = request.resolver_match.url_name
https://docs.djangoproject.com/en/1.5/ref/request-response/#django.http.HttpRequest.resolver_matc
I have written what I hope to be a re-usable Django app, but I have a bit of a conundrum on how to make the post form handling flexible. The simplified version of my view code looks like:
def do_form(request, entity_id, template_name, success_url):
form = MyForm(request.POST or None)
if request.method =='POST':
if form.is_valid():
#do some business logic
return HttpResponseRedirect(finished_url)
return render_to_response(template_name,
{'form': form},
context_instance=RequestContext(request))
I have followed the advice in James Bennets book "Practical Django Projects" and so you can now configure the template and the success url in the url conf, so for example my url conf could look like this:
urlpatterns = patterns('myapp.views',
url(r'^do/(?P<entity_id>\d+)/$',
view = 'do_form',
name = 'do_form_view',
kwargs={'template_name':'form.html',
'success_url':'/finish/'},),
url(r'^finish/$',
view = 'finish',
name = 'finish_view')
)
This is all very well and good but when I have come to use this in my real world application I find myself in a situation that this form sits in the middle of some workflow, and I want the success url to be something like /continue/<workflow_id>/ , and the problem is that you can only have a hardcoded url in the url conf, and the workflow_id will vary every time I hit the do_form code.
Can any one suggest a way to get around this?
You can achieve that by changing the following..
in do_form() in views.py
change the return HttpResponseRedirect to
return HttpResponseRedirect('/continue/%s' %(workflowid))
And in urls.py, you can have
url(r'^continue/(?P<workflowid>\d+)/$',
view = 'continue',
name = 'continue_view')
and for the continue() view in views.py
def continue(request, workflowid=None):
...
This way.. whenever you access the url /continue/ without a number, workflowid will be equal to None. Every other time when you do have a workflowid attached for e.g. like /continue/23/ , then inside your continue() view you can access that id through the variable workflowid.
When you pass a hypothethical "flexible" success_url to a view, that view MUST supply the desired identifier. So if you mismatch the URL and the view, we can't avoid having a "breach of contract" between the two.
Therefore if we are to have flexible URLs, some kind of contract shall have to be enforced, and there will be no loss of generality if we do this through a special syntax for URLs:
'finished_url': '/finish/<workflow_id>/'
Then, of course, the view shall have to instantiate the variable through a string replacement to honor its side of the contract: instead of
return HttpResponseRedirect(finished_url)
you will have
return HttpResponseRedirect(finished_url.replace('<workflow_id>', WorkflowID))
This should keep things reasonably simple.
When reusing code, you will have to keep in mind that <workflow_id> is whatever that app uses to call workflow id, and that's why I use a complicated string such as workflow_id instead of id or maybe $1.
EDIT: I was going to add the code for the next step (intercepting workflow ID in argument of finish), but I see that keithxm23 beat me to the punch :-)
You can do it the same way people have been "overriding" Django's function-based generic views for years: simply wrap the view in another view:
def custom_do_form(request, entity_id, template_name, success_url):
template_name = some_method_to_get_template()
return do_form(request, entity_id, template_name, success_url)