{"count":17,"next":"https://waynelambert.dev/api/blog/posts/?format=json&limit=3&offset=6","previous":"https://waynelambert.dev/api/blog/posts/?format=json&limit=3","results":[{"id":55,"title":"Quick Tip: VS Code Snippet for Python Developers","slug":"quick-tip-vs-code-snippet-for-python-developers","content":"<p>A common task when debugging is to be able to inspect your variables within the terminal or your development server. This can involve putting in some print statements within your code.</p>\r\n<p>Of course, for a more hefty debugging session, you can start up the VS Code debugger, however it's sometimes nice to get a quick view of your variables.</p>\r\n<p>The simplest way is to add a <span style=\"font-family: 'Ubuntu Mono', monospace;\">print</span> function:</p>\r\n<pre class=\"language-python\"><code>print(variable_name)</code></pre>\r\n<p>Python 3.8 makes this even better as you can easily give your print function some context by labelling it with the variable name in addition to its value:</p>\r\n<pre class=\"language-python\"><code>print(f\"{variable_name=}\")</code></pre>\r\n<p>This can be a little bit to type out when you're in the mode of rapid development, so this next tip will make this nice and easy.</p>\r\n<ol>\r\n<li>Open your command palette within VS Code. <span style=\"font-family: 'Ubuntu Mono', monospace;\">Cmd + Shift + P</span> is the default keybinding for Mac, and <span style=\"font-family: 'Ubuntu Mono', monospace;\">Ctrl + Shift + P</span> for Windows and Linux.</li>\r\n<li>Type in <span style=\"font-family: 'Ubuntu Mono', monospace;\">Configure user snippets</span> into the command palette and select it.</li>\r\n<li>Select <span style=\"font-family: 'Ubuntu Mono', monospace;\">Python</span> from the list.</li>\r\n<li>If you have no snippets yet, this will create a <span style=\"font-family: 'Ubuntu Mono', monospace;\">python.json</span> file for you and save it in a snippets directory. On my Mac, for example, it saves the file in the following location:</li>\r\n</ol>\r\n<p><span style=\"font-family: 'Ubuntu Mono', monospace;\">~/Library/Application Support/Code/User/snippets/python.json</span></p>\r\n<p>There will be some guidance to set up the snippet of your choice. For the snippet that I'm recommending, insert the following into the your file.</p>\r\n<pre class=\"language-json\"><code>{\r\n    \"Debug f String\": {\r\n        \"description\": \"Inserts boilerplate for a debug f string\",\r\n        \"prefix\": \"df\",\r\n        \"body\": [\r\n            \"print(f\\\"{${1:variable_name}=}\\\")\",\r\n        ]\r\n    }\r\n}</code></pre>\r\n<p>Now, whenever you type <span style=\"font-family: 'Ubuntu Mono', monospace;\">df</span> into your VS Code editor whilst in any Python file, it will autocomplete the remainder of the body and just leave you to overtype the name of the variable. This means you can enter a debug f string for a variable within about 5 or 6 key presses.</p>\r\n<p><span style=\"font-family: 'Ubuntu Mono', monospace;\">d -&gt; f -&gt; tab -&gt; {1 or 2 letters of variable name} - &gt; tab</span></p>\r\n<p>Best of all, you don't need to remember the syntax for a debug f string.</p>\r\n<p>Now, if you're really lazy, you can use the <span style=\"font-family: 'Ubuntu Mono', monospace;\">locals()</span> variable within another snippet because then you can get a more complete view of the local variables you have to hand and in even less key strokes.</p>\r\n<p>This time, insert this is into your <span style=\"font-family: 'Ubuntu Mono', monospace;\">python.json</span> snippets file:</p>\r\n<pre class=\"language-json\"><code>{\r\n    \"Debug f String Locals\": {\r\n        \"description\": \"Adds a debug f string with locals variables inserted\",\r\n        \"prefix\": \"dfl\",\r\n        \"body\": [\r\n            \"print(f\\\"{${1:locals()}=}\\\")\",\r\n        ]\r\n    }\r\n}</code></pre>\r\n<p>Now, this time in your Python file, simply type <span style=\"font-family: 'Ubuntu Mono', monospace;\">dfl</span> and you will get a completed debug f string along with the contents of the <span style=\"font-family: 'Ubuntu Mono', monospace;\">locals()</span> variable.</p>\r\n<p>For example, this can be really useful to insert just inside the return statement of a Django view function/method.</p>\r\n<p>One friendly word of warning though, if you're doing any Pandas data analysis, you might want to choose a different shortcut to <span style=\"font-family: 'Ubuntu Mono', monospace;\">df</span> since <span style=\"font-family: 'Ubuntu Mono', monospace;\">df</span> is used as the canonical reference variable for your dataframe and it might be annoying if you get a debug f string when you want to assign a dataframe. 😀</p>","reference_url":"","publish_date":"2020-09-29T19:20:55.533540Z","updated_date":"2020-10-04T12:33:44.739498Z","image":"https://wl-portfolio.s3.amazonaws.com/post_images/vscode-snippets.png","status":"Publish","word_count":575,"reading_time":8,"post_absolute_url":"/blog/post/quick-tip-vs-code-snippet-for-python-developers/","author_username":"wayne-lambert","author_first_name":"Wayne","author_last_name":"Lambert","author_full_name":"Wayne Lambert","author_initials":"WL","author_display_name":"Wayne Lambert","author_join_year":2019,"author_view":1,"author_created_date":"2019-07-21T10:02:09.888000Z","author_updated_date":"2022-12-14T14:44:36.068604Z","author_absolute_url":"/blog/users/wayne-lambert/profile/","author_profile_picture":"https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg","categories":[{"id":7,"name":"Infrastructure","slug":"infrastructure","created_date":"2019-08-02T13:33:45.888597Z"},{"id":9,"name":"Python","slug":"python","created_date":"2019-09-05T09:25:47.465274Z"}]},{"id":21,"title":"Integrate a Bootstrap File Upload Utility in Django","slug":"integrate-a-bootstrap-file-upload-utility-in-django","content":"<p>Integrating a standard file upload feature in Django is relatively straightforward. It's simply a case of rendering the individual image field in your Django template.</p>\r\n<p>For a functional image selector, there's absolutely nothing wrong with this approach. It achieves its objective of replacing an image field with another image that a user selects from their computer's hard drive.</p>\r\n<p>What about if you would like a full width selector with the name and image's location to be displayed within the image selector's form control? The image name should be displayed both when the user arrives at an update page, or following a selection of an image from their hard drive.</p>\r\n<p>This isn't as trivial as it perhaps could or even should be and there are a couple of preconditions that must be met before implementing this. Firstly, you'll need to ensure that the Bootstrap stylesheet is referenced within your site's &lt;head&gt; tag and the Bootstrap's JS is referenced inside the closing &lt;/body&gt; tag of your site.</p>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre><code class=\"language-html\"># base.html\r\n\r\n&lt;html lang=\"en\"&gt;\r\n  &lt;head&gt;\r\n    &lt;!-- Meta --&gt;\r\n    ...\r\n\r\n    &lt;!-- Bootstrap core CSS --&gt;\r\n    &lt;link rel=\"stylesheet\" \r\n    href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css\" \r\n    integrity=\"sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk\" \r\n    crossorigin=\"anonymous\"&gt;\r\n    ...\r\n  &lt;/head&gt;\r\n\r\n\r\n  &lt;body&gt;\r\n    ...\r\n    &lt;!-- Bootstrap JS --&gt;\r\n    &lt;script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js\" \r\n      integrity=\"sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI\" \r\n      crossorigin=\"anonymous\"&gt;\r\n    &lt;/script&gt;\r\n\r\n    &lt;!-- Additional Page Specific JavaScript --&gt;\r\n    {% block additional_js %}{% endblock additional_js %}\r\n  &lt;/body&gt;\r\n&lt;/html&gt;</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n<p>&nbsp;</p>\r\n<p>An additional script will also be required to be inserted as an additonal JavaScript block beneath your {% endblock content %} tag.</p>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre><code class=\"language-html\">{% extends 'base.html' %}\r\n{% load static %}\r\n\r\n{% block content %}\r\n  Your form's content...\r\n{% endblock content %}\r\n\r\n{% block additional_js %}\r\n  &lt;!-- Functionality for selected filename from input selector to be displayed --&gt;\r\n  &lt;script src={% static 'assets/js/input-filename.js' %} \r\n    type=\"application/javascript\"&gt;\r\n  &lt;/script&gt;\r\n{% endblock additional_js %}</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n<p>&nbsp;</p>\r\n<p>In your create/update form code, you will need to render out each of the form fields individually. When it comes to rendering out the image field with the Bootstrap file picker, you will need to use the following code.</p>\r\n<p>'form' is the name you have given to your form. The canonical way of naming your form is 'form'</p>\r\n<p>'image' is the name of your image field</p>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre><code class=\"language-html\">&lt;!-- Post Image --&gt;\r\n&lt;div class=\"custom-file mt-2\"&gt;\r\n  &lt;input type=\"file\" class=\"custom-file-input\" name=\"image\" accept=\"image/*\" \r\n    id=\"{{ form.image.id_for_label }}\"&gt;\r\n  &lt;label class=\"custom-file-label\" for=\"{{ form.image.id_for_label }}\"&gt;\r\n    {% if post.image %}{{ post.image.name }}{% else %}Select Post Image...{% endif %}\r\n  &lt;/label&gt;\r\n  &lt;div class=\"small text-muted\"&gt;{{ form.image.help_text }}&lt;/div&gt;\r\n  &lt;span class=\"text-danger small\"&gt;{{ form.image.errors }}&lt;/span&gt;\r\n&lt;/div&gt;</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n<p>The JavaScript code that makes this work is:</p>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre><code class=\"language-javascript\">$('input[type=\"file\"]').change(function(e){\r\n  var fileName = e.target.files[0].name;\r\n  $('.custom-file-label').html(fileName);\r\n});</code></pre>\r\n</div>\r\n</div>\r\n<hr />\r\n<div><u><strong>Reference Details</strong></u></div>\r\n</div>\r\n</div>\r\n<p>&nbsp;</p>\r\n<p>You can find my implementation of this at the following commit: <a href=\"https://github.com/WayneLambert/portfolio/tree/93e4193940f2b1c71c2d14cc45a617833f2584da\" target=\"_blank\" rel=\"noopener\">Reference GitHub Code</a></p>\r\n<p>Use GitHub's <strong>'Go to file'</strong> button to look for the following files:</p>\r\n<ul>\r\n<li>pages/templates/pages/base.html</li>\r\n<li>pages/templates/pages/js.html</li>\r\n<li>blog/templates/blog/components/post_create.html</li>\r\n<li>blog/templates/blog/components/post_image_update.html</li>\r\n<li>static/assets/js/input-filename.js</li>\r\n</ul>\r\n<p><a href=\"https://getbootstrap.com/docs/4.5/components/forms/#file-browser\" target=\"_blank\" rel=\"noopener\">Here are the relevant Boostrap Docs</a></p>\r\n<p><strong>Pinned Versions:</strong> Python 3.8.3, Django 3.0.7, Bootstrap 4.5.0</p>","reference_url":"","publish_date":"2020-07-03T14:07:45.504608Z","updated_date":"2020-10-04T11:42:36.414893Z","image":"https://wl-portfolio.s3.amazonaws.com/post_images/bootstrap-file-image-upload.png","status":"Publish","word_count":501,"reading_time":7,"post_absolute_url":"/blog/post/integrate-a-bootstrap-file-upload-utility-in-django/","author_username":"wayne-lambert","author_first_name":"Wayne","author_last_name":"Lambert","author_full_name":"Wayne Lambert","author_initials":"WL","author_display_name":"Wayne Lambert","author_join_year":2019,"author_view":1,"author_created_date":"2019-07-21T10:02:09.888000Z","author_updated_date":"2022-12-14T14:44:36.068604Z","author_absolute_url":"/blog/users/wayne-lambert/profile/","author_profile_picture":"https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg","categories":[{"id":11,"name":"Bootstrap","slug":"bootstrap","created_date":"2020-09-07T20:58:13.432133Z"},{"id":1,"name":"Django","slug":"django","created_date":"2019-07-27T21:39:31.016414Z"}]},{"id":17,"title":"How to Keep a History of the Last n Items in Python","slug":"how-to-keep-history-last-n-items-python","content":"<p>If I would like to keep a history of the last n number of items that have been seen during iteration or some other kind of processing.</p>\r\n<p>A limited history can be maintained using the <strong>deque</strong> data structure within the <strong>collections</strong> module. The code below performs a word match from within the <strong>words.txt</strong> file used within this site's <a href=\"../../../../countdown-letters/selection/\">Countdown: Letters Game application</a>.</p>\r\n<p>It yields the matching line from the file and&nbsp;the previous 10 lines. The default number of historic lines to use in cases where the third parameter is not submitted to the <strong>'search'</strong> function is 5.</p>\r\n<div>\r\n<pre><code class=\"language-python\">from collections import deque\r\n\r\ndef search(lines, word, history=5):\r\n    previous_lines = deque(maxlen=history)\r\n    for line in lines:\r\n        if word in line:\r\n            yield line, previous_lines\r\n        previous_lines.append(line)\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    with open('countdown_letters/words.txt') as f:\r\n        for line, prevlines in search(f, 'python', 10):\r\n            for pline in prevlines:\r\n                print(pline, end='')\r\n            print(line, end='')\r\n            print('-' * 20)</code></pre>\r\n</div>\r\n<p>The final print functions just return some formatting for the outputted text to the terminal.</p>","reference_url":"","publish_date":"2019-09-16T19:55:11.680148Z","updated_date":"2020-10-03T21:57:40.182456Z","image":"https://wl-portfolio.s3.amazonaws.com/post_images/algorithm2.jpg","status":"Publish","word_count":165,"reading_time":3,"post_absolute_url":"/blog/post/how-to-keep-history-last-n-items-python/","author_username":"wayne-lambert","author_first_name":"Wayne","author_last_name":"Lambert","author_full_name":"Wayne Lambert","author_initials":"WL","author_display_name":"Wayne Lambert","author_join_year":2019,"author_view":1,"author_created_date":"2019-07-21T10:02:09.888000Z","author_updated_date":"2022-12-14T14:44:36.068604Z","author_absolute_url":"/blog/users/wayne-lambert/profile/","author_profile_picture":"https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg","categories":[{"id":8,"name":"Algorithms","slug":"algorithms","created_date":"2019-09-05T08:51:56.026246Z"},{"id":10,"name":"Data Structures","slug":"data-structures","created_date":"2019-09-26T20:04:59.582866Z"},{"id":9,"name":"Python","slug":"python","created_date":"2019-09-05T09:25:47.465274Z"}]}]}