I come from a PHP background and I've been trying to learn Python but I'm having a lot of trouble when it comes to debugging as I'm not yet sure how to go about this in Django or Python in general.
I'm used to being able to print_r
or var_dump
everything in PHP. I could do it in the controller, In a service layer or the even the model and data would show up in my web browser.
I can't do this in Django. Depending on what I'm doing, attempting to just perform a print
on an object from my view will bring the page down or output something to my console that doesn't really help me. Here's an example:
class Page(View):
def get(self, request, *args, **kwargs):
response = Data.objects.all()
# for whatever reason, I want to print something right now:
print response
# return JsonResponse({'success':response})
The above will take down my page completely with a notice saying:
The view didn't return an HttpResponse object. It returned None instead.
There are some instances while working with CBV's where I noticed I could get the data to just dump somewhere such as the console. But it wouldn't be anything that would help me. For instance if I was trying to to take a look at the contents of response
from above, it would just show up like so:
[object Object] [object Object] [object Object]
A var_dump
would have allowed me to actually see inside of it.
So I'm guessing I'm going about this all wrong. Do people just dump data when they're debugging in Python? If they do, how do you perform this, and does it show up in the web browser or the console? If not, how do I go handle basic troubleshooting in Django? Example scenarios:
Simply type python -m django --version or type pip freeze to see all the versions of installed modules including Django.
To fix this, first close the terminal window and relaunch it with administrator privileges. Once you launch the elevated terminal window change directory to where you wish to start your Django project. The command should work.
Server errorsWhen DEBUG is False , Django will email the users listed in the ADMINS setting whenever your code raises an unhandled exception and results in an internal server error (strictly speaking, for any response with an HTTP status code of 500 or greater).
The basic problem is that you are used to how PHP is wired into the entire request/response chain, and this is not how Python is configured when developing web applications.
In PHP-world, the server guarantees a response, which closes the request/response cycle. The PHP file is directly requested by the browser, so you are unaware of what is actually happening in the background.
A typical PHP request, is just the same as a request for any other static asset, like a plain index.html
file or logo.gif
. The browser requests, the web server accepts the request, and then returns the response; the only difference being if a file with .php
is requested, then it goes through an intermediary step where the PHP interpreter evaluates the file, and sends the result back to the client.
In Python however, when a request is made that is mapped to a Python backend process (sometimes called upstream process); the webserver waits for a response from the process (the timeout for this can be adjusted). If a response isn't received within the defined timeout, the webserver sends a timeout error page (504 ERROR).
It is the responsibility of the Python process to send a proper response (with all headers, etc.) as is expected by the browser. In PHP, this is hidden from you (as the developer), because the PHP engine will add these extra information for you. So when you have Python code that does not send such a response (as in your case), django helps you out by printing a friendly error message.
In your case - the view is not returning a response; its just printing something. This print statement will go to the standard output (or error stream) of the application (will be printed on the console if you launched it on the shell, or written to the server's log, etc.) it will not be sent back to the client (the browser).
In order to debug django applications:
DEBUG = True
is set in your settings.py
python manage.py runserver
Now, when you do any print statement, it will be shown on the console and if there is an error in your application code - as long as you are returning a valid response - you will get a rich error page along with a stack trace to help identify the problem.
There is no more "debugging statements and printing things on the browser" as you are developing; this is just how Python is wired into the web world.
For your other questions:
I want to see the contents of a list or dictionary
Simply print it. The output will be on your console (the same place where you wrote python manage.py runserver
)
I want to see the raw sql query being performed by the ORM
If you are testing things out in the django shell, you can just put .query
at the end of your ORM call to see the query being sent:
>>> result = MyModel.objects.filter(foo='bar')
>>> result.query
(query printed here)
For a more rich debugging experience, install django_debug_toolbar
.
I want to see if a function is being executed by slipping some text inside to be outputted on the front end
There is no "outputting to the front end". For such things, you can just print()
what you need, or even better use the logging system.
First, the reason you're getting an error isn't because you're printing, it's because you commented out the return:
class Page(View):
def get(self, request, *args, **kwargs):
response = Data.objects.all()
# for whatever reason, I want to print something right now:
print response
return JsonResponse({'success':response}) # <-- dont comment this out
Secondly, printing arbitrary objects won't always provide the best amount of information. If something defines a __str__
or __unicode__
method, that's what will be printed to the console. Otherwise, the object name along with its memory id will be printed. Not the most useful. Printing an object doesn't do a "deep" print.
You can try to print out the locals and globals:
print(locals())
print(globals())
Or serialise an object to JSON and print that:
print(json.dumps(response)) # some objects may not be serialisable to JSON though.
But you may not get the amount of detail you want from that either. The alternative is to run your webserver in debug mode, and raise an exception:
# settings.py
DEBUG = True
# views.py
def my_view(request):
raise Exception('debug')
.. and rely on django to show you the debug error page, which includes a stack trace, and allows you to inspect all the variables available in each frame.
First off, Django views require some sort of HttpResponse object to be returned. From the docs- In contrast to HttpRequest objects, which are created automatically by Django, HttpResponse objects are your responsibility. Each view you write is responsible for instantiating, populating and returning an HttpResponse.
There are many classes that that you can use to return that response (render_to_response, HttpResponseRedirect, JsonResponse and many, many more- https://docs.djangoproject.com/en/dev/ref/request-response/#httpresponse-subclasses). Your line # return JsonResponse({'success':response}) will do that if you get rid of the #.
Instead of a var_dump, you can use Python's dir function. All attributes of a class or class instance will be shown. See- Is there a function in Python to print all the current properties and values of an object?
You can print a dictionary. There are many ways to do it.
for key,value in your_dictionary.items(): print(key, ":", value)
Easy to do. print Data.objects.all().query . See - How to show the SQL Django is running
These are pretty basic parts of Django and Python. Not to be rude, but your time would probably be better spent doing some tutorials in full than embarking on your own projects. Once it clicks, it will be very simple. MVC/MVT frameworks have a different structure than PHP and you'll need to get used to working within it or will be frustrated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With