tag:blogger.com,1999:blog-82274510829015317622024-03-17T09:40:22.895+02:00Programmer blogMy thoughts/recipes on Django, Python, JS and other things I try...garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.comBlogger92125tag:blogger.com,1999:blog-8227451082901531762.post-38317602722760224022023-03-02T19:30:00.000+02:002023-03-02T19:30:04.212+02:00Install bcrypt on Mac OSX<p> Basically One can do it wih homebrew.</p><h4 style="background-color: white; border: 0px; box-sizing: border-box; clear: both; color: #333333; font-family: Roboto; font-size: 18px; font-weight: 500; line-height: 1.1; margin: 10px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">About the App</h4><ul style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Roboto; font-size: 14px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 10px 3em; outline: 0px; padding: 0px; vertical-align: baseline;"><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><b style="box-sizing: border-box;">App name</b>: bcrypt</li><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><b style="box-sizing: border-box;">App description</b>: Cross platform file encryption utility using blowfish</li><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><b style="box-sizing: border-box;">App website</b>: <a href="http://bcrypt.sourceforge.net/" style="background-color: transparent; border: 0px; box-sizing: border-box; color: #555555; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration-line: none; transition: all 0.1s ease 0s; vertical-align: baseline;">http://bcrypt.sourceforge.net</a></li></ul><h4 style="background-color: white; border: 0px; box-sizing: border-box; clear: both; color: #333333; font-family: Roboto; font-size: 18px; font-weight: 500; line-height: 1.1; margin: 10px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Install the <i>homebrew </i>package manager</h4><ol style="border: 0px; box-sizing: border-box; font-family: Roboto; font-size: 14px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 10px 3em; outline: 0px; padding: 0px; vertical-align: baseline;"><li style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Open <b style="box-sizing: border-box;"><i style="box-sizing: border-box;">Terminal</i></b> and press <b style="box-sizing: border-box;"><i style="box-sizing: border-box;">enter/return</i></b> key.</li><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: white; color: #333333;">Copy and paste the following command in Terminal app:</span><br style="box-sizing: border-box;" /><code style="border-radius: 4px; border: 0px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"><span style="background-color: black; color: #6aa84f;">/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"</span></code><br style="box-sizing: border-box;" /><span style="background-color: white; color: #333333;">and press </span><b style="background-color: white; box-sizing: border-box; color: #333333;"><i style="box-sizing: border-box;">enter/return</i></b><span style="background-color: white; color: #333333;"> key. Wait for the command to finish. If you are prompted to enter a password, please type your Mac user's login password and press ENTER. Mind you, as you type your password, it won't be visible on your Terminal (for security reasons), but rest assured it will work.</span></li><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: white; color: #333333;">Now, copy/paste and run this command to make </span><i style="background-color: white; box-sizing: border-box; color: #333333;">brew</i><span style="background-color: white; color: #333333;"> command available inside the Terminal: </span><code style="border-radius: 4px; border: 0px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"><span style="background-color: black; color: #6aa84f;">echo 'eval</span></code><code style="background-color: #f9f2f4; border-radius: 4px; border: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"> </code><code style="border-radius: 4px; border: 0px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"><span style="background-color: black; color: #6aa84f;">"$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile</span></code></li></ol><div><h4 style="background-color: white; border: 0px; box-sizing: border-box; clear: both; color: #333333; font-family: Roboto; font-size: 18px; font-weight: 500; line-height: 1.1; margin: 10px 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Install the <i>bcrypt </i>lib</h4></div><ol style="border: 0px; box-sizing: border-box; font-family: Roboto; font-size: 14px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 10px 3em; outline: 0px; padding: 0px; vertical-align: baseline;"><li style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: white; color: #333333;">Copy and paste the following command:</span><br style="box-sizing: border-box;" /><code style="border-radius: 4px; border: 0px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"><span style="background-color: black; color: #6aa84f;">brew install bcrypt</span></code></li></ol><p style="border: 0px; box-sizing: border-box; font-family: Roboto; font-size: 15px; letter-spacing: 0.05em; line-height: 2em; margin: 0px 0px 10px; outline: 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: white; color: #333333;">Done! You can now use </span><code style="background-color: black; border-radius: 4px; border: 0px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.5px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 2px 4px; vertical-align: baseline;"><span style="color: #6aa84f;">bcrypt</span></code><span style="background-color: white; color: #333333;">.</span></p>garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-685711527077270052022-12-19T21:46:00.005+02:002022-12-19T21:46:59.029+02:00Writing nice prompts for stable diffusion and like neural networks<p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px 0px 1.25em;"><span style="background-color: white; font-family: inherit; white-space: pre-wrap;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="background-color: white; font-family: inherit; white-space: pre-wrap;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Htt8strw82xwyA3T3j6J_5YSeRz3FCZLcm8xSC9ovKVt1TUH0nKYvyUMUS5nqeM8D9rLtb9AspbKRAUfJtc0NKVMUN-fkpUfSz5K_bgK9Zk-K_MhfuE6fXbHcL-wbRj9SlNByBws0QFDQnzVC5GMgwEUxkcDZokZ4uRqzwMbG0Wpz89gYSc47l4fwQ/s512/000011.82287a03.360540989.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Htt8strw82xwyA3T3j6J_5YSeRz3FCZLcm8xSC9ovKVt1TUH0nKYvyUMUS5nqeM8D9rLtb9AspbKRAUfJtc0NKVMUN-fkpUfSz5K_bgK9Zk-K_MhfuE6fXbHcL-wbRj9SlNByBws0QFDQnzVC5GMgwEUxkcDZokZ4uRqzwMbG0Wpz89gYSc47l4fwQ/s320/000011.82287a03.360540989.png" width="320" /></a></span></div><span style="background-color: white; font-family: inherit; white-space: pre-wrap;"><br />
<i>Request:</i></span><span style="background-color: white; font-family: inherit; white-space: pre-wrap;"><i> </i></span><span style="white-space: pre-wrap;"><i>new york city, synthwave, cinematic, dramatic, composition, sunny sky, brutalist, hyper realistic, epic scale, sense of awe, hypermaximalist, insane level of details, artstation HQ</i></span><p></p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px 0px 1.25em; white-space: pre-wrap;"><span style="background-color: white;">Playing with neural models is really fun. Let's try to make our best at writing good requests. That's the key! So thst's how:</span></p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px 0px 1.25em; white-space: pre-wrap;"><span style="background-color: white; font-family: inherit;">Diffusion prompts are statements or questions that are designed to help individuals think more deeply about a topic or concept and draw their own conclusions. They are often used in discussions or debates to encourage critical thinking and encourage participants to consider different perspectives.</span></p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 1.25em 0px; white-space: pre-wrap;"><span style="background-color: white; font-family: inherit;">Here are some tips for writing good, stable diffusion prompts:</span></p><ol style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; counter-reset: item 0; display: flex; flex-direction: column; list-style-image: initial; list-style-position: initial; margin: 1.25em 0px 0px; padding: 0px 0px 0px 1rem; white-space: pre-wrap;"><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;"><span style="background-color: white; font-family: inherit;">Make sure the prompt is clear and concise: Avoid using jargon or complex language that may be confusing to readers. Keep the prompt brief and to the point, so that it is easy for readers to understand and respond to.</span></p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;"><span style="background-color: white; font-family: inherit;">Focus on a specific topic or concept: Choose a specific topic or concept to focus on, and make sure the prompt is directly related to this topic. This will help readers stay on track and avoid getting sidetracked by unrelated issues.</span></p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;"><span style="background-color: white; font-family: inherit;">Encourage critical thinking: The goal of a diffusion prompt is to encourage critical thinking and encourage participants to consider different perspectives. Use questions or statements that challenge readers to think more deeply about the topic and consider alternative viewpoints.</span></p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;"><span style="background-color: white; font-family: inherit;">Avoid leading questions: Avoid using questions that are biased or leading, as these can influence the reader's response and skew the results of the discussion. Instead, use neutral, unbiased language to encourage honest and objective responses.</span></p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;"><span style="background-color: white; font-family: inherit;">Make sure the prompt is relevant: The prompt should be relevant to the topic being discussed and should be of interest to the reader. If the prompt is not engaging or relevant, it may be difficult to get a meaningful response.</span></p></li></ol><div><span style="white-space: pre-wrap;"><br /></span></div><div><span style="white-space: pre-wrap;">Ths's it...</span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrJfbRW8Gz1z-f-gyEdX_w9Adh-xyC9EF4NEKZyxVFqzXPO-sWjR1OQMKwy2g0y_BaXerKO7eZhsqEqdvSeaF_yYIxVU1FJyrSf339PE_ANSss_SSfAXhNW3QEL6GjTFHYP0iudlGtR_h1iLKQK-4bzwnYFgLRusyS6adbuVbD1rt7YhZtVyFazAwxKg/s512/000010.8e9aa1ce.920962500.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrJfbRW8Gz1z-f-gyEdX_w9Adh-xyC9EF4NEKZyxVFqzXPO-sWjR1OQMKwy2g0y_BaXerKO7eZhsqEqdvSeaF_yYIxVU1FJyrSf339PE_ANSss_SSfAXhNW3QEL6GjTFHYP0iudlGtR_h1iLKQK-4bzwnYFgLRusyS6adbuVbD1rt7YhZtVyFazAwxKg/s320/000010.8e9aa1ce.920962500.png" width="320" /></a></div><br /><span style="white-space: pre-wrap;"><br /></span></div><div><span style="white-space: pre-wrap;"><i>Request: new york city, dust storm, cinematic, dramatic, composition, sunny sky, brutalist, hyper realistic, epic scale, sense of awe, hypermaximalist, insane level of details, artstation HQ</i></span></div>garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-10807260680006306882019-02-19T12:07:00.002+02:002019-02-19T12:16:27.846+02:00Running tasks with Celery on Heroku guide<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeMAN1iW2LxIrVAwU4BtpN8WkaPbEANjB6tBxvNaxTl2qRI5_olPF3vrTMas57aN0XNObe4sXX2gKuUWvFy95jMn1BaaFhhyNccbbLWT7St000-C992w-jH5goZibMAeUnJh01CzWjslHO/s1600/download.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeMAN1iW2LxIrVAwU4BtpN8WkaPbEANjB6tBxvNaxTl2qRI5_olPF3vrTMas57aN0XNObe4sXX2gKuUWvFy95jMn1BaaFhhyNccbbLWT7St000-C992w-jH5goZibMAeUnJh01CzWjslHO/s200/download.png" width="200" /></a></div>
An example project and a basic guide showing how to run Django/Celery on Heroku.<br />
<h3 style="text-align: left;">
Basic requirements</h3>
First of all, let's actually set up a typical Django project for this. We would need <b><a href="https://virtualenvwrapper.readthedocs.io/en/latest/" rel="nofollow" target="_blank">virtualenvwrapper</a> </b>for that. One could use any other particular method. I prefer this one.<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span><span style="color: #007020;">cd </span>dev
<span style="color: #bb60d5;">$ </span>mkvirtualenv dch
<span style="color: #666666;">(</span>dch<span style="color: #666666;">)</span> <span style="color: #bb60d5;">$ </span>pip install django
<span style="color: #666666;">(</span>dch<span style="color: #666666;">)</span> <span style="color: #bb60d5;">$ </span>django-admin startproject djheroku
<span style="color: #666666;">(</span>dch<span style="color: #666666;">)</span> <span style="color: #bb60d5;">$ </span><span style="color: #007020;">cd </span>djheroku
<span style="color: #60a0b0; font-style: italic;"># Make sure is working:</span>
<span style="color: #666666;">(</span>dch<span style="color: #666666;">)</span> <span style="color: #bb60d5;">$ </span>./manage.py runserver</pre>
</div>
From now I will consider working on a terminal with this <b>(dch)</b> environment on.<br />
<h3 style="text-align: left;">
Heroku hosting setup</h3>
We would need our project set up for heroku python server. The docs live <a href="https://devcenter.heroku.com/articles/getting-started-with-python" rel="nofollow" target="_blank">HERE</a>, as for moment of this guide writing. One would need to follow and setup a basic heroku project. I will not stop here rewriting official guide as it is good enough.<br />
<h3 style="text-align: left;">
Installing celery</h3>
Assuming we have a basic django dyno at heroku here we will continue.<br />
Now let's install Celery and add it to our requirements list (as we had just started, let's just overwrite <b>requirements.txt</b> here):<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>pip install <span style="color: #4070a0;">'celery[redis]'</span>
<span style="color: #bb60d5;">$ </span>pip freeze > requirements.txt</pre>
</div>
Let's touch our <b>settings.py</b> adding the following snippet:<br />
And include <b>"djcelery"</b> into <b>INSTALLED_APPS</b> tuple.<br />
<h3 style="text-align: left;">
Redis broker </h3>
Another option would be a Redis-based broker. AMQP is great, but three connections are barely enough - it's a really tight limitation. RedisToGo addon allows for 10 connections, so we may consider using it instead. Both RabbitMQ and Redis brokers are considered stable and fully featured. Let's install the addon and Python module for Redis:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="border: 1px solid rgb(255, 0, 0);">$</span> heroku addons:add rediscloud
Adding rediscloud on happy<span style="color: #666666;">-</span>holliday<span style="color: #666666;">-</span><span style="color: #40a070;">1467.</span><span style="color: #666666;">..</span> done, v10 (free)
Use <span style="border: 1px solid rgb(255, 0, 0);">`</span>heroku addons:docs rediscloud<span style="border: 1px solid rgb(255, 0, 0);">`</span> to view documentation<span style="color: #666666;">.</span>
<span style="border: 1px solid rgb(255, 0, 0);">$</span> echo <span style="color: #4070a0;">'redis==2.10.3'</span> <span style="color: #666666;">>></span> requirements<span style="color: #666666;">.</span>txt
<span style="border: 1px solid rgb(255, 0, 0);">$</span> pip install redis<span style="color: #666666;">==</span><span style="color: #40a070;">2.10</span><span style="color: #666666;">.</span><span style="color: #40a070;">3</span></pre>
</div>
Now we need to add certain settings to configure settings in Django project:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">BROKER_URL</span> <span style="color: #666666;">=</span> <span style="color: #bb60d5;">BROKER_URL</span> <span style="color: #666666;">=</span> os.environ.get<span style="color: #666666;">(</span><span style="color: #4070a0;">"REDISCLOUD_URL"</span>, <span style="color: #4070a0;">"django://"</span><span style="color: #666666;">)</span>
<span style="color: #bb60d5;">BROKER_POOL_LIMIT</span> <span style="color: #666666;">=</span> 1
<span style="color: #bb60d5;">BROKER_CONNECTION_MAX_RETRIES</span> <span style="color: #666666;">=</span> None
<span style="color: #bb60d5;">CELERY_TASK_SERIALIZER</span> <span style="color: #666666;">=</span> <span style="color: #4070a0;">"json"</span>
<span style="color: #bb60d5;">CELERY_ACCEPT_CONTENT</span> <span style="color: #666666;">=</span> <span style="color: #666666;">[</span><span style="color: #4070a0;">"json"</span>, <span style="color: #4070a0;">"msgpack"</span><span style="color: #666666;">]</span>
<span style="color: #bb60d5;">CELERYBEAT_SCHEDULER</span> <span style="color: #666666;">=</span> <span style="color: #4070a0;">'djcelery.schedulers.DatabaseScheduler'</span>
<span style="color: #007020; font-weight: bold;">if </span><span style="color: #bb60d5;">BROKER_URL</span> <span style="color: #666666;">==</span> <span style="color: #4070a0;">"django://"</span>:
INSTALLED_APPS +<span style="color: #666666;">=</span> <span style="color: #666666;">(</span><span style="color: #4070a0;">"kombu.transport.django"</span>,<span style="color: #666666;">)</span>
<span style="color: #bb60d5;">BROKER_TRANSPORT_OPTIONS</span> <span style="color: #666666;">=</span> <span style="color: #666666;">{</span>
<span style="color: #4070a0;">"max_connections"</span>: 2,
<span style="color: #666666;">}</span>
<span style="color: #bb60d5;">BROKER_POOL_LIMIT</span> <span style="color: #666666;">=</span> None</pre>
</div>
We need to set the <b>REDISCLOUD_URL</b> after this is done in heroku app settings. (At the hosting control panel.<br />
<h3 style="text-align: left;">
Continue with broker setup </h3>
Let's store our process by doing a commit. And since <b>djcelery</b> app has some models, also apply migrations:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>git add djheroku/settings.py requirements.txt
<span style="color: #bb60d5;">$ </span>git commit -m <span style="color: #4070a0;">'Add Celery support'</span>
<span style="color: #666666;">[</span>master 43afd41<span style="color: #666666;">]</span> Add Celery support
2 files changed, 46 insertions<span style="color: #666666;">(</span>+<span style="color: #666666;">)</span>
<span style="color: #bb60d5;">$ </span>git push heroku master
...
-----> Installing dependencies with pip
Installing collected packages: amqp, anyjson, billiard, celery, django-celery, kombu, pytz
...
<span style="color: #bb60d5;">$ </span>heroku run python manage.py migrate
...</pre>
</div>
<h3 style="text-align: left;">
Staying in a free tier with a single dyno </h3>
To save money on the start by not using the second dyno at all. From a <b>Procfile</b> we'll start a process manager that would run multiple processes for us. This just can't scale at all (any attempts to scale would give unpredictable results), but we could easily revise this at a later time. The only issue is, since this will be the web dyno, it will be killed ("sleeping" in Heroku terms) if no requests happen within one hour. Since we have a scheduler, we could probably work around this limitation by sending an HTTP request to ourselves, though. Let's consider we've added Celery worker to <b>Procfile</b> using one of the above methods. In this tutorial I'll stick to Python-only, <a href="https://github.com/nickstenning/honcho" rel="nofollow" target="_blank">Honcho</a>.<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span><span style="color: #007020;">echo</span> <span style="color: #4070a0;">'honcho==1.0.1'</span> >> requirements.txt
<span style="color: #bb60d5;">$ </span>pip install <span style="color: #bb60d5;">honcho</span><span style="color: #666666;">==</span>1.0.1</pre>
</div>
We'll need a workers declared in a Procfile. Then we'll swap the file with a "proxy" one:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>git mv Procfile Procfile.real</pre>
</div>
And change the <b>Procfile.real </b>with:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #4070a0;">web</span><span style="color: #666666;">:</span> <span style="color: #4070a0;">gunicorn helloworld.wsgi --log-file -</span>
<span style="color: #4070a0;">worker</span><span style="color: #666666;">:</span> <span style="color: #4070a0;">python manage.py celery worker --loglevel=info</span>
<span style="color: #4070a0;">beat</span><span style="color: #666666;">:</span> <span style="color: #4070a0;">python manage.py celery beat --loglevel=info</span></pre>
</div>
This Original Procfile (that is executed by heroku) should look like this:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #4070a0;">web</span><span style="color: #666666;">:</span> <span style="color: #4070a0;">env > .env; env PYTHONUNBUFFERED=true honcho start -f Procfile.real 2>&1</span></pre>
</div>
Now we should commit and push to heroku and connect to heroku loggin to check if everything went well:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>heroku logs -t | cut -c34-</pre>
</div>
Another downside of this hack is messy logging. But it's the prices of a "free" compromise.<br />
<h3 style="text-align: left;">
Celery essentials</h3>
Now, we're done with the setup so let's actually write some tasks and their management code. First of all, let's create <b>celery.py</b>. A simple task that'd fetch an URL and return a status code would look as following:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;">import os
from celery import Celery
from django.conf import settings
<span style="color: #60a0b0; font-style: italic;"># Lets the celery command line program know where project settings are.</span>
os.environ.setdefault<span style="color: #666666;">(</span><span style="color: #4070a0;">'DJANGO_SETTINGS_MODULE'</span>, <span style="color: #4070a0;">'djheroku.settings'</span><span style="color: #666666;">)</span>
<span style="color: #60a0b0; font-style: italic;"># Creates the instance of the Celery app.</span>
<span style="color: #bb60d5;">app</span> <span style="color: #666666;">=</span> Celery<span style="color: #666666;">(</span><span style="color: #4070a0;">'djheroku'</span><span style="color: #666666;">)</span>
app.config_from_object<span style="color: #666666;">(</span><span style="color: #4070a0;">'djheroku:settings'</span>, <span style="color: #bb60d5;">namespace</span><span style="color: #666666;">=</span><span style="color: #4070a0;">'CELERY'</span><span style="color: #666666;">)</span>
<span style="color: #60a0b0; font-style: italic;"># Set up autodiscovery of tasks in the INSTALLED_APPS.</span>
app.autodiscover_tasks<span style="color: #666666;">(</span>lambda: settings.INSTALLED_APPS<span style="color: #666666;">)</span>
<span style="color: #007020; font-weight: bold;">if </span><span style="color: #bb60d5;">__name__</span> <span style="color: #666666;">==</span> <span style="color: #4070a0;">'__main__'</span>:
app.start<span style="color: #666666;">()</span></pre>
</div>
Now we have a command file to running celery on heroku server dyno. Next step is to add a sample task in a file called <b>tasks.py. </b>It will be auto-collected by celery:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;">from celery import task
@task<span style="color: #666666;">()</span>
def echoe<span style="color: #666666;">()</span>:
<span style="color: #4070a0;">"""</span>
<span style="color: #4070a0;"> A simple task that echoes a Hello World! text to celery console.</span>
<span style="color: #4070a0;"> """</span>
print<span style="color: #666666;">(</span><span style="color: #4070a0;">'Hello World!'</span><span style="color: #666666;">)</span></pre>
</div>
<h3 style="text-align: left;">
Testing stuff</h3>
We can now test this locally by running our server on one terminal instance:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>./manage.py runserver 0.0.0.0:8000</pre>
</div>
And a sample celery console with built in beat process as a debug purpose worker:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>celery worker --loglevel<span style="color: #666666;">=</span>info --beat</pre>
</div>
Both those terminals instances will emulate a working heroku environment that we have just created.<br />
Now we can trigger our sample script:<br />
<div style="background: rgb(240, 240, 240); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #bb60d5;">$ </span>celery call echoe</pre>
</div>
This will trigger a task and put into celery beat queue. We can observe it's execution after some time passed on the celery worker console.<br />
That's basically it.<br />
Time to commit our changes and push to heroku.<br />
<br />
Here is a git repository: <a href="https://github.com/garmoncheg/djheroku" rel="nofollow" target="_blank">https://github.com/garmoncheg/djheroku</a><br />
<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-67168035004622013442018-04-27T20:58:00.004+03:002018-04-27T20:58:55.568+03:00SQLAlchemy (Flask) count model instances by unique values<div dir="ltr" style="text-align: left;" trbidi="on">
One comes to a task that has to do with counting items in a database. We will describe the right approach here. Despite being so obvious I did not find much of the docs for junior developers to watch and learn. Here is a sample task and solution:<br />Let's assume we have a model like so:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration-line: underline;">Cycle</span><span style="color: #d0d0d0;">(db.Model):</span>
<span style="color: #24909d;">id</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">db.Column(db.Integer,</span> <span style="color: #d0d0d0;">primary_key=</span><span style="color: #24909d;">True</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">object_id</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">db.Column(db.String,</span> <span style="color: #d0d0d0;">nullable=</span><span style="color: #24909d;">False</span><span style="color: #d0d0d0;">)</span></pre>
</div>
Sample date populated into it will be:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique1'</span>
<span style="color: #d0d0d0;">},</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">2</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique1'</span>
<span style="color: #d0d0d0;">},</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">3</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique2'</span>
<span style="color: #d0d0d0;">},</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">4</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique2'</span>
<span style="color: #d0d0d0;">},</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">5</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique2'</span>
<span style="color: #d0d0d0;">},</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #24909d;">id</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">6</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">object_id:</span> <span style="color: #ed9d13;">'unique3'</span>
<span style="color: #d0d0d0;">}</span></pre>
</div>
We need to count unique model instances with same <span style="background-color: #cccccc;">object_id</span>. To achieve this relatively simple task one would go straightforward. E.g. Fetch all the <span style="background-color: #cccccc;">Cycle</span> instances with a simple query and then iterate through them via <span style="background-color: #cccccc;">for</span> cycle. Looks like so:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">objects</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">Cycle.query.all()</span>
<span style="color: #d0d0d0;">cycles_unique</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">{}</span>
<span style="color: #6ab825; font-weight: bold;">for</span> <span style="color: #24909d;">object</span> <span style="color: #6ab825; font-weight: bold;">in</span> <span style="color: #d0d0d0;">objects:</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #24909d;">object</span><span style="color: #d0d0d0;">.object_id</span> <span style="color: #6ab825; font-weight: bold;">in</span> <span style="color: #d0d0d0;">cycles_unique.items():</span>
<span style="color: #d0d0d0;">cycles_unique[</span><span style="color: #24909d;">object</span><span style="color: #d0d0d0;">.object_id]</span> <span style="color: #d0d0d0;">+=</span> <span style="color: #3677a9;">1</span>
<span style="color: #6ab825; font-weight: bold;">else</span><span style="color: #d0d0d0;">:</span>
<span style="color: #d0d0d0;">cycles_unique[</span><span style="color: #24909d;">object</span><span style="color: #d0d0d0;">.object_id]</span> <span style="color: #d0d0d0;">=</span> <span style="color: #3677a9;">1</span>
<span style="color: #6ab825; font-weight: bold;">print</span><span style="color: #d0d0d0;">(cycles_unique)</span></pre>
</div>
The output would be like so:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">{</span>
<span style="color: #ed9d13;">'unique1'</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">2</span><span style="color: #d0d0d0;">,</span>
<span style="color: #ed9d13;">'unique2'</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">3</span><span style="color: #d0d0d0;">,</span>
<span style="color: #ed9d13;">'unique3'</span><span style="color: #d0d0d0;">:</span> <span style="color: #3677a9;">1</span>
<span style="color: #d0d0d0;">}</span></pre>
</div>
Job done. All ok. HOWEVER! Imagine this database column would grow to big sizes. E.g. Those Cycles are 1 000 000 records. It is not a rare situation in coding world. Called - BigData ;)<br /><br />
We have a problem with cycle like so. Flask or whatever gear i used behind those models would need to load all those 1 million records into memory and then process them one by one. Even with fast server it will be not an easy task in the scope of rendering a webpage. User might wait quite long for the answer.<br />
<br />
Making it faster means doing this count on a DB side. SQL databases are built specially for tasks like so and will do much much better at this. Incomparable to code written above.<br />
<br />
Proper implementation would be by using SQL syntax and handling on a DB side. Code will use a query that counts unique records with that one particular field. Looks like so:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration-line: underline;">sqlalchemy</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">func</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration-line: underline;">sqlalchemy.sql</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">label</span>
<span style="color: #d0d0d0;">session.query(</span>
<span style="color: #d0d0d0;">label(</span><span style="color: #ed9d13;">'object_id'</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">Crop.object_id),</span> <span style="color: #d0d0d0;">func.count(Cycle.object_id)</span>
<span style="color: #d0d0d0;">).group_by(Cycle.object_id).all()</span></pre>
</div>
This will output the data similar to the above. However output is with numbers of Long type (<a href="https://docs.python.org/2/library/functions.html#long" target="_blank">Python Long</a>).<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">[(</span><span style="color: #ed9d13;">'unique1'</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">2L</span><span style="color: #d0d0d0;">),</span> <span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'unique2'</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">3L</span><span style="color: #d0d0d0;">),</span> <span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'unique3'</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">1L</span><span style="color: #d0d0d0;">)]</span></pre>
</div>
This is basically how to solve this task properly with SQL Alchemy and Flask models.<br />Hope it helps someone to write more reliable and better code.</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-47762526623917928292018-04-21T16:50:00.003+03:002018-04-21T16:50:36.583+03:00PostgreSQL DB with pgAdmin4 access through SSH tunnel<div dir="ltr" style="text-align: left;" trbidi="on">
Despite using console most of the time I have a preference to edit PostgreSQL databases through UI. Especially when it comes to remote side. Usually one can access this through <span style="background-color: black; color: #d1d1d1;">$ psql</span> command. However this tends to writing raw SQL queries and a lot of typing in overall.<br />
Here is a way to do it with UI. First one needs to make a tunnel.Command is fairly simple:<br />
<div style="font-family: sans-serif; overflow: scroll; width: 650px;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">ssh <span style="color: #d2cd86;">-</span>fNg <span style="color: #d2cd86;">-</span>L <span style="color: #008c00;">5555</span><span style="color: #b060b0;">:</span>localhost<span style="color: #b060b0;">:</span><span style="color: #008c00;">5432</span> <span style="color: #b060b0;">{</span>username<span style="color: #b060b0;">}</span><span style="color: #d2cd86;">@</span><span style="color: #b060b0;">{</span>host<span style="color: #d2cd86;">.</span>com<span style="color: #b060b0;">}</span></pre>
</div>
One has a tunnel afterwards. This command opens a SSH connection in the background mapping your local port 5555 to your server’s port 5432 (Postgres’ default port). To understand one can observe the meaning of the flags via <span style="background-color: black; color: #d1d1d1;">$ man ssh</span> to see what each of these flags doing.<br />
It can be accessed via localhost tools like pgAdmin4 at localhost and port 5555<br />DB config would look like so:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLXl_9SDolz49BnGSJ0aulDXmYLQs2RZUiHWMY5xqURlELreVQWdAdNqM02cWr_msgbMZQplCu9Evy6WpHhNBgBSAZmkvnqz4vtdi08Fyvpb0YBgmrAmAfHvtxEj2I8cYqS0LCxRlqTDeo/s1600/pg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1138" data-original-width="1042" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLXl_9SDolz49BnGSJ0aulDXmYLQs2RZUiHWMY5xqURlELreVQWdAdNqM02cWr_msgbMZQplCu9Evy6WpHhNBgBSAZmkvnqz4vtdi08Fyvpb0YBgmrAmAfHvtxEj2I8cYqS0LCxRlqTDeo/s640/pg.png" width="586" /></a></div>
</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-91366111697713809492018-03-08T16:14:00.003+02:002018-03-08T16:14:30.510+02:00Run Flask with Debug in PyCharm<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq_ejaY3NRe07z-1nnsl8NBTZfU1d-NgnD_OCNXX3lCJ5PyKkD9Adrmty3q5L2rXjTcuiesYQrJUrhC5tNMgavz6u2XqjzdYQ7h5Dgx9CL7Y5NieLGOYwlFWZL-kCMK18J57COeqC5LA-s/s1600/FlaskLogo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="340" data-original-width="340" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq_ejaY3NRe07z-1nnsl8NBTZfU1d-NgnD_OCNXX3lCJ5PyKkD9Adrmty3q5L2rXjTcuiesYQrJUrhC5tNMgavz6u2XqjzdYQ7h5Dgx9CL7Y5NieLGOYwlFWZL-kCMK18J57COeqC5LA-s/s200/FlaskLogo.png" width="200" /></a></div>
I have gotten to setting UP a Flask environment for a project recently. Was completely puzzled by how to run this. I have used to running Django project with python manage.py script. This means pointing out a PyCharm interpreter into a certain point of entry, that is also a .py file also.<br /><br />
In flask way of starting things there is another approach however. Here it is in <a href="http://flask.pocoo.org/docs/0.12/cli/#basic-usage" target="_blank">Flask Docs.</a><br />
It states to set a variable <span style="background-color: #f3f3f3;"><i>FLASK_APP</i></span> and then run a <span style="background-color: #f3f3f3;"><i>flask run</i></span> command. This will confuse running a python script way of a project being run. Thus to fix this one needs to set a path to flask binary file. It usually is within a virtual environment binary directory, place where your python interpreter resides.<br /><br />So to set debugging one needs to set path to script binary one needs:<br />
<ul style="text-align: left;">
<li>Script: <i style="background-color: #f3f3f3;">/path/to/env/bin/flask</i></li>
<li>Script parameters: <span style="background-color: #f3f3f3;">run</span> </li>
<li>Environment variable <span style="background-color: #f3f3f3;"><i>FLASK_APP=app.py</i></span></li>
<li>Environment variable <span style="background-color: #f3f3f3;"><i>FLASK_DEBUG=True</i></span></li>
<li>Set working directory back to your app path (It changes automatically according to script being set)</li>
</ul>
<div>
So my will look something like this:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA5ODgGICdbU3hoacvMeT6SVHonFKKj6zMJ6dnbFwxpkOoHOFGfcyltwYvDWISDRe_GoUtA3k2XHDIAjggVFFCzGsAOb76xcYQkd8ljwlqjqsFvYV0vlkLK2eAISrEWJXHJzmuMSyXbfWj/s1600/Run%253ADebug+Configurations+2018-03-08+16-05-24.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1069" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA5ODgGICdbU3hoacvMeT6SVHonFKKj6zMJ6dnbFwxpkOoHOFGfcyltwYvDWISDRe_GoUtA3k2XHDIAjggVFFCzGsAOb76xcYQkd8ljwlqjqsFvYV0vlkLK2eAISrEWJXHJzmuMSyXbfWj/s640/Run%253ADebug+Configurations+2018-03-08+16-05-24.png" width="640" /></a></div>
</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-12733511179343575642018-02-28T14:41:00.001+02:002018-02-28T14:46:39.211+02:00Promise -fication of JS calls.<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwjdw-ADH-7rRq8_54lQp5nHAiBAwO5Uuc-bzQ8osUIO9qatge_pcMVcOzEs233w6g-jbIXYyCqQ5BgFVdM1O41KZrbWO3lRoy11a9Rn8xUA_RrLW5E3_3r3gdvLPt7qV3R3qUwsCxCFmv/s1600/promise.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="236" data-original-width="504" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwjdw-ADH-7rRq8_54lQp5nHAiBAwO5Uuc-bzQ8osUIO9qatge_pcMVcOzEs233w6g-jbIXYyCqQ5BgFVdM1O41KZrbWO3lRoy11a9Rn8xUA_RrLW5E3_3r3gdvLPt7qV3R3qUwsCxCFmv/s200/promise.png" width="200" /></a></div>
Found a new pattern to use recently that is called Promise. I really like the way ES6/7 brings new thinking patterns into life nowdays. Here is Promise used instead of old pattern.<br />
<br />
It was to give JS method a callback function. This splitting code and making a lot of possibilities for error to come out in this place.<br />
<br />
One would write old times according to <a href="https://developer.mozilla.org/en-US/docs/Glossary/Callback_function" target="_blank">MDN</a>:<br />
<div style="background: rgb(39, 40, 34); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #66d9ef;">function</span> <span style="color: #a6e22e;">greeting</span><span style="color: #f8f8f2;">(</span><span style="color: #a6e22e;">name</span><span style="color: #f8f8f2;">)</span> <span style="color: #f8f8f2;">{</span>
<span style="color: #a6e22e;">alert</span><span style="color: #f8f8f2;">(</span><span style="color: #e6db74;">'Hello '</span> <span style="color: #f92672;">+</span> <span style="color: #a6e22e;">name</span><span style="color: #f8f8f2;">);</span>
<span style="color: #f8f8f2;">}</span>
<span style="color: #66d9ef;">function</span> <span style="color: #a6e22e;">processUserInput</span><span style="color: #f8f8f2;">(</span><span style="color: #a6e22e;">callback</span><span style="color: #f8f8f2;">)</span> <span style="color: #f8f8f2;">{</span>
<span style="color: #66d9ef;">var</span> <span style="color: #a6e22e;">name</span> <span style="color: #f92672;">=</span> <span style="color: #a6e22e;">prompt</span><span style="color: #f8f8f2;">(</span><span style="color: #e6db74;">'Please enter your name.'</span><span style="color: #f8f8f2;">);</span>
<span style="color: #a6e22e;">callback</span><span style="color: #f8f8f2;">(</span><span style="color: #a6e22e;">name</span><span style="color: #f8f8f2;">);</span>
<span style="color: #f8f8f2;">}</span>
<span style="color: #a6e22e;">processUserInput</span><span style="color: #f8f8f2;">(</span><span style="color: #a6e22e;">greeting</span><span style="color: #f8f8f2;">);</span></pre>
</div>
And now it is made with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" target="_blank">Promise</a> pattern like so:<br />
<div style="background: rgb(39, 40, 34); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #66d9ef;">let</span> <span style="color: #a6e22e;">promise</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #a6e22e;">Promise</span><span style="color: #f8f8f2;">((</span><span style="color: #a6e22e;">resolve</span><span style="color: #f8f8f2;">,</span> <span style="color: #a6e22e;">reject</span><span style="color: #f8f8f2;">)</span> <span style="color: #f92672;">=></span> <span style="color: #f8f8f2;">{</span>
<span style="color: #a6e22e;">resolve</span><span style="color: #f8f8f2;">(</span><span style="color: #a6e22e;">prompt</span><span style="color: #f8f8f2;">(</span><span style="color: #e6db74;">'Please enter your name.'</span><span style="color: #f8f8f2;">));</span>
<span style="color: #f8f8f2;">});</span>
<span style="color: #a6e22e;">promise</span><span style="color: #f8f8f2;">.</span><span style="color: #a6e22e;">then</span><span style="color: #f8f8f2;">((</span><span style="color: #a6e22e;">name</span><span style="color: #f8f8f2;">)</span> <span style="color: #f92672;">=></span> <span style="color: #f8f8f2;">{</span>
<span style="color: #a6e22e;">alert</span><span style="color: #f8f8f2;">(</span><span style="color: #e6db74;">'Hello '</span> <span style="color: #f92672;">+</span> <span style="color: #a6e22e;">name</span><span style="color: #f8f8f2;">);</span>
<span style="color: #f8f8f2;">});</span></pre>
</div>
In general and briefly this now helps to avoid 'callback hell' with functions passed as arguments and write asynchronous code a sort of in synchronous manner.<br /><br />This all becomes extra useful upon one having need to load set of data from a different sources. E.g. via several API cals to different url's and react accordingly.<br /><br />
Hail to ES6!</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-76390081724424828172017-06-27T17:42:00.001+03:002017-06-27T17:42:22.010+03:00Vagrant error: * Unknown configuration section 'hostmanager'.<div dir="ltr" style="text-align: left;" trbidi="on">
Sometimes you get a vagrant environment or boilerplate with a Vagrantfile config in there and do a vagrant up command. And see some errors. like this:<br />
<pre style="background: #001800; color: red;">There are errors in the configuration of <span style="color: red; font-weight: bold;">this</span> machine<span style="color: red;">.</span> Please fix
the following errors and try again<span style="color: red;">:</span>
<span style="color: red;">Vagrant:</span>
<span style="color: red;">* Unknown configuration section 'hostmanager'.</span></pre>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Andale Mono'; color: #c33720; background-color: #000000; background-color: rgba(0, 0, 0, 0.9)}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Andale Mono'; color: #28fe14; background-color: #000000; background-color: rgba(0, 0, 0, 0.9); min-height: 14.0px}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
To fix this one needs:<br />
<div class="p1">
<div style="font-family: sans-serif; overflow: scroll; width: 603px;">
<pre style="background: rgb(0, 24, 0); color: #55cc66;">$ vagrant plugin install vagrant<span style="color: #808030;">-</span>hostmanager
Installing the <span style="color: maroon;">'</span><span style="color: #cc5555;">vagrant-hostmanager</span><span style="color: maroon;">'</span> plugin<span style="color: #808030;">.</span> This can take a few minutes<span style="color: #808030;">.</span><span style="color: #808030;">.</span><span style="color: #808030;">.</span>
Fetching<span style="color: #808030;">:</span> vagrant<span style="color: #808030;">-</span>hostmanager<span style="color: #808030;">-</span><span style="color: #778c77;">1.8</span><span style="color: #778c77;">.6</span><span style="color: #778c77;">.</span>gem <span style="color: #808030;">(</span><span style="color: #778c77;">100</span><span style="color: #808030;">%</span><span style="color: #808030;">)</span>
Installed the plugin <span style="color: maroon;">'</span><span style="color: #cc5555;">vagrant-hostmanager (1.8.6)</span><span style="color: maroon;">'</span><span style="color: #808030;">!</span></pre>
</div>
</div>
So command to fix this as follows:<br />
<span style="background-color: rgba(0 , 0 , 0 , 0.9); color: #28fe14; font-family: "andale mono"; font-size: 12px;">vagrant plugin install vagrant-hostmanager</span></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-20828572336790063882017-03-06T16:38:00.001+02:002017-03-06T16:40:09.409+02:00POP3 Mock (Fake) server using python script<div dir="ltr" style="text-align: left;" trbidi="on">
Having a need in POP3 server for my debugging purposes I have used this script.<br />
Letting it to be here in case of anyone would need to do something similar.<br />
Usage is:<br />
<b>$ python pypopper.py 110 email_file.eml</b><br />
<br />
<pre style="background: #001800; color: #55cc66;"><span style="color: maroon;">"</span><span style="color: maroon;">"</span><span style="color: maroon;">"</span><span style="color: #cc5555;">pypopper: a file-based pop3 serve</span><span style="background: #dd0000; color: white; font-style: italic; font-weight: bold;">r</span><span style="color: #cc5555;"></span>
<span style="color: #cc5555;"></span>
<span style="color: #cc5555;">Useage</span><span style="background: #dd0000; color: white; font-style: italic; font-weight: bold;">:</span><span style="color: #cc5555;"></span>
<span style="color: #cc5555;"> python pypopper.py <port> <path_to_message_file</span><span style="background: #dd0000; color: white; font-style: italic; font-weight: bold;">></span><span style="color: #cc5555;"></span>
<span style="color: maroon;">"</span><span style="color: maroon;">"</span><span style="color: maroon;">"</span>
<span style="color: #508050; font-weight: bold;">import</span> logging
<span style="color: #508050; font-weight: bold;">import</span> os
<span style="color: #508050; font-weight: bold;">import</span> <span style="color: #400000;">socket</span>
<span style="color: #508050; font-weight: bold;">import</span> sys
<span style="color: #508050; font-weight: bold;">import</span> traceback
logging<span style="color: #808030;">.</span>basicConfig<span style="color: #808030;">(</span>format<span style="color: #808030;">=</span><span style="color: maroon;">"</span><span style="color: #cc5555;">%(name)s %(levelname)s - %(message)s</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #603000;">log</span> <span style="color: #808030;">=</span> logging<span style="color: #808030;">.</span>getLogger<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">pypopper</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
log<span style="color: #808030;">.</span>setLevel<span style="color: #808030;">(</span>logging<span style="color: #808030;">.</span>INFO<span style="color: #808030;">)</span>
class ChatterboxConnection<span style="color: #808030;">(</span>object<span style="color: #808030;">)</span><span style="color: purple;">:</span>
END <span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: maroon;">"</span>
def __init__<span style="color: #808030;">(</span>self<span style="color: #808030;">,</span> conn<span style="color: #808030;">)</span><span style="color: purple;">:</span>
self<span style="color: #808030;">.</span>conn <span style="color: #808030;">=</span> conn
def __getattr__<span style="color: #808030;">(</span>self<span style="color: #808030;">,</span> name<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> getattr<span style="color: #808030;">(</span>self<span style="color: #808030;">.</span>conn<span style="color: #808030;">,</span> name<span style="color: #808030;">)</span>
def sendall<span style="color: #808030;">(</span>self<span style="color: #808030;">,</span> data<span style="color: #808030;">,</span> END<span style="color: #808030;">=</span>END<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">if</span> len<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span> <span style="color: #808030;"><</span> <span style="color: #778c77;">50</span><span style="color: purple;">:</span>
log<span style="color: #808030;">.</span>debug<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">send: %r</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> data<span style="color: #808030;">)</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
log<span style="color: #808030;">.</span>debug<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">send: %r...</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> data<span style="color: #808030;">[</span><span style="color: purple;">:</span><span style="color: #778c77;">50</span><span style="color: #808030;">]</span><span style="color: #808030;">)</span>
data <span style="color: #808030;">+</span><span style="color: #808030;">=</span> END
self<span style="color: #808030;">.</span>conn<span style="color: #808030;">.</span>sendall<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span>
def recvall<span style="color: #808030;">(</span>self<span style="color: #808030;">,</span> END<span style="color: #808030;">=</span>END<span style="color: #808030;">)</span><span style="color: purple;">:</span>
data <span style="color: #808030;">=</span> <span style="color: #808030;">[</span><span style="color: #808030;">]</span>
<span style="color: #508050; font-weight: bold;">while</span> True<span style="color: purple;">:</span>
chunk <span style="color: #808030;">=</span> self<span style="color: #808030;">.</span>conn<span style="color: #808030;">.</span><span style="color: #400000;">recv</span><span style="color: #808030;">(</span><span style="color: #778c77;">4096</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">if</span> END in chunk<span style="color: purple;">:</span>
data<span style="color: #808030;">.</span>append<span style="color: #808030;">(</span>chunk<span style="color: #808030;">[</span><span style="color: purple;">:</span>chunk<span style="color: #808030;">.</span>index<span style="color: #808030;">(</span>END<span style="color: #808030;">)</span><span style="color: #808030;">]</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">break</span>
data<span style="color: #808030;">.</span>append<span style="color: #808030;">(</span>chunk<span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">if</span> len<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span> <span style="color: #808030;">></span> <span style="color: #778c77;">1</span><span style="color: purple;">:</span>
pair <span style="color: #808030;">=</span> data<span style="color: #808030;">[</span><span style="color: #808030;">-</span><span style="color: #778c77;">2</span><span style="color: #808030;">]</span> <span style="color: #808030;">+</span> data<span style="color: #808030;">[</span><span style="color: #808030;">-</span><span style="color: #778c77;">1</span><span style="color: #808030;">]</span>
<span style="color: #508050; font-weight: bold;">if</span> END in pair<span style="color: purple;">:</span>
data<span style="color: #808030;">[</span><span style="color: #808030;">-</span><span style="color: #778c77;">2</span><span style="color: #808030;">]</span> <span style="color: #808030;">=</span> pair<span style="color: #808030;">[</span><span style="color: purple;">:</span>pair<span style="color: #808030;">.</span>index<span style="color: #808030;">(</span>END<span style="color: #808030;">)</span><span style="color: #808030;">]</span>
data<span style="color: #808030;">.</span>pop<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">break</span>
log<span style="color: #808030;">.</span>debug<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">recv: %r</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> <span style="color: maroon;">"</span><span style="color: maroon;">"</span><span style="color: #808030;">.</span>join<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: maroon;">"</span><span style="color: #808030;">.</span>join<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span>
class Message<span style="color: #808030;">(</span>object<span style="color: #808030;">)</span><span style="color: purple;">:</span>
def __init__<span style="color: #808030;">(</span>self<span style="color: #808030;">,</span> filename<span style="color: #808030;">)</span><span style="color: purple;">:</span>
msg <span style="color: #808030;">=</span> open<span style="color: #808030;">(</span>filename<span style="color: #808030;">,</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">r</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #e34adc;"> try:</span>
self<span style="color: #808030;">.</span>data <span style="color: #808030;">=</span> data <span style="color: #808030;">=</span> msg<span style="color: #808030;">.</span>read<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
self<span style="color: #808030;">.</span>size <span style="color: #808030;">=</span> len<span style="color: #808030;">(</span>data<span style="color: #808030;">)</span>
self<span style="color: #808030;">.</span>top<span style="color: #808030;">,</span> bot <span style="color: #808030;">=</span> data<span style="color: #808030;">.</span>split<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> <span style="color: #778c77;">1</span><span style="color: #808030;">)</span>
self<span style="color: #808030;">.</span>bot <span style="color: #808030;">=</span> bot<span style="color: #808030;">.</span>split<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">finally</span><span style="color: #e34adc;">:</span>
msg<span style="color: #808030;">.</span>close<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
def handleUser<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK user accepted</span><span style="color: maroon;">"</span>
def handlePass<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK pass accepted</span><span style="color: maroon;">"</span>
def handleStat<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK 1 </span><span style="color: #007997;">%i</span><span style="color: maroon;">"</span> <span style="color: #808030;">%</span> msg<span style="color: #808030;">.</span>size
def handleList<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK 1 messages (</span><span style="color: #007997;">%i</span><span style="color: #cc5555;"> octets)</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #cc5555;">1 </span><span style="color: #007997;">%i</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #cc5555;">.</span><span style="color: maroon;">"</span> <span style="color: #808030;">%</span> <span style="color: #808030;">(</span>msg<span style="color: #808030;">.</span>size<span style="color: #808030;">,</span> msg<span style="color: #808030;">.</span>size<span style="color: #808030;">)</span>
def handleTop<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
cmd<span style="color: #808030;">,</span> num<span style="color: #808030;">,</span> lines <span style="color: #808030;">=</span> data<span style="color: #808030;">.</span>split<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
assert num <span style="color: #808030;">=</span><span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">1</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">unknown message number: </span><span style="color: #007997;">%s</span><span style="color: maroon;">"</span> <span style="color: #808030;">%</span> num
lines <span style="color: #808030;">=</span> <span style="color: #508050; font-weight: bold;">int</span><span style="color: #808030;">(</span>lines<span style="color: #808030;">)</span>
text <span style="color: #808030;">=</span> msg<span style="color: #808030;">.</span>top <span style="color: #808030;">+</span> <span style="color: maroon;">"</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: maroon;">"</span> <span style="color: #808030;">+</span> <span style="color: maroon;">"</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: maroon;">"</span><span style="color: #808030;">.</span>join<span style="color: #808030;">(</span>msg<span style="color: #808030;">.</span>bot<span style="color: #808030;">[</span><span style="color: purple;">:</span>lines<span style="color: #808030;">]</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK top of message follows</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #007997;">%s</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #cc5555;">.</span><span style="color: maroon;">"</span> <span style="color: #808030;">%</span> text
def handleRetr<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
log<span style="color: #808030;">.</span>info<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">message sent</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK </span><span style="color: #007997;">%i</span><span style="color: #cc5555;"> octets</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #007997;">%s</span><span style="color: #aa3333; font-weight: bold;">\r</span><span style="color: #aa3333; font-weight: bold;">\n</span><span style="color: #cc5555;">.</span><span style="color: maroon;">"</span> <span style="color: #808030;">%</span> <span style="color: #808030;">(</span>msg<span style="color: #808030;">.</span>size<span style="color: #808030;">,</span> msg<span style="color: #808030;">.</span>data<span style="color: #808030;">)</span>
def handleDele<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK message 1 deleted</span><span style="color: maroon;">"</span>
def handleNoop<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK</span><span style="color: maroon;">"</span>
def handleQuit<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">return</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">+OK pypopper POP3 server signing off</span><span style="color: maroon;">"</span>
dispatch <span style="color: #808030;">=</span> dict<span style="color: #808030;">(</span>
USER<span style="color: #808030;">=</span>handleUser<span style="color: #808030;">,</span>
PASS<span style="color: #808030;">=</span>handlePass<span style="color: #808030;">,</span>
STAT<span style="color: #808030;">=</span>handleStat<span style="color: #808030;">,</span>
LIST<span style="color: #808030;">=</span>handleList<span style="color: #808030;">,</span>
TOP<span style="color: #808030;">=</span>handleTop<span style="color: #808030;">,</span>
RETR<span style="color: #808030;">=</span>handleRetr<span style="color: #808030;">,</span>
DELE<span style="color: #808030;">=</span>handleDele<span style="color: #808030;">,</span>
NOOP<span style="color: #808030;">=</span>handleNoop<span style="color: #808030;">,</span>
QUIT<span style="color: #808030;">=</span>handleQuit<span style="color: #808030;">,</span>
<span style="color: #808030;">)</span>
def serve<span style="color: #808030;">(</span>host<span style="color: #808030;">,</span> port<span style="color: #808030;">,</span> filename<span style="color: #808030;">)</span><span style="color: purple;">:</span>
assert os<span style="color: #808030;">.</span>path<span style="color: #808030;">.</span>exists<span style="color: #808030;">(</span>filename<span style="color: #808030;">)</span>
sock <span style="color: #808030;">=</span> <span style="color: #400000;">socket</span><span style="color: #808030;">.</span><span style="color: #400000;">socket</span><span style="color: #808030;">(</span><span style="color: #400000;">socket</span><span style="color: #808030;">.</span>AF_INET<span style="color: #808030;">,</span> <span style="color: #400000;">socket</span><span style="color: #808030;">.</span>SOCK_STREAM<span style="color: #808030;">)</span>
sock<span style="color: #808030;">.</span><span style="color: #400000;">bind</span><span style="color: #808030;">(</span><span style="color: #808030;">(</span>host<span style="color: #808030;">,</span> port<span style="color: #808030;">)</span><span style="color: #808030;">)</span>
<span style="color: #e34adc;"> try:</span>
<span style="color: #508050; font-weight: bold;">if</span> host<span style="color: purple;">:</span>
hostname <span style="color: #808030;">=</span> host
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
hostname <span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">localhost</span><span style="color: maroon;">"</span>
log<span style="color: #808030;">.</span>info<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">pypopper POP3 serving '</span><span style="color: #007997;">%s</span><span style="color: #cc5555;">' on </span><span style="color: #007997;">%s</span><span style="color: #cc5555;">:</span><span style="color: #007997;">%s</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> filename<span style="color: #808030;">,</span> hostname<span style="color: #808030;">,</span> port<span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">while</span> True<span style="color: purple;">:</span>
sock<span style="color: #808030;">.</span><span style="color: #400000;">listen</span><span style="color: #808030;">(</span><span style="color: #778c77;">1</span><span style="color: #808030;">)</span>
conn<span style="color: #808030;">,</span> addr <span style="color: #808030;">=</span> sock<span style="color: #808030;">.</span>accept<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
log<span style="color: #808030;">.</span>debug<span style="color: #808030;">(</span><span style="background: #dd0000; color: white; font-style: italic; font-weight: bold;">'Connected by %s'</span><span style="color: #808030;">,</span> addr<span style="color: #808030;">)</span>
<span style="color: #e34adc;"> try:</span>
msg <span style="color: #808030;">=</span> Message<span style="color: #808030;">(</span>filename<span style="color: #808030;">)</span>
conn <span style="color: #808030;">=</span> ChatterboxConnection<span style="color: #808030;">(</span>conn<span style="color: #808030;">)</span>
conn<span style="color: #808030;">.</span>sendall<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">+OK pypopper file-based pop3 server ready</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">while</span> True<span style="color: purple;">:</span>
data <span style="color: #808030;">=</span> conn<span style="color: #808030;">.</span>recvall<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
command <span style="color: #808030;">=</span> data<span style="color: #808030;">.</span>split<span style="color: #808030;">(</span>None<span style="color: #808030;">,</span> <span style="color: #778c77;">1</span><span style="color: #808030;">)</span><span style="color: #808030;">[</span><span style="color: #778c77;">0</span><span style="color: #808030;">]</span>
<span style="color: #e34adc;"> try:</span>
cmd <span style="color: #808030;">=</span> dispatch<span style="color: #808030;">[</span>command<span style="color: #808030;">]</span>
except KeyError<span style="color: purple;">:</span>
conn<span style="color: #808030;">.</span>sendall<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">-ERR unknown command</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
conn<span style="color: #808030;">.</span>sendall<span style="color: #808030;">(</span>cmd<span style="color: #808030;">(</span>data<span style="color: #808030;">,</span> msg<span style="color: #808030;">)</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">if</span> cmd is handleQuit<span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">break</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">finally</span><span style="color: #e34adc;">:</span>
conn<span style="color: #808030;">.</span>close<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
msg <span style="color: #808030;">=</span> None
except <span style="color: #808030;">(</span>SystemExit<span style="color: #808030;">,</span> KeyboardInterrupt<span style="color: #808030;">)</span><span style="color: purple;">:</span>
log<span style="color: #808030;">.</span>info<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">pypopper stopped</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span>
except Exception<span style="color: #808030;">,</span> ex<span style="color: purple;">:</span>
log<span style="color: #808030;">.</span>critical<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">fatal error</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> exc_info<span style="color: #808030;">=</span>ex<span style="color: #808030;">)</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">finally</span><span style="color: #e34adc;">:</span>
sock<span style="color: #808030;">.</span><span style="color: #400000;">shutdown</span><span style="color: #808030;">(</span><span style="color: #400000;">socket</span><span style="color: #808030;">.</span>SHUT_RDWR<span style="color: #808030;">)</span>
sock<span style="color: #808030;">.</span>close<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #508050; font-weight: bold;">if</span> __name__ <span style="color: #808030;">=</span><span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">__main__</span><span style="color: maroon;">"</span><span style="color: purple;">:</span>
<span style="color: #508050; font-weight: bold;">if</span> len<span style="color: #808030;">(</span>sys<span style="color: #808030;">.</span>argv<span style="color: #808030;">)</span> <span style="color: #808030;">!</span><span style="color: #808030;">=</span> <span style="color: #778c77;">3</span><span style="color: purple;">:</span>
print <span style="color: maroon;">"</span><span style="color: #cc5555;">USAGE: [<host>:]<port> <path_to_message_file></span><span style="color: maroon;">"</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
_<span style="color: #808030;">,</span> port<span style="color: #808030;">,</span> filename <span style="color: #808030;">=</span> sys<span style="color: #808030;">.</span>argv
<span style="color: #508050; font-weight: bold;">if</span> <span style="color: maroon;">"</span><span style="color: #cc5555;">:</span><span style="color: maroon;">"</span> in port<span style="color: purple;">:</span>
host <span style="color: #808030;">=</span> port<span style="color: #808030;">[</span><span style="color: purple;">:</span>port<span style="color: #808030;">.</span>index<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">:</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: #808030;">]</span>
port <span style="color: #808030;">=</span> port<span style="color: #808030;">[</span>port<span style="color: #808030;">.</span>index<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #cc5555;">:</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span> <span style="color: #808030;">+</span> <span style="color: #778c77;">1</span><span style="color: purple;">:</span><span style="color: #808030;">]</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
host <span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: maroon;">"</span>
<span style="color: #e34adc;"> try:</span>
port <span style="color: #808030;">=</span> <span style="color: #508050; font-weight: bold;">int</span><span style="color: #808030;">(</span>port<span style="color: #808030;">)</span>
except Exception<span style="color: purple;">:</span>
print <span style="color: maroon;">"</span><span style="color: #cc5555;">Unknown port:</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> port
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
<span style="color: #508050; font-weight: bold;">if</span> os<span style="color: #808030;">.</span>path<span style="color: #808030;">.</span>exists<span style="color: #808030;">(</span>filename<span style="color: #808030;">)</span><span style="color: purple;">:</span>
serve<span style="color: #808030;">(</span>host<span style="color: #808030;">,</span> port<span style="color: #808030;">,</span> filename<span style="color: #808030;">)</span>
<span style="color: #e34adc;"> </span><span style="color: #508050; font-weight: bold;">else</span><span style="color: #e34adc;">:</span>
print <span style="color: maroon;">"</span><span style="color: #cc5555;">File not found:</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> filename
</pre>
<div dir="ltr" style="text-align: left;" trbidi="on">
Original code is created by:<span style="background-color: white; color: #555555; font-family: "Open Sans", sans-serif; font-size: x-small;"> </span><a href="http://code.activestate.com/recipes/users/4016391/" style="background: rgb(255, 255, 255); border: 0px; color: #c90e00; font-family: "Open Sans", sans-serif; font-size: 15px; font-stretch: normal; line-height: 25px; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;">Daniel Miller</a></div>
</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-59652320350638910722015-08-31T14:33:00.002+03:002015-08-31T14:33:42.066+03:00Install Docker under Ubuntu 14.04 (Trusty)<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbGPk8QQwLKrZ0jyFlam9ZWTOxDC9filRY19eBaQ55DkPyWycm4jWfzUQqSIwQzUBx3ASjL-JiKoC-zVKVTMdN1gr-EQS7KH-kLd7e6YrzF0o4WdGjlB4w7zbRuoDsxe06OLuMW4K5drDf/s1600/leopard+%25E2%2580%2594+garmon%2540ubuntu%253A+%257E+%25E2%2580%2594+ssh+%25E2%2580%2594+75%25C3%259711+2015-08-31+14-33-03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbGPk8QQwLKrZ0jyFlam9ZWTOxDC9filRY19eBaQ55DkPyWycm4jWfzUQqSIwQzUBx3ASjL-JiKoC-zVKVTMdN1gr-EQS7KH-kLd7e6YrzF0o4WdGjlB4w7zbRuoDsxe06OLuMW4K5drDf/s640/leopard+%25E2%2580%2594+garmon%2540ubuntu%253A+%257E+%25E2%2580%2594+ssh+%25E2%2580%2594+75%25C3%259711+2015-08-31+14-33-03.png" width="640" /></a></div>
Docker supports Ubuntu versions:<br />
<br />
<ul style="text-align: left;">
<li>Ubuntu Vivid 15.04 (64-bit)</li>
<li>Ubuntu Trusty 14.04 (LTS) (64-bit)</li>
<li>Ubuntu Precise 12.04 (LTS) (64-bit)</li>
<li>Ubuntu Raring 13.04 and Saucy 13.10 (64 bit) </li>
</ul>
<br />
For both Vivid and Trusty you need nothing. It will work out of the box. Others will require some modifications. (Updating of some things, like kernel or installing with wget on 13.04)<br />
<br />
1. To install docker from a repository do so:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">sudo apt<span style="color: #d2cd86;">-</span>get update
sudo apt<span style="color: #d2cd86;">-</span>get install docker<span style="color: #d2cd86;">.</span>io
sudo ln <span style="color: #d2cd86;">-</span>sf <span style="color: #d2cd86;">/</span>usr<span style="color: #d2cd86;">/</span>bin<span style="color: #d2cd86;">/</span>docker<span style="color: #d2cd86;">.</span>io <span style="color: #d2cd86;">/</span>usr<span style="color: #d2cd86;">/</span>local<span style="color: #d2cd86;">/</span>bin<span style="color: #d2cd86;">/</span>docker
sudo sed <span style="color: #d2cd86;">-</span>i <span style="background: rgb(221, 0, 0); color: white;">'$acomplete -F _docker docker'</span> <span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>bash_completion<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>docker<span style="color: #d2cd86;">.</span>io</pre>
</div>
<br />
2. Now run it with:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">sudo apt<span style="color: #d2cd86;">-</span>get install lxc<span style="color: #d2cd86;">-</span>docker</pre>
</div>
<br />
3. Make it run on system boot:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">sudo update<span style="color: #d2cd86;">-</span>rc<span style="color: #d2cd86;">.</span>d docker<span style="color: #d2cd86;">.</span>io defaults</pre>
</div>
<br />
4. Ready to go! Run container with an Ubuntu:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">sudo docker run <span style="color: #d2cd86;">-</span>i <span style="color: #d2cd86;">-</span>t ubuntu <span style="color: #d2cd86;">/</span>bin<span style="color: #d2cd86;">/</span>bash</pre>
</div>
<br />
To disconnect, or detach, from the shell without exiting use the escape sequence<b> Ctrl-p + Ctrl-q</b>. </div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-25042100448046516912015-08-27T15:42:00.002+03:002015-08-27T15:42:57.190+03:00Remi and EPEL repositories in CentOS<div dir="ltr" style="text-align: left;" trbidi="on">
There are 2 common repositories that come nowdays for centos. They contain tasty things, while they are absent in official repositories.<br />
<br />
CentOS 5:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">wget http<span style="color: #b060b0;">:</span><span style="color: #9999a9;">//dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm</span>
wget http<span style="color: #b060b0;">:</span><span style="color: #9999a9;">//rpms.famillecollet.com/enterprise/remi-release-5.rpm</span>
sudo rpm <span style="color: #d2cd86;">-</span>Uvh remi<span style="color: #d2cd86;">-</span>release<span style="color: #d2cd86;">-</span><span style="color: #008c00;">5</span><span style="color: #d2cd86;">*</span><span style="color: #d2cd86;">.</span>rpm epel<span style="color: #d2cd86;">-</span>release<span style="color: #d2cd86;">-</span><span style="color: #008c00;">5</span><span style="color: #d2cd86;">*</span><span style="color: #d2cd86;">.</span>rpm</pre>
</div>
<br />CentOS 6:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">wget http<span style="color: #b060b0;">:</span><span style="color: #9999a9;">//dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm</span>
wget http<span style="color: #b060b0;">:</span><span style="color: #9999a9;">//rpms.famillecollet.com/enterprise/remi-release-6.rpm</span>
sudo rpm <span style="color: #d2cd86;">-</span>Uvh remi<span style="color: #d2cd86;">-</span>release<span style="color: #d2cd86;">-</span><span style="color: #008c00;">6</span><span style="color: #d2cd86;">*</span><span style="color: #d2cd86;">.</span>rpm epel<span style="color: #d2cd86;">-</span>release<span style="color: #d2cd86;">-</span><span style="color: #008c00;">6</span><span style="color: #d2cd86;">*</span><span style="color: #d2cd86;">.</span>rpm</pre>
</div>
<br />You can check you are successful like so:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">ls <span style="color: #d2cd86;">-</span><span style="color: #008c00;">1</span> <span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>epel<span style="color: #d2cd86;">*</span> <span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>remi<span style="color: #d2cd86;">.</span>repo
<span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>epel<span style="color: #d2cd86;">.</span>repo
<span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>epel<span style="color: #d2cd86;">-</span>testing<span style="color: #d2cd86;">.</span>repo
<span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>remi<span style="color: #d2cd86;">.</span>repo</pre>
</div>
<br />Now you are only left to activate Remi repository:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">sudo vi <span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>yum<span style="color: #d2cd86;">.</span>repos<span style="color: #d2cd86;">.</span>d<span style="color: #d2cd86;">/</span>remi<span style="color: #d2cd86;">.</span>repo</pre>
</div>
<br />In <b>[remi]</b> section we need to change enabled=<b>0</b> into enabled=<b>1</b>. It will look like so:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;"><span style="color: #ff8906;">[</span><span style="color: #f6c1d0;">remi</span><span style="color: #ff8906;">]</span>
name<span style="color: #d2cd86;">=</span>Les RPM de remi pour Enterprise Linux <span style="color: #008c00;">6</span> <span style="color: #d2cd86;">-</span> $basearch
#baseurl<span style="color: #d2cd86;">=</span>http<span style="color: #d2cd86;">:</span><span style="color: #d2cd86;">/</span><span style="color: #d2cd86;">/</span>rpms<span style="color: #d2cd86;">.</span>famillecollet<span style="color: #d2cd86;">.</span>com<span style="color: #d2cd86;">/</span>enterprise<span style="color: #d2cd86;">/</span><span style="color: #008c00;">6</span><span style="color: #d2cd86;">/</span>remi<span style="color: #d2cd86;">/</span>$basearch<span style="color: #d2cd86;">/</span>
mirrorlist<span style="color: #d2cd86;">=</span>http<span style="color: #d2cd86;">:</span><span style="color: #d2cd86;">/</span><span style="color: #d2cd86;">/</span>rpms<span style="color: #d2cd86;">.</span>famillecollet<span style="color: #d2cd86;">.</span>com<span style="color: #d2cd86;">/</span>enterprise<span style="color: #d2cd86;">/</span><span style="color: #008c00;">6</span><span style="color: #d2cd86;">/</span>remi<span style="color: #d2cd86;">/</span>mirror
enabled<span style="color: #d2cd86;">=</span><span style="color: #008c00;">1</span>
gpgcheck<span style="color: #d2cd86;">=</span><span style="color: #008c00;">1</span>
gpgkey<span style="color: #d2cd86;">=</span>file<span style="color: #d2cd86;">:</span><span style="color: #d2cd86;">/</span><span style="color: #d2cd86;">/</span><span style="color: #d2cd86;">/</span>etc<span style="color: #d2cd86;">/</span>pki<span style="color: #d2cd86;">/</span>rpm<span style="color: #d2cd86;">-</span>gpg<span style="color: #d2cd86;">/</span>RPM<span style="color: #d2cd86;">-</span>GPG<span style="color: #d2cd86;">-</span>KEY<span style="color: #d2cd86;">-</span>remi</pre>
</div>
<br />Only need to update now:<br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">yum update <span style="color: #d2cd86;">-</span>y</pre>
</div>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br />
<br />
<br />
<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-24999268483207855362015-08-25T18:16:00.000+03:002015-08-25T18:16:16.076+03:00Tmux quick start guide<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7mktVQ2SDdbW9wo7TtJPA7uCyIykxhJFQaV_ryOx88HMI6h5ezOTZzq-Jpy6NIUPd7pFDr34AG4NDBJMBWlQBKXCdo16-4FfJ3yvPKl0h_5qOpgA65ZjopYyEMbOG60D4QBE8dEJeffhN/s1600/tmux+lol+-+Google+Search+2015-08-25+18-11-50.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7mktVQ2SDdbW9wo7TtJPA7uCyIykxhJFQaV_ryOx88HMI6h5ezOTZzq-Jpy6NIUPd7pFDr34AG4NDBJMBWlQBKXCdo16-4FfJ3yvPKl0h_5qOpgA65ZjopYyEMbOG60D4QBE8dEJeffhN/s1600/tmux+lol+-+Google+Search+2015-08-25+18-11-50.png" /></a></div>
<b>Tmux</b> is a handy terminal manager that allows you to switch between terminal sessions easily. Without losing history or windows upon ssh disconnects or similar. It is like <b>screen</b>, just better. (First of all because of using client-server based technology... )<br />
<br />
Here is my minimal keyboard shortcuts guide that allows you to start using Tmux in a blink of an eye. Endless advanced commands and hotkey combinations you could always find by entering "man tmux" in a terminal.<br />
<br />
Tmux is installed quite easily in most of common linux based systems. Just type:<br /><span style="font-family: sans-serif;">Ubuntu:</span><br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">$ sudo apt<span style="color: #d2cd86;">-</span>get install tmux</pre>
</div>
<span style="font-family: sans-serif;">CentOS:</span><br />
<div style="font-family: sans-serif; overflow: auto;">
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;">$ sudo yum install tmux</pre>
</div>
<br />
This allows you to start using by starting it with<br />
<pre style="background: rgb(0, 0, 0); color: #d1d1d1;"><pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;">$ tmux a <span style="color: #d2cd86;">|</span><span style="color: #d2cd86;">|</span> tmux new</pre>
</pre>
This command first tries to attach to existing running tmux instance and creates new in case it is not found.<br /><br />
<div style="text-align: left;">
<b>Ctrl+b d</b> - Will allow you to disconnect at any time. (This is also a way it is happening when you loose ssh session. How to connect - look earlier)</div>
<br />
<br />
Each session can have many windows:<br />
<div style="text-align: left;">
<b>Ctrl+b c</b> - Create a new window.</div>
<b>Ctrl+b 0...9</b> - switch to window #;<br />
<b>Ctrl+b p</b> - switch to previous window;<br />
<b>Ctrl+b n </b>- switch to next window;<br />
<b>Ctrl+b l</b> - switch to next active window (to the one you have switched from to this window);<br />
<b>Ctrl+b &</b> - close this window (Or just type exit in terminal.<br />
<br />
One terminal can have multiple windows:<br /><b>Ctrl+b %</b> - splits current panel in part, vertically;<br />
<b>Ctrl+b "</b> - splits current horizontally;<br />
<b>Ctrl+b →←↑↓ </b>- switch between panels;<br />
<b>Ctrl+b x</b> - close current panel (you could also type <b>exit</b> in a terminal window).<br />
<br />
Minus is a scrolling behavior: <br /><b>Ctrl+b PgUp</b> - enters "copy mode", afterwards:<br />
<b>PgUp, PgDown</b> - scrolling;<br />
<b>q</b> - exit copy mode.<br />
<br />
Good more complex gist of hotkeys also here:<br /><a href="http://gist/" rel="nofollow" target="_blank">HOTKEYS GIST</a></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com1tag:blogger.com,1999:blog-8227451082901531762.post-40277021833351595972015-03-05T18:58:00.001+02:002015-03-05T18:58:59.000+02:00Installing MySQL and phpMyAdmin for web development on a Mac OS X 10.9, 10.8, 10.7, 10.6<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ABMh82hjLxKa3oRJoSBqp-dxyacqYbzXSbsV0sWrhAEzk1c6gtTl9pd1osX_N6ciZ7xOtLTyZUvB6usa4s4-NaEqGQWUGRQFxo8p59GWqjvp6-ME-jiBP7vofL4tjbQdOzyFW9PHozAk/s1600/logo-mysql-170x115.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ABMh82hjLxKa3oRJoSBqp-dxyacqYbzXSbsV0sWrhAEzk1c6gtTl9pd1osX_N6ciZ7xOtLTyZUvB6usa4s4-NaEqGQWUGRQFxo8p59GWqjvp6-ME-jiBP7vofL4tjbQdOzyFW9PHozAk/s1600/logo-mysql-170x115.png" /></a></div>
This is a simple guide on installing a must have SQL database engine for web development. It is often used at the beginning of the journey and I did not find a good guide for it. That made me make myself one and share with others. Hope somebody would benefit from it.<br />
<br />
<br />
<br />
<br />
<br />
<a name='more'></a><br />
First we need to setup the MySQL community edition (latest or not depending on your requirements). It's possible to download it here: <a href="http://dev.mysql.com/downloads/mysql/">http://dev.mysql.com/downloads/mysql/</a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL-eOyrMTmczNQ5BJlJ3tmNTW7SkkwHvayN98CLU8IXpoa9VpJiqBbpxgOPL1y1fwG2AUwN3EF_V37mO9_-NMxvbryEWnTXtUUzBvueh-58SaqW04QfcQ-CQpLmg-gUklt9t6Euzf9sKxY/s1600/mysql-5.6.22-osx10.8-x86_64+2015-03-05+18-13-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL-eOyrMTmczNQ5BJlJ3tmNTW7SkkwHvayN98CLU8IXpoa9VpJiqBbpxgOPL1y1fwG2AUwN3EF_V37mO9_-NMxvbryEWnTXtUUzBvueh-58SaqW04QfcQ-CQpLmg-gUklt9t6Euzf9sKxY/s1600/mysql-5.6.22-osx10.8-x86_64+2015-03-05+18-13-11.png" height="260" width="320" /></a></div>
<br />
It comes in form of a .pkg installer file. It is advised to install it as follows by using default settings. Installation is pretty straightforward. Just click next and agree several times...<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7o-NQn70oKID6S4a9xdr_X3AIWN_UdJaZJVWwuctqqU1a84GwILPlGV5m00NN2w0SnyLjUDLKh57OjsycYb86linhBIVB44S3Wv9omI7nKKFXRoWKBOsPzRl9FqQ2r0j2LYhKpVXJHMHJ/s1600/Install+MySQL+5.6.22-community+2015-03-05+18-13-58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7o-NQn70oKID6S4a9xdr_X3AIWN_UdJaZJVWwuctqqU1a84GwILPlGV5m00NN2w0SnyLjUDLKh57OjsycYb86linhBIVB44S3Wv9omI7nKKFXRoWKBOsPzRl9FqQ2r0j2LYhKpVXJHMHJ/s1600/Install+MySQL+5.6.22-community+2015-03-05+18-13-58.png" height="452" width="640" /></a></div>
This will add a service of MySQL to your system. Nothing more. To interact with it you need either to use SQL console (in case you know SQL) or install something like phpMyAdmin to interact with it. Your pkg installer installs a useful enough Preference Panel switch by default.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNRF2b0p0B0VZ75T3Hd3F412U7J1xU1jonv0uIjbLiIpCclYW2fSuQdFpMvA4-3p_-BcpsAzYiwlGC4R26mMEhzEo4zKyk_2JmPIUmF7Yfpy8akZgNd13oo1LgGKqXeQIZW9kmn9en-LJd/s1600/System+Preferences+2015-03-05+18-17-14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNRF2b0p0B0VZ75T3Hd3F412U7J1xU1jonv0uIjbLiIpCclYW2fSuQdFpMvA4-3p_-BcpsAzYiwlGC4R26mMEhzEo4zKyk_2JmPIUmF7Yfpy8akZgNd13oo1LgGKqXeQIZW9kmn9en-LJd/s1600/System+Preferences+2015-03-05+18-17-14.png" height="320" width="302" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
There you can have it basically configured. Only two basic options persist. Either to run the service on startup or start/stop service button.</div>
Go ahead and start a service for farther interaction:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZLttehuOlPqkv-HV_TyMYFx92V3Q9MSYjf6mn9HwkgGhGWP-X0t15fX2JU3Q2aSDGcriZIYqDb55YhyMhdXYtTyxlNp2jSTAoRiMJDluJVO0APtGQD_LhOfcEUhn-Op8RLpoyr0PJ2ON2/s1600/MySQL+2015-03-05+18-19-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZLttehuOlPqkv-HV_TyMYFx92V3Q9MSYjf6mn9HwkgGhGWP-X0t15fX2JU3Q2aSDGcriZIYqDb55YhyMhdXYtTyxlNp2jSTAoRiMJDluJVO0APtGQD_LhOfcEUhn-Op8RLpoyr0PJ2ON2/s1600/MySQL+2015-03-05+18-19-18.png" height="315" width="640" /></a></div>
It is possible to now test your MySQL version by typing a terminal command:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #3399cc;">/</span><span style="color: #cccccc;">usr</span><span style="color: #3399cc;">/</span><span style="color: #cccccc;">local</span><span style="color: #3399cc;">/</span><span style="color: #cccccc;">mysql</span><span style="color: #3399cc;">/</span><span style="color: #cd00cd;">bin</span><span style="color: #3399cc;">/</span><span style="color: #cccccc;">mysql</span> <span style="color: #3399cc;">-</span><span style="color: #cccccc;">v</span></pre>
</div>
Good idea would be to add a path to your mysql executable to system path in your bash config. So you could type just "mysql" without specifying a path. To do so append this line to your <b><i>~/.bashrc_profile</i></b>:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">export</span> <span style="color: #cccccc;">PATH</span><span style="color: #3399cc;">=</span><span style="color: #cd0000;">"/usr/local/mysql/bin:$PATH"</span></pre>
</div>
Either restart console or do <b><i>source ~/.bash_profile</i></b> to update your current environment.<br />
It is now possible to do:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">mysql</span> <span style="color: #3399cc;">-</span><span style="color: #cccccc;">v</span></pre>
</div>
Note you do not have to specify a path to it any more.<br />
<br />
Stoping at this no more farther let's finish configuring mysql by adding at least one main user/password and disabling defaults. There is a handy config script for this:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">sudo</span> <span style="color: #cccccc;">mysql_secure_installation</span></pre>
</div>
Just execute this and follow up the steps widely described to you there. That's it you can now use MySQL on your system.<br />
<br />
Let's go ahead and make a UI for ourselves by installing phpMyAdmin. Basically it's a utility that runs on your mac's built in Apache server (make sure it is running) and provides you an ability to manage your SQL databases through a handy web UI.<br />
<br />
here you need to download a <a href="http://www.phpmyadmin.net/home_page/downloads.php">http://www.phpmyadmin.net/home_page/downloads.php</a> latest version of the phpMyAdmin.<br />
You will get yourself an archive version of this PHP application. that's basically all you need to know about it.<br />
You also need to have apache running on your MAC. Make sure you do. zThere are many guides on it. Basically you need to have your computer outputting something in your web browser in case of typing localhost in your address line:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLL6JxKJbRN0LSOGDODKyo-Fd3dN_ugUJ2VAkOgcQC56BQ5GulETEWyLNCs3MeoUkb7eEUit09wceXq2E9kcgS4QQlbXPq_lidF095JpfC2CVnwMbxcJZV1pzSexuee2BkhhwHtac8zde4/s1600/%E2%80%8Elocalhost+2015-03-05+18-41-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLL6JxKJbRN0LSOGDODKyo-Fd3dN_ugUJ2VAkOgcQC56BQ5GulETEWyLNCs3MeoUkb7eEUit09wceXq2E9kcgS4QQlbXPq_lidF095JpfC2CVnwMbxcJZV1pzSexuee2BkhhwHtac8zde4/s1600/%E2%80%8Elocalhost+2015-03-05+18-41-16.png" height="242" width="400" /></a></div>
With this in mind you also need to have PHP enabled in your apache config. There are guides on that too. Enough of precautions and let's move farther with our straightforward install:<br />
Time to place our unpacked folder contents into <b><i>~/Sites</i></b> folder. It is advised to rename it into <b>'myadmin'</b> to follow along with me.<br />
This will bring you ability to type:<br />
<b>http://localhost/~your_username/myadmin/setup/</b> or either <b>http://localhost/myadmin/setup/</b>, depending on your apache configuration.<br />
This will show up something similar to this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmOsyq7evvt60CACz9nKPjpp6E8cYTL8FAj68ktgDHYBR_4swZD5PEeRFt9dSzRAR5pI7oqIeyKIm38P5uKijJzXM7PoPPWA-Bju04sgVmmDuxkBGR8uG7NubDmBeS8xDDHU_BhMLrm0ix/s1600/phpMyAdmin+setup+2015-03-05+18-47-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmOsyq7evvt60CACz9nKPjpp6E8cYTL8FAj68ktgDHYBR_4swZD5PEeRFt9dSzRAR5pI7oqIeyKIm38P5uKijJzXM7PoPPWA-Bju04sgVmmDuxkBGR8uG7NubDmBeS8xDDHU_BhMLrm0ix/s1600/phpMyAdmin+setup+2015-03-05+18-47-13.png" height="448" width="640" /></a></div>
Click <b>New Server</b> button and configure your newly installed MySQL server, so phpMyAdmin would be able to use it.<br />
Fill in only username <b>root</b> and your root <b>password</b>, leaving all the other fields intact. (with default settings). You hopefully remember specifying a password for root in the initial MySQL server configuration step?<br />
Switch to the Authentication tab and enter them.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMTGdrxXVl8YRyCa9VkR6WNwlr3DOBppQjLwLVZZ5WAIyzmlYd9zrbSjhTlZ-TV3Zxh9SUWAtxwqb8ezvV3hb7tDd6Sg3GOW-fSGAIOh69J4UCl_jSHN9jvgb13z1X8LHlntnBJhhezRNZ/s1600/phpMyAdmin+setup+2015-03-05+18-52-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMTGdrxXVl8YRyCa9VkR6WNwlr3DOBppQjLwLVZZ5WAIyzmlYd9zrbSjhTlZ-TV3Zxh9SUWAtxwqb8ezvV3hb7tDd6Sg3GOW-fSGAIOh69J4UCl_jSHN9jvgb13z1X8LHlntnBJhhezRNZ/s1600/phpMyAdmin+setup+2015-03-05+18-52-09.png" height="402" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Now you are able to manage your MySQL databases through a web UI using phpMyAdmin</div>
Type in the address like: http://localhost/~username/myadmin/<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwlcQ0f3xc10l_5nvV8mXAZmXTCUUXrpWUULx-rzH-KWnZ75h0oSnSB_OaPomDaJhRriiq5C4ixXauJJ6_o5bsLCuoG26cQN3wxgTwVCk62PppNUjtDlAZKfOLC5cwPDMjXKJIES-e1v9z/s1600/phpMyAdmin+2015-03-05+18-54-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwlcQ0f3xc10l_5nvV8mXAZmXTCUUXrpWUULx-rzH-KWnZ75h0oSnSB_OaPomDaJhRriiq5C4ixXauJJ6_o5bsLCuoG26cQN3wxgTwVCk62PppNUjtDlAZKfOLC5cwPDMjXKJIES-e1v9z/s1600/phpMyAdmin+2015-03-05+18-54-18.png" height="494" width="640" /></a></div>
<br />
Here you go... Please comment in case you have found it useful. I will know my time writing this was not wasted. thank you!</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com1tag:blogger.com,1999:blog-8227451082901531762.post-67231896043618863372015-01-23T17:17:00.000+02:002015-01-23T18:08:19.443+02:00[Django CMS] Adding plugins inside plugins programatically<div dir="ltr" style="text-align: left;" trbidi="on">
I have a task to migrate a website. Old one is plain HTML and new one is Django CMS. I have a script that parses an HTML page from old website in to CMS page and places it into proper place.<br />
Task is to migrate all the page content (that is a CMS TextPlugin) into an interlinked pages setup. Like we have text<br />
<br />
<b><i><p>blah blah </p><a href="/page/url">Text</a><p> some other text</p></i></b><br />
<br />
And I need to change it into CMS LinkPlugin that is nested inside of the TextPlugin. It have become a common standard in the Django CMS world now. Note we need to have a LinkPlugin because of the requirement to interlink pages.<br />
E.g. <i><b><a href="/page/url"></b></i> is a link to CMS Page object.<br />
<br />
The solution is divided into two major parts. First we need to have the link plugin added to a placeholder of the text plugin. It must also be nested by the TextPlugin, like Django CMS admin web UI would do. So our plugin would look somehow like this in the CMS Page admin:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk4QRmcwv9R1W0-N6hSj3C4659LGuSFiZ37ZqQhDfu6ckeFmeEMHBfQC9ACszz1G1IbZ9CY_sRUT7W0vhTe6Ct-CM5B7l6UexY5GvDfVPyC0w0ZYHQoPEFEMIhtTDf5fYNtJXv1CTc-Jed/s1600/scr1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk4QRmcwv9R1W0-N6hSj3C4659LGuSFiZ37ZqQhDfu6ckeFmeEMHBfQC9ACszz1G1IbZ9CY_sRUT7W0vhTe6Ct-CM5B7l6UexY5GvDfVPyC0w0ZYHQoPEFEMIhtTDf5fYNtJXv1CTc-Jed/s1600/scr1.png" height="178" width="640" /></a></div>
And the second is modifying the Text Plugin instance itself with placing Link plugin placeholders instead of <a></a> tags we have there.<br />
In this particular example we have a placeholder named "content" and a page containing only one TextPlugin with text in it. We need to modify that text.<br />
First we need to create an instance of a CMSPlugin that is attached to a proper placeholder and is nested in our TextPlugin instance. Creating a Link plugin (an instance of a configuration for that CMS plugin in practice) is a next step to achieve this.<br />
<script src="https://gist.github.com/garmoncheg/bf18e9601c34d55a51e9.js"></script>
That will be the part 2 of this article. Coming soon.<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com3tag:blogger.com,1999:blog-8227451082901531762.post-20049050534310120032015-01-22T15:27:00.000+02:002015-01-22T15:27:54.372+02:00Don't put html, head and body tags automatically into beautifulsoup content<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP5m-orhk_U9oaPsTPCC5J3Em-EI_3abBZQpTI2g_PVYtmtlGz1LGfcbDnmJYvafMYfPCY8JL6MTSe-c5q3y677M1yMpEb7KOwgkiTXqww0-Iy4teoEvydXJwiGAQbWsBMi_ji3j5KrZQn/s1600/6.1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP5m-orhk_U9oaPsTPCC5J3Em-EI_3abBZQpTI2g_PVYtmtlGz1LGfcbDnmJYvafMYfPCY8JL6MTSe-c5q3y677M1yMpEb7KOwgkiTXqww0-Iy4teoEvydXJwiGAQbWsBMi_ji3j5KrZQn/s1600/6.1.jpg" /></a></div>
<br />
Was making a parser recently with BeautifulSoup. Came to the final with rendering contents of the edited text. Like so:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">text</span> <span style="color: #3399cc;">=</span> <span style="color: #cd0000;">"<h1>Test text tag</h1>"</span>
<span style="color: #cccccc;">soup</span> <span style="color: #3399cc;">=</span> <span style="color: #cccccc;">BeautifulSoup(text,</span> <span style="color: #cd0000;">"html5"</span><span style="color: #cccccc;">)</span>
<span style="color: #cccccc;">text</span> <span style="color: #3399cc;">=</span> <span style="color: #cccccc;">soup</span><span style="color: #3399cc;">.</span><span style="color: #cccccc;">renderContents()</span>
<span style="color: #cdcd00;">print</span> <span style="color: #cccccc;">text</span></pre>
</div>
It renders those contents with a result wrapped into the <html>, <head> and <body> tags. So print output looks like so:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cd0000;">'<html><head></head><body><h1>Test text tag</h1></body></html>'</span></pre>
</div>
That's a feature of the html5lib library, it fixes HTML that is lacking, such as adding back in missing required elements. <br />
<br />
The workaround is simple enough:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">text</span> <span style="color: #3399cc;">=</span> <span style="color: #cccccc;">soup</span><span style="color: #3399cc;">.</span><span style="color: #cccccc;">body</span><span style="color: #3399cc;">.</span><span style="color: #cccccc;">renderContents()</span></pre>
</div>
This solution will return an inside of the <html> tag <body>.<br />
Result is:<br />
<div style="background: rgb(0, 0, 0); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">text</span> <span style="color: #3399cc;">=</span> <span style="color: #cd0000;">'<h1>Test text tag</h1>'</span></pre>
</div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-19560863505676842302014-12-20T14:54:00.000+02:002014-12-20T14:54:23.830+02:00Error copying files in Finder of OS X<div dir="ltr" style="text-align: left;" trbidi="on">
Problem:<br />
I have an SD flash card (8 GB Kingston) and a MacBook Pro 13" (Late 2011 model). I also use external card reader time to time.<br />This problem persisted on all the conditions. The error message was stating:<br />
<h4 style="text-align: left;">
The Finder can’t complete the operation because some data in “” can’t be read or written.<br />(Error code -36)</h4>
This was happening while copying Photos from my camera (cr2 files). It worked, however, in case of copying files up to 200 MB in total size of batch. It dropped this error message and did stop to copy files upon selecting of lots of RAW files. E.g. all of them and attempting to copy them from a flash drive.<br />
<br />
Solution:<br />
Problem occurred with building miniatures of the CR2 files. Those files are quite heavy photos (25+ MB) and building miniature did take some time. While building those miniatures on both MAC and SD card finder windows it did die.<br /><br />For me it was enough to change the view from icons to list. E.g.:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNIhvGLp7PuE0UPhDNLpZIeL0gcxzVUShZPvub3QivjPoXF2sSJRN3szE9-I4EiEzFaF0z2y3TNS_B5cUFCIUxG4lKdjmOmthTZMpVP8WcKuugZ-dPydC81PKlbfxuKTvb0LHX1KeBjOvb/s1600/2014.12.15+2014-12-20+14-50-31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNIhvGLp7PuE0UPhDNLpZIeL0gcxzVUShZPvub3QivjPoXF2sSJRN3szE9-I4EiEzFaF0z2y3TNS_B5cUFCIUxG4lKdjmOmthTZMpVP8WcKuugZ-dPydC81PKlbfxuKTvb0LHX1KeBjOvb/s1600/2014.12.15+2014-12-20+14-50-31.png" height="153" width="400" /></a></div>
This did solve it for me. Other solution (Suspect in case your MAC would be lower processor model and/or less productive hardware version) is to disable building miniatures for files in Finder.</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-19799673997528737392014-07-31T22:20:00.002+03:002014-07-31T22:20:50.624+03:005 most common Rsync command usage examples<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbpvhl3kB3i1dmDppQxdZ6fBvKQDOoxUyxh2iyA8MmLdg4b9UIhIP7fpEsqYzw3hhZHkazfPSBmyMSRKomKHHjdVtuA02QetsvrVS66RKP4Nq7jL2An-MA-ffHfgHYFmfQoqrDXsD1vKKF/s1600/sync1.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbpvhl3kB3i1dmDppQxdZ6fBvKQDOoxUyxh2iyA8MmLdg4b9UIhIP7fpEsqYzw3hhZHkazfPSBmyMSRKomKHHjdVtuA02QetsvrVS66RKP4Nq7jL2An-MA-ffHfgHYFmfQoqrDXsD1vKKF/s1600/sync1.png" /></a></div>
rsync is a command for remote sync.<br />
<br />
It is used to synchronise one location to another in a simple way. Location is meant to be local directory, server or remote web server or whatever accessible by ssh.<br />
<br />
Advantages of using rsync over other tools is speed and bandwidth requirements. First time rsync copies entire contents of the directory provided and increments changes over next sync times.<br />
<br />
<h3 style="text-align: left;">
Command syntax:</h3>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">options</span> <span style="color: #d0d0d0;">source</span> <span style="color: #d0d0d0;">destination</span></pre>
</div>
<br />
<h3 style="text-align: left;">
1. Synchronising local directories:</h3>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">-zvr</span> <span style="color: #ed9d13;">/tmp/logs/ /tmp/logs1/</span>
<span style="color: #d0d0d0;">building</span> <span style="color: #d0d0d0;">file</span> <span style="color: #d0d0d0;">list</span> <span style="color: #d0d0d0;">...</span> <span style="color: #d0d0d0;">done</span>
<span style="color: #d0d0d0;">created</span> <span style="color: #d0d0d0;">directory</span> <span style="color: #ed9d13;">/tmp/</span><span style="color: #d0d0d0;">logs1</span>
<span style="color: #d0d0d0;">./</span>
<span style="color: #d0d0d0;">log.</span><span style="color: #bbbbbb;">log</span>
<span style="color: #d0d0d0;">sent</span> <span style="color: #3677a9;">98</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #d0d0d0;">received</span> <span style="color: #3677a9;">48</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #3677a9;">292.00</span> <span style="color: #d0d0d0;">bytes/sec</span>
<span style="color: #d0d0d0;">total</span> <span style="color: #d0d0d0;">size</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0</span> <span style="color: #d0d0d0;">speedup</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0.00</span>
<span style="color: #d0d0d0;">$</span></pre>
</div>
Used rsync command options here:<br />
<br />
<ul style="text-align: left;">
<li><b><i>-z</i></b> is for compression</li>
<li><b><i>-v</i></b> is for verbose output</li>
<li><b><i>-r</i></b> is for recursive directory scanning</li>
</ul>
<div>
By default rsync does not preserve timestamps. </div>
<h3 style="text-align: left;">
2. Preserve timestamps and permissions during sync:</h3>
<br />
<div>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">-azvr</span> <span style="color: #ed9d13;">/tmp/logs/ /tmp/logs1/</span>
<span style="color: #d0d0d0;">building</span> <span style="color: #d0d0d0;">file</span> <span style="color: #d0d0d0;">list</span> <span style="color: #d0d0d0;">...</span> <span style="color: #d0d0d0;">done</span>
<span style="color: #d0d0d0;">./</span>
<span style="color: #d0d0d0;">log.</span><span style="color: #bbbbbb;">log</span>
<span style="color: #d0d0d0;">sent</span> <span style="color: #3677a9;">122</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #d0d0d0;">received</span> <span style="color: #3677a9;">48</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #3677a9;">340.00</span> <span style="color: #d0d0d0;">bytes/sec</span>
<span style="color: #d0d0d0;">total</span> <span style="color: #d0d0d0;">size</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0</span> <span style="color: #d0d0d0;">speedup</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0.00</span>
<span style="color: #d0d0d0;">$</span></pre>
</div>
</div>
Option <b><i>-a</i></b> preserves symbolic links, timestamps, user permissions and ownership.<br />
<h3 style="text-align: left;">
3. Synchronize from Local to Remote:</h3>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">-avz</span> <span style="color: #ed9d13;">/tmp/logs/ root@192.168.1.105:/home/user/logs/</span>
<span style="color: #d0d0d0;">root</span><span style="background-color: #e3d2d2; color: #a61717;">@</span><span style="color: #3677a9;">192.168</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">1.105</span><span style="background-color: #e3d2d2; color: #a61717;">'</span><span style="color: #d0d0d0;">s</span> <span style="color: #d0d0d0;">password:</span>
<span style="color: #d0d0d0;">building</span> <span style="color: #d0d0d0;">file</span> <span style="color: #d0d0d0;">list</span> <span style="color: #d0d0d0;">...</span> <span style="color: #d0d0d0;">done</span>
<span style="color: #d0d0d0;">created</span> <span style="color: #d0d0d0;">directory</span> <span style="color: #ed9d13;">/home/user/</span><span style="color: #d0d0d0;">logs</span>
<span style="color: #d0d0d0;">./</span>
<span style="color: #d0d0d0;">log.</span><span style="color: #bbbbbb;">log</span>
<span style="color: #d0d0d0;">sent</span> <span style="color: #3677a9;">122</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #d0d0d0;">received</span> <span style="color: #3677a9;">48</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #3677a9;">68.00</span> <span style="color: #d0d0d0;">bytes/sec</span>
<span style="color: #d0d0d0;">total</span> <span style="color: #d0d0d0;">size</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0</span> <span style="color: #d0d0d0;">speedup</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">0.00</span>
<span style="color: #d0d0d0;">$</span></pre>
</div>
It is required to specify username and ip-address of the remote server, while doing synchronization. It is also required to specify the destination directory on the remote server. The format is <b style="font-style: italic;">username@machinename:path</b>. Sometimes depending on your credentials and ssh authentication method you may need to enter a password. Like in this example.<br />
<h3 style="text-align: left;">
4. Synchronize from Remote to Local:</h3>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">-avz</span> <span style="color: #d0d0d0;">root</span><span style="background-color: #e3d2d2; color: #a61717;">@</span><span style="color: #3677a9;">192.168</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">1.105</span><span style="color: #d0d0d0;">:/tmp</span><span style="color: #ed9d13;">/ ~/temp/</span>
<span style="color: #d0d0d0;">root</span><span style="background-color: #e3d2d2; color: #a61717;">@</span><span style="color: #3677a9;">192.168</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">1.105</span><span style="background-color: #e3d2d2; color: #a61717;">'</span><span style="color: #d0d0d0;">s</span> <span style="color: #d0d0d0;">password:</span>
<span style="color: #d0d0d0;">receiving</span> <span style="color: #d0d0d0;">file</span> <span style="color: #d0d0d0;">list</span> <span style="color: #d0d0d0;">...</span> <span style="color: #d0d0d0;">done</span>
<span style="color: #d0d0d0;">./</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_182.</span><span style="color: #bbbbbb;">MYD</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_182.</span><span style="color: #bbbbbb;">MYI</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_182.</span><span style="color: #bbbbbb;">frm</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_183.</span><span style="color: #bbbbbb;">MYD</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_183.</span><span style="color: #bbbbbb;">MYI</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_183.</span><span style="color: #bbbbbb;">frm</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b6.</span><span style="color: #bbbbbb;">MYD</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b6.</span><span style="color: #bbbbbb;">MYI</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b6.</span><span style="color: #bbbbbb;">frm</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b7.</span><span style="color: #bbbbbb;">MYD</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b7.</span><span style="color: #bbbbbb;">MYI</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_58f_b7.</span><span style="color: #bbbbbb;">frm</span>
<span style="color: #d0d0d0;">sent</span> <span style="color: #3677a9;">290</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #d0d0d0;">received</span> <span style="color: #3677a9;">11002</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #3677a9;">3226.29</span> <span style="color: #d0d0d0;">bytes/sec</span>
<span style="color: #d0d0d0;">total</span> <span style="color: #d0d0d0;">size</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">16956702</span> <span style="color: #d0d0d0;">speedup</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">1501.66</span>
<span style="color: #d0d0d0;">$</span></pre>
</div>
This example is opposite to previous. we have synchronized a list of only changed files here. So speedup is relatively high.<br />
5. View the rsync Progress during Transfer:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">rsync</span> <span style="color: #d0d0d0;">-avz</span> <span style="color: #d0d0d0;">--progress</span> <span style="color: #d0d0d0;">root</span><span style="background-color: #e3d2d2; color: #a61717;">@</span><span style="color: #3677a9;">192.168</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">1.105</span><span style="color: #d0d0d0;">:/tmp</span><span style="color: #ed9d13;">/ ~/temp/</span>
<span style="color: #d0d0d0;">root</span><span style="background-color: #e3d2d2; color: #a61717;">@</span><span style="color: #3677a9;">192.168</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">1.105</span><span style="background-color: #e3d2d2; color: #a61717;">'</span><span style="color: #d0d0d0;">s</span> <span style="color: #d0d0d0;">password:</span>
<span style="color: #d0d0d0;">receiving</span> <span style="color: #d0d0d0;">file</span> <span style="color: #d0d0d0;">list</span> <span style="color: #d0d0d0;">...</span>
<span style="color: #3677a9;">284</span> <span style="color: #d0d0d0;">files</span> <span style="color: #d0d0d0;">to</span> <span style="color: #d0d0d0;">consider</span>
<span style="color: #d0d0d0;">./</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1ae.</span><span style="color: #bbbbbb;">MYD</span>
<span style="color: #3677a9;">1372</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">1.31</span><span style="color: #d0d0d0;">MB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#1, to-check=252/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1ae.</span><span style="color: #bbbbbb;">MYI</span>
<span style="color: #3677a9;">1024</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">1000.00</span><span style="color: #d0d0d0;">kB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#2, to-check=251/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1ae.</span><span style="color: #bbbbbb;">frm</span>
<span style="color: #3677a9;">8658</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">8.26</span><span style="color: #d0d0d0;">MB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#3, to-check=250/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1af.</span><span style="color: #bbbbbb;">MYD</span>
<span style="color: #3677a9;">0</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">0.00</span><span style="color: #d0d0d0;">kB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#4, to-check=249/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1af.</span><span style="color: #bbbbbb;">MYI</span>
<span style="color: #3677a9;">1024</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">500.00</span><span style="color: #d0d0d0;">kB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#5, to-check=248/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="background-color: #e3d2d2; color: #a61717;">#</span><span style="color: #d0d0d0;">sql8ac_57e_1af.</span><span style="color: #bbbbbb;">frm</span>
<span style="color: #3677a9;">8632</span> <span style="color: #3677a9;">100</span><span style="color: #d0d0d0;">%</span> <span style="color: #3677a9;">2.74</span><span style="color: #d0d0d0;">MB</span><span style="color: #ed9d13;">/s 0:00:00 (xfer#6, to-check=247/</span><span style="color: #3677a9;">284</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">sent</span> <span style="color: #3677a9;">158</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #d0d0d0;">received</span> <span style="color: #3677a9;">9666</span> <span style="color: #d0d0d0;">bytes</span> <span style="color: #3677a9;">3929.60</span> <span style="color: #d0d0d0;">bytes/sec</span>
<span style="color: #d0d0d0;">total</span> <span style="color: #d0d0d0;">size</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">16956814</span> <span style="color: #d0d0d0;">speedup</span> <span style="color: #6ab825; font-weight: bold;">is</span> <span style="color: #3677a9;">1726.06</span>
<span style="color: #d0d0d0;">$</span></pre>
</div>
Running with <b><i>--progress</i></b> option showcase detailed progress of server interaction during load operations.<br />
<br />
Thats it. Hope you find this article helpful to you. Comments? Suggestions?</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-12792708815321800192014-07-29T12:54:00.001+03:002014-07-29T12:54:12.650+03:00Django adding custom widget to Django Admin<div dir="ltr" style="text-align: left;" trbidi="on">
Sometimes you need to get out of standard behaviour of your Django admin. It means expanding its functionality with custom things. In our case we have a model that we want to add a custom html element. Button that must load something via AJAX from another place to be exact.<br />
We have a typical Django polls application for simplicity. Here is its structure:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7IBm68gaAXZ-gVXDCvklW2gGDWSK9K17SdiHR05awGb78ef2v6fK-iH-y44zWFFm2lO79nfaJg9vLfebtidpZXbFwfB3OYCvdJy3QsYRWX67BnEYgg-FJ0fBxB1-aKPfHnQlpmwHYWoSy/s1600/hw1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7IBm68gaAXZ-gVXDCvklW2gGDWSK9K17SdiHR05awGb78ef2v6fK-iH-y44zWFFm2lO79nfaJg9vLfebtidpZXbFwfB3OYCvdJy3QsYRWX67BnEYgg-FJ0fBxB1-aKPfHnQlpmwHYWoSy/s1600/hw1.png" height="400" width="250" /></a></div>
<br />
First of all we need to create a structure. So here comes our model:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># models.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.db</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">models</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">Poll</span><span style="color: #d0d0d0;">(models.Model):</span>
<span style="color: #d0d0d0;">question</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">models.CharField(max_length=</span><span style="color: #3677a9;">200</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">pub_date</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">models.DateTimeField(</span><span style="color: #ed9d13;">'date published'</span><span style="color: #d0d0d0;">)</span></pre>
</div>
We have to have our django application admin configuration to display that model:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># admin.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.contrib</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">admin</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">polls.models</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">Poll</span>
<span style="color: #d0d0d0;">admin.site.register(Poll)</span></pre>
</div>
It will look in Django admin like so:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL6MuhJwfifVltyJThyphenhyphen99oXSg7pxL2g7xWz37PlHUBgk7Ckb3e0ZmfW58plMkLm_c0fW9lnVAcDiYp81pMBVNuCailC6ax9FkBFcW6kTihq67FJOwW4WcMxV6pR7z1OV48aUkgaf0If2I7/s1600/dja1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL6MuhJwfifVltyJThyphenhyphen99oXSg7pxL2g7xWz37PlHUBgk7Ckb3e0ZmfW58plMkLm_c0fW9lnVAcDiYp81pMBVNuCailC6ax9FkBFcW6kTihq67FJOwW4WcMxV6pR7z1OV48aUkgaf0If2I7/s1600/dja1.png" height="231" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
You can see polls available here in admin. You can do all the typical things with Polls model. Add/Delete/Edit... Using standard Django features. Imagine we have something on that polls model that we need to expand. Say, we need a button to visit external site here, made like an additional edit field. Imagine we need to take something on external website. We can post something to that website from our filled django admin form. To do that we need to create a custom form field. I have not found any standard widgets to do that. It is required to write our own field and attach it to the Django admin form.</div>
<div class="separator" style="clear: both; text-align: left;">
We do not need own field here. Just a widget. Widgets are standard Django types. It is possible to read wide description of them in the official documentation: <a href="https://docs.djangoproject.com/en/dev/ref/forms/widgets/" target="_blank">Django Widgets</a>. I wont discuss here best ways to implement this task and there might be better ones. However I have chosen a form widget for simplicity.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
It is required to have a model expansion form and a custom widget in order to do so. Registration fo that for m in django admin setup is also required. Lets implement this.<br />Starting with a form and a widget:</div>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># forms.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">forms</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.utils.safestring</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">mark_safe</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.template.loader</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">render_to_string</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">polls.models</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">Poll</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">ButtonWidget</span><span style="color: #d0d0d0;">(forms.Widget):</span>
<span style="color: #d0d0d0;">template_name</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">'auth_button_widget.html'</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">render</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">name,</span> <span style="color: #d0d0d0;">value,</span> <span style="color: #d0d0d0;">attrs=</span><span style="color: #24909d;">None</span><span style="color: #d0d0d0;">):</span>
<span style="color: #d0d0d0;">context</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #ed9d13;">'url'</span><span style="color: #d0d0d0;">:</span> <span style="color: #ed9d13;">'/'</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">mark_safe(render_to_string(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.template_name,</span> <span style="color: #d0d0d0;">context))</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">PollsForm</span><span style="color: #d0d0d0;">(forms.ModelForm):</span>
<span style="color: #d0d0d0;">button</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">forms.CharField(widget=ButtonWidget)</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">Meta</span><span style="color: #d0d0d0;">:</span>
<span style="color: #d0d0d0;">model</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">Poll</span></pre>
</div>
<div class="separator" style="clear: both; text-align: left;">
It is located in a newly created file - <b><i>forms.py</i></b> at the django app - <b><i>polls</i></b> directory. Here we have a custom written widget that inherits a typical default Django widget (<b><i>forms.Widget</i></b>). we have provided it a template - <b><i>auth_button_widget.html </i></b>and a custom <b><i>render()</i></b> method that provides extra context for that template.</div>
<div class="separator" style="clear: both; text-align: left;">
Next comes the <b><i>PollsForm</i></b> class with a custom <b><i>button</i></b> field that uses that widget. Note here <b><i>Meta</i></b> for that model is specified, indicating we are adding that field to the <b><i>Polls</i></b> model add/edit form.</div>
<div class="separator" style="clear: both; text-align: left;">
Template, residing in all django templates directory will look like so:</div>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">{</span><span style="color: #999999; font-style: italic;"># auth_button_widget.html #}</span>
<span style="color: #d0d0d0;"><a</span> <span style="color: #d0d0d0;">href=</span><span style="color: #ed9d13;">"{{ url }}"</span><span style="color: #d0d0d0;">>Go</span> <span style="color: #d0d0d0;">Button</a></span></pre>
</div>
<div class="separator" style="clear: both; text-align: left;">
We have our form and widget and a template to render that form element. Time to use that form.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Using this form means modifying our admin.py file and registering custom model admin there. It will use our custom form and a widget. Resulting <b><i>admin.py</i></b> will look like this:</div>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># admin.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.contrib</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">admin</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">polls.models</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">Poll</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">polls.forms</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">PollsForm</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">PollsAdmin</span><span style="color: #d0d0d0;">(admin.ModelAdmin):</span>
<span style="color: #d0d0d0;">form</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">PollsForm</span>
<span style="color: #d0d0d0;">admin.site.register(Poll,</span> <span style="color: #d0d0d0;">PollsAdmin)</span></pre>
</div>
<div class="separator" style="clear: both; text-align: left;">
Resulting change will add a custom form to edit or add the Polls model, containing our custom button field. It will look something like so:<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3-GB1j5N3THR9t-LyXOtTlJipZwULtGGuPPgVJDIv9A5usbuiyfeyB6WJVpbL-7uFKDbu8LDpqtHHGLK8k3FoVQrRWPNKQqkl38ztqjCkzjLJGrJq6k47V9E69fPXy318J_r-Hz9bcbB_/s1600/admin1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3-GB1j5N3THR9t-LyXOtTlJipZwULtGGuPPgVJDIv9A5usbuiyfeyB6WJVpbL-7uFKDbu8LDpqtHHGLK8k3FoVQrRWPNKQqkl38ztqjCkzjLJGrJq6k47V9E69fPXy318J_r-Hz9bcbB_/s1600/admin1.png" height="230" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Notice the button we have add here. Its just a simple HTML element that needs to be styled and animated by some CSS and JS. It can be done adding <b><i>Media</i></b> to our form widget. Resulting new widget will look like this:</div>
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># forms.py (partially)</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">ButtonWidget</span><span style="color: #d0d0d0;">(forms.Widget):</span>
<span style="color: #d0d0d0;">template_name</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">'auth_button_widget.html'</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">Media</span><span style="color: #d0d0d0;">:</span>
<span style="color: #d0d0d0;">js</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">(</span>
<span style="color: #ed9d13;">'js/admin_button_script.js'</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">css</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #ed9d13;">'all'</span><span style="color: #d0d0d0;">:</span> <span style="color: #d0d0d0;">(</span>
<span style="color: #ed9d13;">'css/admin_button_widget.css'</span><span style="color: #d0d0d0;">,</span>
<span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">render</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">name,</span> <span style="color: #d0d0d0;">value,</span> <span style="color: #d0d0d0;">attrs=</span><span style="color: #24909d;">None</span><span style="color: #d0d0d0;">):</span>
<span style="color: #d0d0d0;">context</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #ed9d13;">'url'</span><span style="color: #d0d0d0;">:</span> <span style="color: #ed9d13;">'/'</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">mark_safe(render_to_string(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.template_name,</span> <span style="color: #d0d0d0;">context))</span></pre>
</div>
<div class="separator" style="clear: both; text-align: left;">
Its a registration of static files to use in your widget. They will represent a scripting and styling for that field and will be included to the page of django admin form automatically.<br />For this to function you have to have <a href="https://docs.djangoproject.com/en/dev/howto/static-files/" target="_blank">django static files configured</a>. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Content of scripts and styles are out of the scope of this article. Main idea here is to highlight a proper way to add and write a custom widget from the backend perspective.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Comments, suggestions?</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com2tag:blogger.com,1999:blog-8227451082901531762.post-27093561743741761692014-07-14T15:07:00.000+03:002014-07-14T15:07:17.349+03:00Virtualenv for Django<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjls-QhMBXw_izCDYDrAOj5ePG-vMetN2cxzcOvZdQRbmnY2ukp25nItoQpHqTZ0TI-HLPeXv80riBaE7JHKloVYVus60VxfLG0c1hzoUGj4mlwlhSJFz_eboihQnkg-9lrKRbSBJgetKp6/s1600/virtualenv.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjls-QhMBXw_izCDYDrAOj5ePG-vMetN2cxzcOvZdQRbmnY2ukp25nItoQpHqTZ0TI-HLPeXv80riBaE7JHKloVYVus60VxfLG0c1hzoUGj4mlwlhSJFz_eboihQnkg-9lrKRbSBJgetKp6/s1600/virtualenv.png" /></a></div>
One of main features and troubles for Django projects is the Django version you are using. Example for this would be the occasion of starting project for Django 1.4.x version. Trying to run it under Django 1.7.x would lead to various troubles, counting template changes, misconfiguration errors and so on.<br /><br />
Solution is to use virtual environment. The tool for this is called <a href="http://virtualenv.readthedocs.org/en/latest/">Virtualenv</a>. It is a wrapper for a python interpreter. It enables you to have multiple versions of python packages that run independently.<br /><br />
The Virtualenv creates you a standalone environment. Basically it copies and keeps a system Python of yours in a specified directory. All the python packages will be installed there. (In case you have not forgot to activate it first, of course)<br /><br />Lets get started then. We need Virtualenv itself for the first. There are many ways <a href="http://virtualenv.readthedocs.org/en/latest/virtualenv.html#installation">to install it depending on your system</a>. Most obvious to use pip. Your installation command will look something like that:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #cccccc;">pip install virtualenv</span></pre>
</div>
This installs the tool itself to your system. this only must be done once.<br />
<br />
Assuming we have it now and going forward to usage basics. We need to create a virtual environment for our particular project. Usual rule for most of developers is to have a single virtual environment for a standalone project.<br />
To create one for ours we need to be in the directory where we want it to reside. (Virtual environment is not movable by default). So choose wisely.<br />
I suggest it be somewhere in the project directory. The directory that is up one step from the project one is ok too. Assuming we have a project that is called "<b><i>example</i></b>". I will enter the directory of that project:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$ cd example</span>
<span style="color: #d0d0d0;">garmoncheg:~/Projects/example$ ls -la</span>
<span style="color: #d0d0d0;">total 8</span>
<span style="color: #d0d0d0;">drwxr-xr-x 4 garmoncheg staff 136B Jul 14 14:26 ./</span>
<span style="color: #d0d0d0;">drwxr-xr-x 3 garmoncheg staff 102B Jul 14 14:26 ../</span>
<span style="color: #d0d0d0;">drwxr-xr-x 6 garmoncheg staff 204B Jul 14 14:26 example/</span>
<span style="color: #d0d0d0;">-rw-r--r-- 1 garmoncheg staff 250B Jul 14 14:26 manage.py</span></pre>
</div>
We have here a<b> manage.py</b> file to run our project with and a project files directory. Seems like a nice place to create a virtual environment at. Time to do it with executing a command:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$ virtualenv venv</span>
<span style="color: #d0d0d0;">New python executable in venv/bin/python</span>
<span style="color: #d0d0d0;">Installing setuptools............done.</span>
<span style="color: #d0d0d0;">Installing pip...............done.</span></pre>
</div>
We have commanded our virtualenv to create a directory for our new project environment and call it <b>venv</b>. You could use any name here. it will indicate your projects name or whatever your fantasy is up to. Mine project directory now looks like this:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$ ls -l</span>
<span style="color: #d0d0d0;">total 9</span>
<span style="color: #d0d0d0;">drwxr-xr-x 6 garmoncheg staff 204B Jul 14 14:26 example/</span>
<span style="color: #d0d0d0;">-rw-r--r-- 1 garmoncheg staff 250B Jul 14 14:26 manage.py</span>
<span style="color: #d0d0d0;">drwxr-xr-x 6 garmoncheg staff 204B Jul 14 14:32 venv/</span></pre>
</div>
I have a mange.py script here, example directory with project files and a venv directory containig my environment files.<br />
Now we have created a directory for environment and put our environment in it. However system is not aware we are using this environment. We must activate it now. Doing that is easy enough.<br />Assuming you are in the same project directory and called the virtual environment we are creating "venv". Execute a command:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$ source venv/bin/activate</span>
<span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ </span></pre>
</div>
This will tell the system we are using the interpreter set we have just created. It is indicated with <b>(venv)</b> at the start of your terminal prompt. this means we are "inside" the environment now.<br />
Note we are in the same directory we where before.<br /><br />Lets familiarise ourselves with main virtualenv functionality now. Whats the main point of it?<br />Simple. All the "<b><i>pip install something</i></b>" made now in this terminal will install a Python package inside this venv folder, leaving the main system python files intact. You can have as many environment as you wish. You can install whatever Python package you want inside of that virtual environment.<br /><br />Now lets go through basic commands. Lets try to run our project now, assuming you have followed my previous instructions. To do that just type:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)$ ls</span>
<span style="color: #d0d0d0;">total 9</span>
<span style="color: #d0d0d0;">drwxr-xr-x 6 garmoncheg staff 204B Jul 14 14:26 example/</span>
<span style="color: #d0d0d0;">-rw-r--r-- 1 garmoncheg staff 250B Jul 14 14:26 manage.py</span>
<span style="color: #d0d0d0;">drwxr-xr-x 6 garmoncheg staff 204B Jul 14 14:32 venv/</span>
<span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ python manage.py runserver</span>
<span style="color: #d0d0d0;">Traceback (most recent call last):</span>
<span style="color: #d0d0d0;"> File "manage.py", line 8, in <module></span>
<span style="color: #d0d0d0;"> from django.core.management import execute_from_command_line</span>
<span style="color: #d0d0d0;">ImportError: No module named django.core.management</span></pre>
</div>
Whoops. We can not do that because there is no Django installed. Even though you have had it in system it does not seem to be present now.<br />
All the credits to virtualenv activation command. (<i>source path/to/activate/script</i>). We have to have it installed in the environment now. However it is more convenient to look for ourselves there is no Dango in environment. Lets execute:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ pip freeze</span>
<span style="color: #d0d0d0;">wsgiref==0.1.2</span></pre>
</div>
Tadaam. We only have wsgiref in our console environment now. Lets install django:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ pip install django</span>
<span style="color: #d0d0d0;">Downloading/unpacking django</span>
<span style="color: #d0d0d0;"> Downloading Django-1.6.5.tar.gz (6.6MB): 6.6MB downloaded</span>
<span style="color: #d0d0d0;"> Running setup.py egg_info for package django</span>
<span style="color: #d0d0d0;"> </span>
<span style="color: #d0d0d0;"> warning: no previously-included files matching '__pycache__' found under directory '*'</span>
<span style="color: #d0d0d0;"> warning: no previously-included files matching '*.py[co]' found under directory '*'</span>
<span style="color: #d0d0d0;">Installing collected packages: django</span>
<span style="color: #d0d0d0;"> Running setup.py install for django</span>
<span style="color: #d0d0d0;"> changing mode of build/scripts-2.7/django-admin.py from 644 to 755</span>
<span style="color: #d0d0d0;"> </span>
<span style="color: #d0d0d0;"> warning: no previously-included files matching '__pycache__' found under directory '*'</span>
<span style="color: #d0d0d0;"> warning: no previously-included files matching '*.py[co]' found under directory '*'</span>
<span style="color: #d0d0d0;"> changing mode of /Users/leopard/Developer/Python/Me/Tests/Projects/example/venv/bin/django-admin.py to 755</span>
<span style="color: #d0d0d0;">Successfully installed django</span>
<span style="color: #d0d0d0;">Cleaning up...</span></pre>
</div>
Tadaa. We have our django for the project now. Lets make sure with pip freeze:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ pip freeze</span>
<span style="color: #d0d0d0;">Django==1.6.5</span>
<span style="color: #d0d0d0;">wsgiref==0.1.2</span></pre>
</div>
And our project now can run inside a wrapper. Lets test with:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)leopard@garmoncheg:~/Projects/example$ python manage.py runserver</span>
<span style="color: #d0d0d0;">Validating models...</span>
<span style="color: #d0d0d0;">0 errors found</span>
<span style="color: #d0d0d0;">July 14, 2014 - 12:00:03</span>
<span style="color: #d0d0d0;">Django version 1.6.5, using settings 'example.settings'</span>
<span style="color: #d0d0d0;">Starting development server at http://127.0.0.1:8000/</span>
<span style="color: #d0d0d0;">Quit the server with CONTROL-C.</span></pre>
</div>
Yes it works.<br /><br />Cons here that we must activate a virtual environment each time we want to seriously interact with our project. So even to run it we need to activate it first. but it is really the only option to work with multiple project in a system in an easy way.<br />
<br />
To return the terminal to a proper state (back to system Python interpreter) you could just close it or deactivate the environment:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">(venv)garmoncheg:~/Projects/example$ deactivate</span>
<span style="color: #d0d0d0;">garmoncheg:~/Projects/example$ </span></pre>
</div>
Tadaa. (venv) preceding the terminal prompt is gone and we are back to the system interpreter.<br />
<br />
Hope this helps someone. Suggestions? Helped? Please comment! I will really appreciate all the info.<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-12031378646507184332014-06-12T13:14:00.000+03:002014-06-12T13:14:17.336+03:00Django CMS custom Plugin ManyToMany fields problems.<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuPhfBK0S9K-Zqk1sn0rjAJcKyWsAm619PClHDuMQeFiBDF0owAgBuX03H9Oz7iadpUl0LM7GzNflEmHQXRZRQBQCLgSeyY73XuGmX0OJvoEBzF-lhr6bdOpomefWODbXJebSTXWGt-vYX/s1600/5363429690_5cb8155275.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuPhfBK0S9K-Zqk1sn0rjAJcKyWsAm619PClHDuMQeFiBDF0owAgBuX03H9Oz7iadpUl0LM7GzNflEmHQXRZRQBQCLgSeyY73XuGmX0OJvoEBzF-lhr6bdOpomefWODbXJebSTXWGt-vYX/s1600/5363429690_5cb8155275.jpg" height="150" width="200" /></a></div>
Developing a website for Django CMS I have done a plugin. This plugin however have had a problem. It had an m2m field. While selecting images there (It was a gallery plugin). It was not saving it to production. This way main problem with this field was that plugin have displayed m2m choices on a draft page and while storing it to live it fails.<br />
Django CMS Pages is built like so it has multiple versions of pages. Each Page model that is changed is stored under new revision. And so plugin is copied and relinked to that page too. So plugin revisions multiply to.<br />
For e.g. in case you have a Draft page with two plugins that have model primary key number (pk in future) 12 and 14 accordingly. Say you hit publish changes. Not only PK of Page model rises and data are copypasted into new empty Page model instance. Those plugins are copied to. So mentioned plugins PK would change to 15 and 16 accordingly, assuming 14 is the latest plugin pk. New copied plugins will be linked to new page. Thats how things work in Django CMS.<br />
<br />
There is also a line in the CMS code stating in its comment that you need to override m2m storing by yourself. Somehow its omitted from basic Django CMS tutorials and I can only find it in the old versions documentation for now. SO THE SOLUTION TO ALL THIS:<br />
<br />
Say you have CMSPlugin a model for your custom plugin:<br />
<div style="background: rgb(32, 32, 32); border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">SelectImagePlugin</span><span style="color: #d0d0d0;">(CMSPlugin):</span>
<span style="color: #ed9d13;">"""Extension model for plugin class"""</span>
<span style="color: #d0d0d0;">display_text</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">models.BooleanField(</span><span style="color: #ed9d13;">'Project text overlay display'</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">images</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">models.ManyToManyField(Image)</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">copy_relations</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">old_instance):</span>
<span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.images</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">old_instance.images.all()</span></pre>
</div>
Here method<b> copy_relations</b> overrides default empty method.<br />
For foreign keys it is described another behaviour and copy_relations mappings. However Foreign keys were working like intended by themselves in my plugins. SO I believe info about them is outdated a bit.<br />Otherwise it may be useful to read about it in official docs.<br /><a href="http://django-cms.readthedocs.org/en/latest/extending_cms/custom_plugins.html#handling-relations" rel="nofollow" style="background-color: white; color: #4a6b82; cursor: pointer; font-family: arial, sans-serif; font-size: 13px; text-decoration: none;">http://django-cms.readthedocs.org/en/latest/extending_cms/custom_plugins.html#handling-relations</a><br />
Thats it. Hope it will help someone like myself to solve a problem like this in a timely manner.<br />
Comments? Suggestions?<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com2tag:blogger.com,1999:blog-8227451082901531762.post-39835019042093129462014-05-09T11:42:00.000+03:002014-05-09T11:42:48.700+03:00Implementing a Multiple (Radio) Select + “Other” widget in Django<div dir="ltr" style="text-align: left;" trbidi="on">
I have had a task to implement Radio Select field with "Other" choice field in a Django Model Form. Here is my implementation in case someone would benefit from it. The idea is to have it all stored to Django's CharField type of data and have a preselected set of fields. We have a model:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># models.py</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">Entry</span><span style="color: #d0d0d0;">(models.Model):</span>
<span style="color: #d0d0d0;">SET_OF_CHOICES</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">(</span>
<span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'choice1'</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">'choice1'</span><span style="color: #d0d0d0;">),</span>
<span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'choice2'</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">'choice2'</span><span style="color: #d0d0d0;">),</span>
<span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'choice3'</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">'choice3'</span><span style="color: #d0d0d0;">),</span>
<span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">'Other'</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">'Other Please Specify'</span><span style="color: #d0d0d0;">),</span>
<span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">choice</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">models.CharField(_(</span><span style="color: #ed9d13;">"Selected your choice"</span><span style="color: #d0d0d0;">),</span> <span style="color: #d0d0d0;">max_length=</span><span style="color: #3677a9;">250</span><span style="color: #d0d0d0;">)</span></pre>
</div>
That makes it ready for the set of fields for for our form. We are overriding Model form default field for this type of data (CharField) by intentionally specifying field with the same name.<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># forms.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.forms</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">ModelForm,</span> <span style="color: #d0d0d0;">ChoiceField,</span> <span style="color: #d0d0d0;">RadioSelect</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">models</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">Entry</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">fields</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">ChoiceWithOtherField</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">EntryForm</span><span style="color: #d0d0d0;">(ModelForm):</span>
<span style="color: #d0d0d0;">choice</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">ChoiceWithOtherField(label=_(</span><span style="color: #ed9d13;">"Selected your choice"</span><span style="color: #d0d0d0;">),</span> <span style="color: #d0d0d0;">choices=Entry.SET_OF_CHOICES)</span></pre>
</div>
Note the field.py import here. We are using custom form field here. It is a modified version of Django's<br />
MultiValueField.<br />
Here is the fields snippet:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># fields.py</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">newforms</span> <span style="color: #6ab825; font-weight: bold;">as</span> <span style="color: #d0d0d0;">forms</span>
<span style="color: #6ab825; font-weight: bold;">from</span> <span style="color: #447fcf; text-decoration: underline;">django.utils.encoding</span> <span style="color: #6ab825; font-weight: bold;">import</span> <span style="color: #d0d0d0;">force_unicode</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">ChoiceWithOtherRenderer</span><span style="color: #d0d0d0;">(forms.RadioSelect.renderer):</span>
<span style="color: #ed9d13;">"""RadioFieldRenderer that renders its last choice with a placeholder."""</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">__init__</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">*args,</span> <span style="color: #d0d0d0;">**kwargs):</span>
<span style="color: #24909d;">super</span><span style="color: #d0d0d0;">(ChoiceWithOtherRenderer,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">).__init__(*args,</span> <span style="color: #d0d0d0;">**kwargs)</span>
<span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.choices,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.other</span> <span style="color: #d0d0d0;">=</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.choices[:-</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">],</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.choices[-</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">]</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">__iter__</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">):</span>
<span style="color: #6ab825; font-weight: bold;">for</span> <span style="color: #24909d;">input</span> <span style="color: #6ab825; font-weight: bold;">in</span> <span style="color: #24909d;">super</span><span style="color: #d0d0d0;">(ChoiceWithOtherRenderer,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">).__iter__():</span>
<span style="color: #6ab825; font-weight: bold;">yield</span> <span style="color: #24909d;">input</span>
<span style="color: #24909d;">id</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">'%s_%s'</span> <span style="color: #d0d0d0;">%</span> <span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.attrs[</span><span style="color: #ed9d13;">'id'</span><span style="color: #d0d0d0;">],</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.other[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">])</span> <span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #ed9d13;">'id'</span> <span style="color: #6ab825; font-weight: bold;">in</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.attrs</span> <span style="color: #6ab825; font-weight: bold;">else</span> <span style="color: #ed9d13;">''</span>
<span style="color: #d0d0d0;">label_for</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">' for="%s"'</span> <span style="color: #d0d0d0;">%</span> <span style="color: #24909d;">id</span> <span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #24909d;">id</span> <span style="color: #6ab825; font-weight: bold;">else</span> <span style="color: #ed9d13;">''</span>
<span style="color: #d0d0d0;">checked</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">''</span> <span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #6ab825; font-weight: bold;">not</span> <span style="color: #d0d0d0;">force_unicode(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.other[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">])</span> <span style="color: #d0d0d0;">==</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.value</span> <span style="color: #6ab825; font-weight: bold;">else</span> <span style="color: #ed9d13;">'checked="true" '</span>
<span style="color: #6ab825; font-weight: bold;">yield</span> <span style="color: #ed9d13;">'<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s'</span> <span style="color: #d0d0d0;">%</span> <span style="color: #d0d0d0;">(</span>
<span style="color: #d0d0d0;">label_for,</span> <span style="color: #24909d;">id</span><span style="color: #d0d0d0;">,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.other[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">],</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.name,</span> <span style="color: #d0d0d0;">checked,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.other[</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">])</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">ChoiceWithOtherWidget</span><span style="color: #d0d0d0;">(forms.MultiWidget):</span>
<span style="color: #ed9d13;">"""MultiWidget for use with ChoiceWithOtherField."""</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">__init__</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">choices):</span>
<span style="color: #d0d0d0;">widgets</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">[</span>
<span style="color: #d0d0d0;">forms.RadioSelect(choices=choices,</span> <span style="color: #d0d0d0;">renderer=ChoiceWithOtherRenderer),</span>
<span style="color: #d0d0d0;">forms.TextInput</span>
<span style="color: #d0d0d0;">]</span>
<span style="color: #24909d;">super</span><span style="color: #d0d0d0;">(ChoiceWithOtherWidget,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">).__init__(widgets)</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">decompress</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">value):</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #6ab825; font-weight: bold;">not</span> <span style="color: #d0d0d0;">value:</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">[</span><span style="color: #24909d;">None</span><span style="color: #d0d0d0;">,</span> <span style="color: #24909d;">None</span><span style="color: #d0d0d0;">]</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">value</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">format_output</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">rendered_widgets):</span>
<span style="color: #ed9d13;">"""Format the output by substituting the "other" choice into the first widget."""</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">rendered_widgets[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">]</span> <span style="color: #d0d0d0;">%</span> <span style="color: #d0d0d0;">rendered_widgets[</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">]</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">ChoiceWithOtherField</span><span style="color: #d0d0d0;">(forms.MultiValueField):</span>
<span style="color: #ed9d13;">"""</span>
<span style="color: #ed9d13;"> ChoiceField with an option for a user-submitted "other" value.</span>
<span style="color: #ed9d13;"> The last item in the choices array passed to __init__ is expected to be a choice for "other". This field's</span>
<span style="color: #ed9d13;"> cleaned data is a tuple consisting of the choice the user made, and the "other" field typed in if the choice</span>
<span style="color: #ed9d13;"> made was the last one.</span>
<span style="color: #ed9d13;"> >>> class AgeForm(forms.Form):</span>
<span style="color: #ed9d13;"> ... age = ChoiceWithOtherField(choices=[</span>
<span style="color: #ed9d13;"> ... (0, '15-29'),</span>
<span style="color: #ed9d13;"> ... (1, '30-44'),</span>
<span style="color: #ed9d13;"> ... (2, '45-60'),</span>
<span style="color: #ed9d13;"> ... (3, 'Other, please specify:')</span>
<span style="color: #ed9d13;"> ... ])</span>
<span style="color: #ed9d13;"> ...</span>
<span style="color: #ed9d13;"> >>> # rendered as a RadioSelect choice field whose last choice has a text input</span>
<span style="color: #ed9d13;"> ... print AgeForm()['age']</span>
<span style="color: #ed9d13;"> <ul></span>
<span style="color: #ed9d13;"> <li><label for="id_age_0_0"><input type="radio" id="id_age_0_0" value="0" name="age_0" /> 15-29</label></li></span>
<span style="color: #ed9d13;"> <li><label for="id_age_0_1"><input type="radio" id="id_age_0_1" value="1" name="age_0" /> 30-44</label></li></span>
<span style="color: #ed9d13;"> <li><label for="id_age_0_2"><input type="radio" id="id_age_0_2" value="2" name="age_0" /> 45-60</label></li></span>
<span style="color: #ed9d13;"> <li><label for="id_age_0_3"><input type="radio" id="id_age_0_3" value="3" name="age_0" /> Other, please \\</span>
<span style="color: #ed9d13;">specify:</label> <input type="text" name="age_1" id="id_age_1" /></li></span>
<span style="color: #ed9d13;"> </ul></span>
<span style="color: #ed9d13;"> >>> form = AgeForm({'age_0': 2})</span>
<span style="color: #ed9d13;"> >>> form.is_valid()</span>
<span style="color: #ed9d13;"> True</span>
<span style="color: #ed9d13;"> >>> form.cleaned_data</span>
<span style="color: #ed9d13;"> {'age': (u'2', u'')}</span>
<span style="color: #ed9d13;"> >>> form = AgeForm({'age_0': 3, 'age_1': 'I am 10 years old'})</span>
<span style="color: #ed9d13;"> >>> form.is_valid()</span>
<span style="color: #ed9d13;"> True</span>
<span style="color: #ed9d13;"> >>> form.cleaned_data</span>
<span style="color: #ed9d13;"> {'age': (u'3', u'I am 10 years old')}</span>
<span style="color: #ed9d13;"> >>> form = AgeForm({'age_0': 1, 'age_1': 'This is bogus text which is ignored since I didn\\\\'t pick "other"'})</span>
<span style="color: #ed9d13;"> >>> form.is_valid()</span>
<span style="color: #ed9d13;"> True</span>
<span style="color: #ed9d13;"> >>> form.cleaned_data</span>
<span style="color: #ed9d13;"> {'age': (u'1', u'')}</span>
<span style="color: #ed9d13;"> """</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">__init__</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">*args,</span> <span style="color: #d0d0d0;">**kwargs):</span>
<span style="color: #d0d0d0;">fields</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">[</span>
<span style="color: #d0d0d0;">forms.ChoiceField(widget=forms.RadioSelect(renderer=ChoiceWithOtherRenderer),</span> <span style="color: #d0d0d0;">*args,</span> <span style="color: #d0d0d0;">**kwargs),</span>
<span style="color: #d0d0d0;">forms.CharField(required=</span><span style="color: #24909d;">False</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">]</span>
<span style="color: #d0d0d0;">widget</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">ChoiceWithOtherWidget(choices=kwargs[</span><span style="color: #ed9d13;">'choices'</span><span style="color: #d0d0d0;">])</span>
<span style="color: #d0d0d0;">kwargs.pop(</span><span style="color: #ed9d13;">'choices'</span><span style="color: #d0d0d0;">)</span>
<span style="color: #24909d;">self</span><span style="color: #d0d0d0;">._was_required</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">kwargs.pop(</span><span style="color: #ed9d13;">'required'</span><span style="color: #d0d0d0;">,</span> <span style="color: #24909d;">True</span><span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">kwargs[</span><span style="color: #ed9d13;">'required'</span><span style="color: #d0d0d0;">]</span> <span style="color: #d0d0d0;">=</span> <span style="color: #24909d;">False</span>
<span style="color: #24909d;">super</span><span style="color: #d0d0d0;">(ChoiceWithOtherField,</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">).__init__(widget=widget,</span> <span style="color: #d0d0d0;">fields=fields,</span> <span style="color: #d0d0d0;">*args,</span> <span style="color: #d0d0d0;">**kwargs)</span>
<span style="color: #6ab825; font-weight: bold;">def</span> <span style="color: #447fcf;">compress</span><span style="color: #d0d0d0;">(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">value):</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #24909d;">self</span><span style="color: #d0d0d0;">._was_required</span> <span style="color: #6ab825; font-weight: bold;">and</span> <span style="color: #6ab825; font-weight: bold;">not</span> <span style="color: #d0d0d0;">value</span> <span style="color: #6ab825; font-weight: bold;">or</span> <span style="color: #d0d0d0;">value[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">]</span> <span style="color: #6ab825; font-weight: bold;">in</span> <span style="color: #d0d0d0;">(</span><span style="color: #24909d;">None</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">''</span><span style="color: #d0d0d0;">):</span>
<span style="color: #6ab825; font-weight: bold;">raise</span> <span style="color: #d0d0d0;">forms.ValidationError(</span><span style="color: #24909d;">self</span><span style="color: #d0d0d0;">.error_messages[</span><span style="color: #ed9d13;">'required'</span><span style="color: #d0d0d0;">])</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #6ab825; font-weight: bold;">not</span> <span style="color: #d0d0d0;">value:</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">[</span><span style="color: #24909d;">None</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">u''</span><span style="color: #d0d0d0;">]</span>
<span style="color: #999999; font-style: italic;"># Patch to override model specific other choice and return CharField value instead of choice tuple</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #d0d0d0;">value[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">]</span> <span style="color: #d0d0d0;">==</span> <span style="color: #ed9d13;">'Other'</span><span style="color: #d0d0d0;">:</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">value[</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">]</span>
<span style="color: #6ab825; font-weight: bold;">else</span><span style="color: #d0d0d0;">:</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">value[</span><span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">]</span>
<span style="color: #999999; font-style: italic;"># Use this for field to return tuple</span>
<span style="color: #999999; font-style: italic;">#return value[0], value[1] if force_unicode(value[0]) == force_unicode(self.fields[0].choices[-1][0]) else u''</span></pre>
</div>
It is based on the code from the <a href="https://djangosnippets.org/snippets/863/">snippet by sciyoshi</a>. It is put here because there are some modifications to in inline with idea that things could easily disappear without a trace through the internet.<br />
Anyway it will show something like this in the end:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL-ldH0h5thkGAd-V3pOV4htsmRqVF2qhRFwaAspbiai7UHcBVPYgYO-1NnzKWPurvLhtzZEK2CuwfMdqSXu7S_3nF_ju7zTDbjdFDNRfOaPojo6FibvcOFc_OxDiwyNJZYl28dgzHkZtJ/s1600/ch1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL-ldH0h5thkGAd-V3pOV4htsmRqVF2qhRFwaAspbiai7UHcBVPYgYO-1NnzKWPurvLhtzZEK2CuwfMdqSXu7S_3nF_ju7zTDbjdFDNRfOaPojo6FibvcOFc_OxDiwyNJZYl28dgzHkZtJ/s1600/ch1.png" height="115" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
It's up to your imagination to style it now. Hope this howto helps someone with similar problem to save some time.</div>
</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com4tag:blogger.com,1999:blog-8227451082901531762.post-19401151189886761562014-05-01T18:39:00.001+03:002014-05-01T18:39:58.004+03:00How to delete a remote git tag<div dir="ltr" style="text-align: left;" trbidi="on">
I'm always forgetting this. So decided to put it here for someone's benefit.<br />
<br />
I have the git tag added by command:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">git</span> <span style="color: #d0d0d0;">tag</span> <span style="color: #d0d0d0;">-a</span> <span style="color: #3677a9;">1.2</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">0</span> <span style="color: #d0d0d0;">-m</span> <span style="color: #ed9d13;">"1.2.0"</span></pre>
</div>
this means my tags tree will be updated with the tag 1.2.0 and message 1.2.0<br />Usually it marks the version of the build/release.<br />
<br />
I now push a tag to origin by command:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">git</span> <span style="color: #d0d0d0;">push</span> <span style="color: #d0d0d0;">origin</span> <span style="color: #d0d0d0;">--tags</span></pre>
</div>
It is possible to see it at my repository github tagged.<br /><br />Time now to delete a tag.<br />It can be done by command:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">git</span> <span style="color: #d0d0d0;">tag</span> <span style="color: #d0d0d0;">-d</span> <span style="color: #3677a9;">1.2</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">0</span></pre>
</div>
This will remove a local tag 1.2.0. Leaving origin intact. Pushing tags to origin does not give anything.<br />To remove a remote tag now it is required to execute command:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">git</span> <span style="color: #d0d0d0;">push</span> <span style="color: #d0d0d0;">origin</span> <span style="color: #d0d0d0;">:refs/tags/</span><span style="color: #3677a9;">1.2</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">0</span></pre>
</div>
It will remove tag 1.2.0 at origin. This is the only way how to move tags to another commits.<br />
<br /></div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-64926548764953614042014-04-28T12:03:00.001+03:002014-04-28T12:03:17.241+03:00Pillow compile error clang: -Wno-error=unused-command-line-argument-hard-error-in-future fix<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQmlrIdq6ZjQFy5imrDY_LA_7mmWpX5iFhaEYD-kJ6eXuWjnHnIIfyt7TgTGUUyVFs648dGLl-q19qewNulDFGQHumEYOxXUmaKdbVq-Nx5zAAagvxNmFK0oQWpem4raMWMZLsqa7pysgL/s1600/pillow+(1).png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQmlrIdq6ZjQFy5imrDY_LA_7mmWpX5iFhaEYD-kJ6eXuWjnHnIIfyt7TgTGUUyVFs648dGLl-q19qewNulDFGQHumEYOxXUmaKdbVq-Nx5zAAagvxNmFK0oQWpem4raMWMZLsqa7pysgL/s1600/pillow+(1).png" height="140" width="200" /></a></div>
<br />
I have had a problem with compiling Pillow recently. the error was with Pillow/Pil compilation.<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">pillow</span> <span style="color: #d0d0d0;">install</span> <span style="color: #d0d0d0;">error</span> <span style="color: #d0d0d0;">clang:</span> <span style="color: #d0d0d0;">error:</span> <span style="color: #d0d0d0;">unknown</span> <span style="color: #d0d0d0;">argument:</span>
<span style="color: #ed9d13;">'-mno-fused-madd'</span>
<span style="color: #d0d0d0;">[-Wunused-command-line-argument-hard-error-</span><span style="color: #6ab825; font-weight: bold;">in</span><span style="color: #d0d0d0;">-future]</span></pre>
</div>
Apple updated command line tools. So the cc command was updated too.<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">gcc</span> <span style="color: #d0d0d0;">--version</span>
<span style="color: #d0d0d0;">Configured</span> <span style="color: #6ab825; font-weight: bold;">with</span><span style="color: #d0d0d0;">:</span> <span style="color: #d0d0d0;">--prefix=</span><span style="background-color: #e3d2d2; color: #a61717;">/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1</span>
<span style="color: #d0d0d0;">Apple</span> <span style="color: #d0d0d0;">LLVM</span> <span style="color: #d0d0d0;">version</span> <span style="color: #3677a9;">5.1</span> <span style="color: #d0d0d0;">(clang-</span><span style="color: #3677a9;">503.0</span><span style="color: #d0d0d0;">.</span><span style="color: #3677a9;">38</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">(based</span> <span style="color: #d0d0d0;">on</span> <span style="color: #d0d0d0;">LLVM</span> <span style="color: #3677a9;">3.4</span><span style="color: #d0d0d0;">svn)</span>
<span style="color: #d0d0d0;">Target:</span> <span style="color: #d0d0d0;">x86_64-apple-darwin13.</span><span style="color: #3677a9;">1.0</span>
<span style="color: #d0d0d0;">Thread</span> <span style="color: #d0d0d0;">model:</span> <span style="color: #d0d0d0;">posix</span></pre>
</div>
The bug is in GCC. It is quite serious because those flags support will be dropped in future. Fortunately there is a worakround for now:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #6ab825; font-weight: bold;">export</span> <span style="color: #d0d0d0;">ARCHFLAGS=</span><span style="color: #ed9d13;">"-Wno-error=unused-command-line-argument-hard-error-in-future"</span></pre>
</div>
It works for Pillow 2.4.0 and I can compile it with Apple LLVM 5.1 (That is current now), as of Xcode 5.1.<br />
Hope my findings will help someone.</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0tag:blogger.com,1999:blog-8227451082901531762.post-28512003347477410882014-02-03T19:45:00.000+02:002014-02-03T19:45:00.959+02:00Django: adding additional Admin static and writing JS snippets for Django Admin<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS8pi5l620i9ZlxfsArC_oyPolnz-h9Mj52Zu7jUq-HlyroFVjuU01uTodXJS_EYgyLtfbd4Uatx2qfVgCi4LyTdFJiydLlR64bGh_NBnDQTSpfnQce8E9Yh3VgE3cSjenVlZeBwLFBf_B/s1600/django-folder.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS8pi5l620i9ZlxfsArC_oyPolnz-h9Mj52Zu7jUq-HlyroFVjuU01uTodXJS_EYgyLtfbd4Uatx2qfVgCi4LyTdFJiydLlR64bGh_NBnDQTSpfnQce8E9Yh3VgE3cSjenVlZeBwLFBf_B/s1600/django-folder.jpg" height="159" width="200" /></a></div>
It often gets that you need it because you invent something that is meant to be displayed for admin. E.g. some nasty form field or something. Here is my recipe to add some additional Django static to your admin.<br />
<br />
Rather than writing a <a href="https://docs.djangoproject.com/en/dev/ref/forms/widgets/">widget</a>, that is more proper way here... I was using a widget already (from another package). So I could not use it properly, at least without a ton of overrides and complexity it leads to. SO I've decided to add the JS functionality to override a lack of backend.<br />
<br />
First of all we should add the javascript/css like so:<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #999999; font-style: italic;"># admin.py</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">MyModelAdmin</span><span style="color: #d0d0d0;">(admin.ModelAdmin):</span>
<span style="color: #999999; font-style: italic;"># admin additions</span>
<span style="color: #6ab825; font-weight: bold;">class</span> <span style="color: #447fcf; text-decoration: underline;">Media</span><span style="color: #d0d0d0;">:</span>
<span style="color: #d0d0d0;">css</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #ed9d13;">"all"</span><span style="color: #d0d0d0;">:</span> <span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"css/my_style.css"</span><span style="color: #d0d0d0;">,)</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">js</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"js/my_script.js"</span><span style="color: #d0d0d0;">,)</span></pre>
</div>
This add should list your files, loaded in the <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/">admin</a>. So you can access them and see in the Django admin frontend itself. Like so:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1dME6g_rYzRUr5GidEMQYHZzHnsBy1_FTFKMbQCQ7fiLKg44jOBLo1eHhOafvkYumW98ZygCsA3q4JbG55J4ts6OXN8Q-NON4zVhBezWrQWNcdGZxFMc09jjTK-MTJPoxytaGXvO3LKO/s1600/Screen+Shot+2014-02-03+at+6.59.25+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1dME6g_rYzRUr5GidEMQYHZzHnsBy1_FTFKMbQCQ7fiLKg44jOBLo1eHhOafvkYumW98ZygCsA3q4JbG55J4ts6OXN8Q-NON4zVhBezWrQWNcdGZxFMc09jjTK-MTJPoxytaGXvO3LKO/s1600/Screen+Shot+2014-02-03+at+6.59.25+PM.png" /></a></div>
Now that your script and style are loaded you could just hack anything you want dynamically. Django admin already has a jQuery attached, so you can do whatever you want with it. But there is a problem. You can not just do <i><b>$(....... your code</b></i>. This simply does not work and will get error like this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigKlmqFPoUTZioH4oyeIkb-0I-3nul0W_Gu1ZHP__BZ9XIK3edRXzdqDNjxLQhmtn1h7d28HDgK7Msfi2bAzyHjjQK8NJkT0q58MinEElG1l2WXddYXi2oJxsXniJMy8JF2eCatu9kKbCt/s1600/Screen+Shot+2014-02-03+at+7.04.17+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigKlmqFPoUTZioH4oyeIkb-0I-3nul0W_Gu1ZHP__BZ9XIK3edRXzdqDNjxLQhmtn1h7d28HDgK7Msfi2bAzyHjjQK8NJkT0q58MinEElG1l2WXddYXi2oJxsXniJMy8JF2eCatu9kKbCt/s1600/Screen+Shot+2014-02-03+at+7.04.17+PM.png" height="290" width="640" /></a></div>
(<span style="box-sizing: border-box; color: red; font-family: Menlo, monospace; font-size: 11px; line-height: 12px; white-space: pre-wrap;">Uncaught TypeError: Property '$' of object [object Object] is not a function</span>)<br />
There is no usual jQuery namespace there. but there is a simple hack.<br />
<div style="background-color: #202020; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; color: #333333; font-family: Verdana, Helvetica, Arial, sans-serif; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #6ab825; font-weight: bold;">var</span> <span style="color: #d0d0d0;">$</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">django.jQuery;</span>
<span style="color: #999999; font-style: italic;">// your usual jQuery code goes here</span>
<span style="color: #999999; font-style: italic;">// e.g.:</span>
<span style="color: #999999; font-style: italic;">// $(document).ready(function() {</span>
<span style="color: #999999; font-style: italic;">// $('#admin_big_image').wrap('<div class="mrmen-b">');</span>
<span style="color: #999999; font-style: italic;">// });</span></pre>
</div>
Thats all. Yu may improvise. E.g. dynamically create or alter DOM elements and manipulate them. Im my case it was a simple Admin banner overlay into image displayed by 3-d party django plugin.<br />
Imagination is the limit.<br />
<br />
External links:<br />
<a href="http://stackoverflow.com/questions/4709298/difficulty-with-django-and-jquery-why-is-undefined-in-the-admin-app">http://stackoverflow.com/questions/4709298/difficulty-with-django-and-jquery-why-is-undefined-in-the-admin-app</a> About what may be wrong with your scripts<br />
<a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-asset-definitions">https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-asset-definitions</a> About whee is this idea taken from in Django docs.<br />
<br />
Suggestions? Wrong? Comment here!</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com1tag:blogger.com,1999:blog-8227451082901531762.post-54686707095566758272014-01-02T20:41:00.000+02:002014-01-02T20:51:35.141+02:00Lightning unofficial cable trick for iOS 7<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOBosyAbIRMrl3HughRzIetHv0GO9kY97tWZB5Dxap2_yEIii83HHzZsDxfbREKPw_-gDiBNGGGbZcinP6JIsvA62dSohSfleB6qALZQHr03a7oFy45ByT65wZ9VINr_CB4OkTBsHImoBG/s1600/lghtn.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOBosyAbIRMrl3HughRzIetHv0GO9kY97tWZB5Dxap2_yEIii83HHzZsDxfbREKPw_-gDiBNGGGbZcinP6JIsvA62dSohSfleB6qALZQHr03a7oFy45ByT65wZ9VINr_CB4OkTBsHImoBG/s640/lghtn.jpg" width="640" /></a></div>
I have found a hack of how to firs time sync your iphone via unofficial (cheap Chinese) cable.<br />
It may be a hint to you if you are buying an iPhone from a second hand without accessories.<br />
<br />
You will need TADAA! Official Apple cable but not for a lightning port. And another Apple device.<br />
<br />
The thing is if you connect both your new iPhone or iPad via lightning port and using unofficial cable and ANY of your Apple devices using OFFICIAL Apple cable. It will trust your lightning connected device.<br />
<br />
Some magic happens and one device connected with official apple cord makes another device connected via official cord too.<br />
<br />
TADAA. Now you can sync at least once... and use Wi-Fi sync later on...<br />
<br />
Hopoe it helps you. Comments?</div>
garmoncheghttp://www.blogger.com/profile/01374837358090129603noreply@blogger.com0