I am new to Django, and having a difficulty soting out a problem. My code is processing extra method in views.py even without being called.Below is an example:-
When I am cliking on Home button on my page.
Landing Page:
I am being redirected to correct view method i.e., index.
IndexMthod in views.py:
After loading the page my code is hitting another method edit content, without being called with a param favicon.io
Concern Method
which is my concern.
Though it is not affecting my django app, but still it's annoying to see extra method being called everytime.
Please let me know, if I have done something wrong here or if any more info is required from my end. Thanks in advance.
Related
I am building a simple blog using Web2Py on Debian Linux.
I have a controller called blog.py, to which I added the following function, along with an if block:
def display_form():
form = SQLFORM(db.blog)
if form.process().accepted:
session.flash = 'form accepted'
redirect(URL('thanks'))
elif form.errors:
response.flash = 'form has errors'
else:
response.flash = 'please fill out the form'
return locals()
I proceeded to add a "view" html file called blog/display_form.html, with a basic template, as follows:
{{extend 'layout.html'}}
<h1>Display Form</h1>
{{=form}}
I load the "display_form" blog page just fine, and it accepts all the input successfully, but it does not redirect to a thank you page. Instead, the browser generates an "invalid function blog/thanks" error.
I tried removing the compiled app via the Web2Py admin interface, and recompiled everything. Still does not work. I added a "view" for the "Thanks" page, but that does not change anything. I restarted the Web2Py framework and the web server, but still no go.
Some web sites refer to a possible routes.py issue, but I am confused as to why that would be pertinent at all.
Please help,
I am hitting a brick wall here.
So, after tweaking a number of things, and removing all of the compiled files, and starting from scratch again, the solution turned out to be way more simple than I was trying to make it.
I simply defined a function called thanks in the aforementioned blog.py controller, and returned the local variables, like so:
def thanks():
return locals()
I then added a blog/thanks view file, with a basic html header, stating:
Thank you for submitting the form!
And it finally redirected the display_form blog page as intended to a thanks page, thereby flashing the form accepted message (also as expected).
Thanks for your help, Anthony!
Cheers.
When you pass only a single argument to the URL() helper, it assumes that argument is the function name and that the controller is the current controller. Since the current controller is blog, URL('thanks') will generate the following URL: /yourapp/blog/thanks.
Presumably, your thanks function is in a different controller (perhaps default.py), in which case, a request for the above URL will generate the error you observe. Just change the URL to URL('default', 'thanks').
I'm working on a Django project, and I've created some custom admin views using the get_urls override method described in the documentation. It works perfectly. There is just one problem. There is no way to get to this custom admin view unless you already know the URL.
There are some ways I already know of to add a link to this view somewhere in the admin, but none of them are satisfactory. I want a link to the custom view to appear in the model listings right with all the model admins. I just don't want it to have +add or +change links next to it because it isn't a model.
I could just override the admin_site or the template, but this is no good. It puts the customization on the project level instead of the app level. It also will only put the link on the /admin/ page and not the /admin/myapp/ page.
I could also just easily add the link in a different location by overriding the app_index.html template, but that is not exactly a convenient or intuitive place to look for it.
Another solution I came up with is to create a blank model and register a blank admin for it. Then steal the url patterns for that model so clicking on its entry goes to my custom view instead of to a blank add/change view. That works, but it's an incredibly ugly hack.
Here is a picture of what I'm trying to achieve.
I still think the correct way of doing this is overwriting some parts of django admin templates. There is no easy way of adding these links.
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing-an-admin-template
I also found this article http://coffeeonthekeyboard.com/o-hai-django-adminplus-568/ which also suggests that django-adminplus is a good tool for doing this. Personally I prefer to keep clear of any extra dependancies and would still use templates - but thats up to you.
Have you tried this app: https://github.com/jsocol/django-adminplus? Even if it does not work for the exact purpose you are trying to achieve, at least it can give you some enlightement by checking out the code
You need to override the template admin/index.html. Thenput a new pair of tags after the {% endfor %} on line 40.
You might also be able to solve it using jQuery.
I am getting a template error during rendering, which I think would be easy to fix if I could just see what's in the context that is passed into the template that is being rendered. Django's debug error page provides a lot of information, but I'm not seeing my context anywhere. Am I missing something? Also, I am using Django-debug-toolbar, but that only seems to come up if the page successfully renders. Not being able to see the contents of the context that is passed to the template makes debugging some types of template errors hard! What do I need to do to be able to see it in this scenario? (Note that I'm not asking for a fix to my specific error, which is why I'm not providing more information about it).
From the comments:
I think you need to walk up the stacktrace (in the django debug page) to actually see your context variables. I don't understand your problem exactly. If I have a template error I can inspect my context somewhere in the traceback.
Yes, setting a "breakpoint" in django can sometimes mean just inserting a non-defined variable at the point you want to inspect. The last entry in the traceback is usually the one for this variable. It will give you all context details in the traceback of the debug page.
The easiest way to do this is with the Django Debug Toolbar. it will give you a popup tab on the right hand side of your screen that you can use to inspect various things about the current page's request. Things like SQL statements, versions, logging, and all the templates that were used to render the page, and the context available to each of them.
There's some functionality on our Django app that displays a link to refresh some information from our version control system. This is simply a link, and when they hit that URL the actions of going to version control, getting the information, checking it against the database and updating the database are performed.
Recently we had a user click the 'refresh' button twice for one asset. This resulted in the URL being hit twice, so the operations were performed twice and eventually a duplicate entry was created in our database.
We need to do something to remove the possibility of the user clicking that button twice. Should we move from a link to a javascript button? Should we set some flag in request.session as soon as the first click happens, then unset it upon completion, and always check that flag when performing a refresh? Those are just two ideas that seem feasible, but I really don't know.
You should use POST request and redirect after it, really.
Also, to prevent double submitting, you can employ a solution like one from this question: Does a library to prevent duplicate form submissions exist for django?. You can store a key refreshing_vcs in request.session and check its value in your view. If the data is already being refreshed, then you can redirect user to another page and tell to wait a bit.
Completely another way would be to setup a django-celery task (or simply use cron) to perform updates at regular intervals automatically, but I don't know whether it suit your requirements.
That is the best solution, however you could disable the button onclick by adding a disabled attribute to the button equalling 'true'
With jQuery:
$('#yourButtonId').attr("disabled", true);
from django.views import View
from django.shortcuts import render, redirect
class MyView(View):
def get(self, request):
return render(request, 'get.html')
def post(self, request):
# handle your post here
# maybe you had a form that was filled, handle it here
# then instead of returning a HttpResponse
# use a redirect, that way, a refresh won't result in the
# post method been called twice.
# note if you want, you can also safely redirect to the same view
return redirect('/my-login-view')
looking at the django code the redirect functions arguments can be:
1. A model
2. A view name or
3. A URL
Is there anyway to pass context variables to a redirect response? I want to redirect a user to a success page after they submit a form, but I don't want the success page to be just a static html file. I need to display extra information based on the form data.
I have looked at this question, but the solution presented there simply renders a different file at the same url. I'd like to redirect the user so that hitting refresh at the page won't submit duplicate entries into the application.
Right now the only thing I have been able to use with some success is redirecting to a url while passing it GET variables as described here. That just seems like a bit of a hack, and was just wondering if there is any better solution...
Thank You
The way I see it you have three options:
Use GET variables in the redirect.
Store something in the session.
If you are creating an object using the form that was submitted, put the id of that object in the redirect url and use it in the new view.
The limitation you are running up against is that http is stateless, not something inherent in django.
How about storing your values in a session, then have the redirected page pick up the values from there?