Print that info, tips for debugging django with print statements
1 Print that info
1.1 Check out debug-toolbar package.
1.2 Print attributes through __init__
In Django, when you define methods or attributes directly within a class body (outside of any method), they are executed only once when the class is defined, not every time an instance of the class is created or used.
In your case, the lol method is defined directly within the CollateralInline class body. Therefore, it's executed only once when the CollateralInline class is defined, typically when the server starts or when the admin module is loaded.
If you want lol to be executed every time a page is loaded or refreshed in the Django admin interface, you should call it from within a method that gets executed during the page rendering process, such as get_formset, get_fields, or __init__.
from django.contrib import admin from .models import * class CollateralInline(admin.TabularInline): model = Collateral extra = 1 readonly_fields = ('status',) # ON EACH PAGE REFRESH KAZKAIP KAZKODEL def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) print(self.readonly_fields) print("lol") # Call the lol method when an instance of CollateralInline is created def lol(self): print("lolziesssssssssssss") class DealAdmin(admin.ModelAdmin): inlines = [CollateralInline] # VIENA KARTA TIK KAI INITIATING def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) CollateralInline.lol(self) # Call the lol method when an instance of DealAdmin is created
1.3 Print attrs, values, ojb, request
through get_fields
from django.contrib import admin from .models import * class CollateralInline(admin.TabularInline): model = Collateral extra = 1 readonly_fields = ('status',) # ON EACH PAGE REFRESH def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) print(self.extra) # why I can only do it from already defined methods? def get_fields(self, request, obj=None): # print(obj.register_date) print('REQUEST INFO BELOW===================================') print(dir(request)) print('REQUEST HEADERS BELOW===================================') print(request.headers) print('SELF DICT BELOW===================================') print(self.__dict__) print('SELF STUFF BELOW===================================') print(self.verbose_name) print(self.opts) print('OBJ BELOW===================================') print(obj) print(obj.__dict__) print('FIELDS===================================') z = super().get_fields(request, obj) z.sort() print(z) print(dir(z)) print(type(z)) # Print the values of each field print('FIELD VALUES===================================') for field in z: # Get the field value from the obj instance print(f'{field}') for obj in self.get_queryset(request): # Print a separator between rows print('--------------------------') # Print the values of each field for the current row for field in z: # Get the field value from the obj instance field_value = getattr(obj, field) # Use field directly # Print the field name and its corresponding value print(f'{field}: {field_value}') return z class DealAdmin(admin.ModelAdmin): inlines = [CollateralInline] # # Once only, when initiating # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) admin.site.register(Deal, DealAdmin) admin.site.register(Vessel) admin.site.register(Collateral)
1.4 See the query
that django is executing
Multiple ways to SEE the SQL that Django executes: 8 different ways - https://b0uh.github.io/django-show-me-the-sql.html
lol = str(Quote.objects.filter(text__icontains="niuk").query) print(lol)
result of that above is:
SELECT "quotes_quote"."id", "quotes_quote"."text", "quotes_quote"."author_id", "quotes_quote"."active", "quotes_quote"."date_created" FROM "quotes_quote" WHERE "quotes_quote"."text" LIKE %niuk% ESCAPE '\'
Print the queries that django is executing
from django.db import connection print(connection.queries)
See queries with django extensions and shell_plus. Do pip install
django-extensions
. Add to installed apps!!!! - 'django_extensions',
. After
installation can do: python manage.py shell_plus --print-sql
1.5 Fetch opt
values. Write this in the template
<script> console.log("Model name: {{ opts.model_name }}"); </script>
{% if opts.model_name == 'deal' %} <script src="{% static 'js/deal.js' %}"></script> {% elif opts.model_name == 'vessel' %} <script src="{% static 'js/vessel.js' %}"></script> {% endif %}
1.6 opts
again
{% extends "admin/change_form.html" %} {% load i18n admin_urls static admin_modify %} {% block admin_change_form_document_ready %} <script src="{% static 'js/vessel.js' %}"></script> {% endblock %} {% if opts.model_name == 'deal' %} <script src="{% static 'js/deal.js' %}"></script> {% elif opts.model_name == 'vessel' %} <script src="{% static 'js/vessel.js' %}"></script> {% endif %}
Fetch opt values. Write this in the template
<script> console.log("Model name: {{ opts.model_name }}"); </script>
1.7 Print the current object
class QuoteUpdateView(UpdateView): model = Quote fields = "__all__" success_url = reverse_lazy('quote-list') def get_object(self, queryset=None): """ Return the object the view is displaying. """ # Call the superclass method to get the object obj = super().get_object(queryset=queryset) print(obj) return obj def form_valid(self, form): """ Return the object the view is saving. """ # Print the instance that's going to be updated print(self.object) # Call the superclass form_valid method to continue the update process return super().form_valid(form)
1.8 Introspection!! Create an instance of a class and print out its attributes/methods
Was trying to find out the csss that is being used for autocomplete widget.
from dal import autocomplete # Assuming you have an instance of ModelSelect2 widget_instance = autocomplete.ModelSelect2() # Print all attributes and methods of the widget instance print(dir(widget_instance))
Printed it out, then saw bunch of attributes/methods:
['__class__', '__deepcopy__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', '__subclasshook__', '__weakref__', '_choice_has_empty_value', '_get_language_code', '_get_url', '_make_forward_dict', '_render', '_set_url', '_url', 'add_id_index', 'allow_multiple_selected', 'attrs', 'autocomplete_function', 'build_attrs', 'checked_attribute', 'choices', 'create_option', 'filter_choices_to_render', 'format_value', 'forward', 'get_context', 'id_for_label', 'input_type', 'is_hidden', 'is_localized', 'is_required', 'media', 'needs_multipart_form', 'optgroups', 'option_inherits_attrs', 'option_template_name', 'options', 'placeholder', 'render', 'render_forward_conf', 'render_options', 'subwidgets', 'supports_microseconds', 'template_name', 'url', 'use_fieldset', 'use_required_attribute', 'value_from_datadict', 'value_omitted_from_data']
Saw "media" inside of it. So I printed out the media
print(widget_instance.media)
, got all the media files. Now I know exactly
where the stylesheets are, can override them.
<link href="/static/static/admin/css/vendor/select2/select2.css" media="screen" rel="stylesheet"> <link href="/static/static/admin/css/autocomplete.css" media="screen" rel="stylesheet"> <link href="/static/static/autocomplete_light/select2.css" media="screen" rel="stylesheet"> <script src="/static/static/admin/js/vendor/select2/select2.full.js"></script> <script src="/static/static/autocomplete_light/autocomplete_light.js"></script> <script src="/static/static/autocomplete_light/select2.js"></script> <script src="/static/static/autocomplete_light/i18n/en.js"></script>
1.9 Built in dir
and locals
methods
See current local scope
dir() Locals() print(dir(VesselInline))
1.10 Print request
info on each page with context_processor
Can probably do it in the shell or views.py, but another way, to do it for
each page is to use context_processor
def request_info(request): request_info = dir(request) print("request:", request_info) print("User:", getattr(request, 'user', None)) return {"request_info": request_info}
In settings.py
add context_processor:
'context_processors.request_info',
Then in template:
<p>Request info - {{request_info}}</p>
1.11 Print out ALL the CONTEXT variables
class OneListView(generic.ListView): # model = One is shorthand for saying queryset = One.objects.all() model = One def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Add the model name to the context print(dir(self.model._meta)) context['model_name'] = self.model._meta.verbose_name_plural return context
Result:
['FORWARD_PROPERTIES', 'REVERSE_PROPERTIES', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_expire_cache', '_format_names_with_class', '_forward_fields_map', '_get_default_pk_class', '_get_fields', '_get_fields_cache', '_non_pk_concrete_field_names', '_ordering_clash', '_populate_directed_relation_graph', '_prepare', '_property_names', '_relation_tree', 'abstract', 'add_field', 'add_manager', 'app_config', 'app_label', 'apps', 'auto_created', 'auto_field', 'base_manager', 'base_manager_name', 'can_migrate', 'concrete_fields', 'concrete_model', 'constraints', 'contribute_to_class', 'db_returning_fields', 'db_table', 'db_table_comment', 'db_tablespace', 'default_apps', 'default_manager', 'default_manager_name', 'default_permissions', 'default_related_name', 'fields', 'fields_map', 'get_ancestor_link', 'get_base_chain', 'get_field', 'get_fields', 'get_latest_by', 'get_parent_list', 'get_path_from_parent', 'get_path_to_parent', 'index_together', 'indexes', 'label', 'label_lower', 'local_concrete_fields', 'local_fields', 'local_managers', 'local_many_to_many', 'managed', 'managers', 'managers_map', 'many_to_many', 'model', 'model_name', 'object_name', 'order_with_respect_to', 'ordering', 'original_attrs', 'parents', 'permissions', 'pk', 'private_fields', 'proxy', 'proxy_for_model', 'related_fkey_lookups', 'related_objects', 'required_db_features', 'required_db_vendor', 'select_on_save', 'setup_pk', 'setup_proxy', 'swappable', 'swapped', 'total_unique_constraints', 'unique_together', 'verbose_name', 'verbose_name_plural', 'verbose_name_raw']
1.12 Print out ALL info about the object
class OneListView(ListView): model = One print(dir()) print(locals()) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Print the docstring print("Docstring:", self.__doc__) # Print the base classes print("Base classes:", self.__class__.__bases__) # Print the class dictionary print("Class dictionary:", self.__dict__) # Print the class methods print("Class methods:") for key, value in self.__class__.__dict__.items(): if callable(value): print("\t", key, ":", value) # Print the instance dictionary print("Instance dictionary:", self.__dict__) # Print the instance methods print("Instance methods:") for key, value in self.__dict__.items(): if callable(value): print("\t", key, ":", value)
1.13 Add a custom variable to object list
from django.shortcuts import render from django.views import generic from three.models import Three class ThreeListView(generic.ListView): # model = One is shorthand for saying queryset = One.objects.all() model = Three template_name = 'list_view.html' context_object_name = 'object_list' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # print(f"CONTEXT IS HERE {context}") context['model_name'] = self.model.__name__.lower() # Lowercase model name context['model_name_plural'] = self.model._meta.verbose_name_plural # Plural form of model name # print(f"UPDATED IS HERE {context}") return context
Can then use it in the templates like so:
<h1>List of {{ model_name_plural }}</h1> <!-- {% if "three" in model_name_plural %} <p>Hello</p> {% else %} <p>NOTTTTTTTT</p> {% endif %} --> <ul id="{{model_name_plural}} object_list"> {% for instance in object_list %} <p>Hello</p> <!-- <li><a href="{% url model_name|add:'_detail' pk=instance.pk %}">{{ instance }}</a></li> --> {% endfor %} </ul>
1.14 _meta !!!!!!!!!!!
class TwoListView(ListView): # model = One is shorthand for saying queryset = One.objects.all() model = Two print(dir(model._meta)) paginate_by = 15
1.15 Create a debugging decorator! Printerino
def printerino(cls): ''' The printerino function takes a class as input (cls) and prints out various information about it when called. The __init__ method within the printerino function is modified to print out additional information about the class and its instances. The @printerino decorator is used to apply the printerino functionality to the OneListView class. This effectively modifies the __init__ method of OneListView to include the printing functionality. idomu del ko su GreetingView neveikia pilnai, bet su OneListView veikia. ''' print(dir(cls)) print(locals()) def __init__(self, *args, **kwargs): super(cls, self).__init__(*args, **kwargs) # Print the docstring print("Docstring:", self.__doc__) # Print the base classes print("Base classes:", self.__class__.__bases__) # Print the class dictionary print("Class dictionary:", self.__dict__) # Print the class methods print("Class methods:") for key, value in self.__class__.__dict__.items(): if callable(value): print("\t", key, ":", value) # Print the instance dictionary print("Instance dictionary:", self.__dict__) # Print the instance methods print("Instance methods:") for key, value in self.__dict__.items(): if callable(value): print("\t", key, ":", value) cls.__init__ = __init__ return cls
Then to use it in the python code, add this above the classes: @printerino