PROJECTS NOTES HOME

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