Jekyll2023-06-20T18:01:47+00:00https://taranjeet.co/feed.xmlTaranjeet SinghLearning Path for a Computer Science Student2019-06-08T11:30:00+00:002019-06-08T11:30:00+00:00https://taranjeet.co/learning-path-for-a-computer-science-student<p>This article is written for a student pursuing graduation in computer science for a duration of 4 years. It provides a learning path for a good career in software development, which can be either of the following:</p>
<ul>
<li>
<p>Working for an early stage or high growth startup</p>
</li>
<li>
<p>Working for a big MNC</p>
</li>
</ul>
<p>This article assumes the following:</p>
<ul>
<li>
<p>There can be many achievements for a computer science student, but it mainly focuses on a good career in software development.</p>
</li>
<li>
<p>A good career in software development means either working for an early stage or a high growth startup or working for a big MNC.</p>
</li>
<li>
<p>This article does not suggest to skip the college syllabus. In fact, it suggests how to put efforts alongside your college curriculum.</p>
</li>
<li>
<p>This article does not provide a learning path for any specialized roles like Machine Learning Engineer, or Data Scientist. However, it tries providing an optimum path for students interested in Software engineering roles.</p>
</li>
<li>
<p>This article is written keeping in mind Computer Science graduates, but it is not strict about it. It can be used by anyone interested in pursuing a career in software development.</p>
</li>
<li>
<p>It does not provide any suggestion for “resources”. You can find the resources by doing a Google search for “how to learn X”.</p>
</li>
<li>
<p>Last, this article is just a suggestion of how should you structure yourself, so that you are more aware of how to plan and put your efforts during your graduation course.</p>
</li>
</ul>
<p>In most of the tech companies, an entry-level software engineer role expects the following:</p>
<ul>
<li>
<p>Good knowledge of algorithms and data structures, so that you can pick up things on the fly and are able to comprehend most of the logical things.</p>
</li>
<li>
<p>An understanding and knowledge of the language and frameworks used in the company. It’s better if you know.</p>
</li>
</ul>
<p>Before we begin, let’s understand how is the graduation course generally structured. A 4-year programme is divided into 8 semesters, with a break of 1–3 months in between. Most of the courses run the class(around 8 hours) 6 days a week, with some half days(4 hours). This also includes the practical implementation part a.k.a Labs related to the courses you take.</p>
<p>Let’s first plan out the time of how and when can you spend your time in following this learning path. We will call this as your additional time. You can spend your time in the following way:</p>
<ul>
<li>
<p>2 hours per day, on weekdays(Monday - Friday)</p>
</li>
<li>
<p>4 hours per day, on weekends(Saturday, Sunday)</p>
</li>
</ul>
<p>For each day, you can split it into shifts, like morning and evening.</p>
<ul>
<li>
<p>1 hour per day, on weekdays, in Morning</p>
</li>
<li>
<p>1 hour per day, on weekdays, in Evening</p>
</li>
<li>
<p>2 hours per day, on weekends, in Morning</p>
</li>
<li>
<p>2 hours per day, on weekends, in Evening.</p>
</li>
</ul>
<p>However, this is just an outline and you are free to structure your day/week in whatever way you want to.</p>
<p>Also, for better understanding and be clear with your goals, the semesters are divided into the following categories</p>
<ul>
<li>
<p><strong>Maker</strong> - This means that the entire focus is on building a product. The product can be as simple as a static web page to as complex as a chat application. It is also important to understand that here learning will be there, but it will be mainly driven towards building a product.</p>
</li>
<li>
<p><strong>Learner</strong> - This means that the entire focus is on learning new stuff. It will focus less on creating products and more on building your base and depth about concepts.</p>
</li>
<li>
<p><strong>Exposure</strong> - This will consist mainly of interactions with the community and learning/making by observing others or collaborating with others.</p>
</li>
</ul>
<p>Let’s us begin of how you should put additional efforts alongside your semester syllabus to have a better career in software development.</p>
<h3 id="first-semestermaker">First Semester [Maker]</h3>
<p>In this semester, learn HTML, CSS. You should learn how to build static web pages. If you are running out of ideas, of what to build, then start creating static pages of popular and frequently used websites, like Twitter, GitHub, Medium, HackerNews.</p>
<p>Next, you should learn how to use git and GitHub. It’s very important and will be used throughout your entire career in software development. Also, commit all the code that you create during this semester to your GitHub account.</p>
<p>You can learn JavaScript and jQuery if you want to add some interactivity to the pages. This is additional.</p>
<p>You can participate in international challenges like <a href="https://www.100daysofcode.com/">100 days of code</a>. This gives you a community of like minded people willing to learn and helps you in case you get stuck.</p>
<p><strong>Time:</strong> Spend all of your additional time in learning frontend development.</p>
<h3 id="second-semestermaker">Second Semester[Maker]</h3>
<p>In this semester, learn Backend development. You can pick up any language like Javascript, Php, Python, Ruby or Java. The choice of framework is also yours. But the main focus here should be able to create fully functional dynamic apps.</p>
<p>At this point, you can also start participating in hackathons with your fellow peers and learn more about building products in a time restricted manner and working in a team.</p>
<p><strong>Time:</strong> Spend all of your additional time in learning backend development</p>
<h3 id="third-semesterlearner-maker">Third Semester[Learner + Maker]</h3>
<p>This semester, you should focus on learning data structures and algorithms. You can try competitive programming to learn. It gives you an environment and a community. Or you can learn algorithms by reading and implementing them.</p>
<p>Apart from this, also focus on your web development projects. Keep participating in hackathons and building side projects on ideas that fascinate you.</p>
<p><strong>Time:</strong></p>
<ul>
<li>
<p>Spend 30% of your time in making products(3 hours per day on weekends).</p>
</li>
<li>
<p>Spend 70% of your time in algorithms(rest of the additional time).</p>
</li>
</ul>
<h3 id="fourth-semesterexposure">Fourth Semester[Exposure]</h3>
<p>This semester, start contributing to open source projects on framework/language of your own choice. You can use <a href="https://github.com/trending">GitHub trending projects</a> or <a href="https://summerofcode.withgoogle.com/archive/">GSOC past projects</a> to select a project.</p>
<p>Also, you should participate in GSoC. At least, spend some time with an organization, understand their codebase and fix some issues. If you are excited by what they are solving, then write a GSOC proposal on a project idea. This will help you learn more about how to plan out the development, how to manage yourself, and how to be an efficient communicator.</p>
<p>Apart from this, keep sharpening your algorithm skills.</p>
<p><strong>Time:</strong></p>
<ul>
<li>
<p>Spend 30% of your time in algorithms(1 hour a day, for 6 days a week)</p>
</li>
<li>
<p>Spend 70% of your time in open source(rest of the additional time)</p>
</li>
</ul>
<h3 id="fifth-semester-learner-maker">Fifth Semester [Learner + Maker]</h3>
<p>This semester, you need to balance and focus on most of the things you have done until now. Spend some of your time(30%) in refining your algorithm skills. Spend 40% of your time in going deep in maker skills(frontend or backend development or both).</p>
<p>Spend the last 30% in open source stuff. For open source, you can contribute to some projects or publish packages of your own. In fact, one suggestion for this can be to create an open source repo of algorithms in a language of your own choice. This will deepen your knowledge of algorithms, help you learn more about the caveats of a language and help understand how to collaborate and maintain an open source project.</p>
<p><strong>Time:</strong></p>
<ul>
<li>
<p>Spend 30% of your time in algorithms(1 hour a day, for 6 days a week, in the morning).</p>
</li>
<li>
<p>Spend 30% of your time in open source(1 hour a day, for 6 days a week, in the evening).</p>
</li>
<li>
<p>Spend the remaining 40% of your time in maker stuff(rest of the additional time).</p>
</li>
</ul>
<h3 id="sixth-semesterlearner-maker">Sixth Semester[Learner + Maker]</h3>
<p>This semester, spend time(50%) in preparing and practising algorithms, the next 40% time in building stuff. In fact, this time can be used to apply to GSoC as well.</p>
<p>At last, spend remaining 10% of your time in learning essentials skills for an interview like resume and portfolio building, and preparing for managerial round interview questions.</p>
<p><strong>Time:</strong></p>
<ul>
<li>
<p>Spend 50% of your time in algorithms(1 hour per day on weekdays, 2 hours per day on weekends).</p>
</li>
<li>
<p>Spend 40% of your time in building stuff(1 hour per day on weekdays, 2 hours on Saturday).</p>
</li>
<li>
<p>Spend 10% of your time in essential skills(2 hours on Sunday).</p>
</li>
</ul>
<h3 id="seventh-semesterexposure">Seventh Semester[Exposure]</h3>
<p>This semester, spend entire of your time in preparing for job interviews and securing a job. This will require you to visit each of the skills learned above and balance them.</p>
<p><strong>Time:</strong> Spend all of your additional time in this.</p>
<h3 id="eight-semesterexposure">Eight Semester[Exposure]</h3>
<p>This semester, spend time preparing for interviews if not placed. If you are placed, then you should spend time expanding your overall knowledge about software development. You should learn <a href="https://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development</a> and <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">Object-Oriented Programming</a>(if not learned until now). You should learn Deploying applications on cloud providers like AWS or Heroku. You should participate in local meetups of your preferred language and should give a talk. You can also use this time to explore other frontend frameworks like React, Vue or Angular.</p>
<p><strong>Time:</strong> Spend all of your additional time in this.</p>
<h3 id="conclusion">Conclusion</h3>
<p>This article suggests a leaning path for a career in software development, which can be followed alongside the curriculum of the college. It is written keeping in mind the experiences and observations of the author, in solving the industry-academia gap.</p>
<hr />
<p>Special Thanks to <a href="https://github.com/aviaryan">Avi Aryan</a> and <a href="https://github.com/PragatiVerma18">Pragati Verma</a> for reading draft of this article and suggesting improvements.</p>taranjeetThis article is written for a student pursuing graduation in computer science for a duration of 4 years. It provides a learning path for a good career in software development, which can be either of the following:My Notable Open Source Contributions2019-04-22T19:30:00+00:002019-04-22T19:30:00+00:00https://taranjeet.co/my-notable-open-source-contributions<p>This page contains a selective list of open source contributions I have made so far.</p>
<h3 id="cloudcvs-evalai">CloudCV’s EvalAI</h3>
<ul>
<li>
<p><a href="https://github.com/Cloud-CV/EvalAI/commits?author=taranjeet">Developed EvalAI</a> from scratch. Led API, database and architecture design. Followed test driven development approach to build the product.</p>
</li>
<li>
<p><a href="https://github.com/Cloud-CV/EvalAI/commits/master/scripts/workers/submission_worker.py?author=taranjeet">Implemented parallelized backend</a> which reduced the submission evaluation time by 80% in comparison to <a href="https://www.microsoft.com/en-us/research/project/codalab/">Microsoft Codalab</a>.</p>
</li>
</ul>
<h3 id="dropboxs-zulip">Dropbox’s Zulip</h3>
<ul>
<li><a href="https://github.com/zulip/zulip/commits?author=taranjeet">Refactored code linting pipeline</a> to make it more efficient.</li>
</ul>
<h3 id="pythonindias-wye">PythonIndia’s Wye</h3>
<ul>
<li><a href="https://github.com/pythonindia/wye/commits?author=taranjeet">Created dashboards</a> for tutors to manage their workshops and students.</li>
</ul>
<h3 id="mozillas-fjord">Mozilla’s Fjord</h3>
<ul>
<li><a href="https://github.com/mozilla/fjord/commits?author=taranjeet">Improved test cases</a> for the authentication module.</li>
</ul>
<h3 id="open-source-at-paytm">Open Source at Paytm</h3>
<ul>
<li>
<p>Created <a href="https://github.com/paytm/django-supermigrate/commits?author=taranjeet">Django Supermigrate</a> to manage migrations on production and development environment with no hassle.</p>
</li>
<li>
<p>Created <a href="https://github.com/paytm/django-paytm-oauth/commits?author=taranjeet">Django Paytm Oauth</a>, which is a Django based application for consuming Paytm Oauth 2 implementation.</p>
</li>
<li>
<p>Created <a href="https://github.com/paytm/dj-j-ka-bachcha-field/commits?author=taranjeet">dj-j-ka-bachcha-field</a> to create JSON WYSIWYG model field.</p>
</li>
<li>
<p>Created <a href="https://github.com/paytm/dj-myghanta/commits?author=taranjeet">dj-myghanta</a> to create timestamp model field for MYSQL.</p>
</li>
<li>
<p>Created <a href="https://github.com/paytm/courier-plugin-sdk-nodejs">courier-plugin-sdk-nodejs</a> to ease out third party integrations and reduce their onboarding time.</p>
</li>
</ul>
<h3 id="open-source-at-gradeup">Open Source at Gradeup</h3>
<ul>
<li>
<p>Created <a href="https://github.com/gradeup/youknowwho-gui/commits?author=taranjeet">Rule Engine GUI</a> to create/edit/delete rules.</p>
</li>
<li>
<p>Created <a href="https://github.com/gradeup/rockeathon/commits?author=taranjeet">Rockeathon Showcase website</a> to showcase projects created during <a href="https://gradeup.github.io/rockeathon/">Rockeathon 1.0</a>.</p>
</li>
</ul>taranjeetThis page contains a selective list of open source contributions I have made so far.Adding forms dynamically to a Django formset2017-07-11T21:00:00+00:002017-07-11T21:00:00+00:00https://taranjeet.co/adding-forms-dynamically-to-a-formset<h3 id="django-forms">Django Forms</h3>
<p>Forms in HTML are a collection of input elements that allows us to perform dynamic actions on a website. Django models these forms as an object of <a href="https://docs.djangoproject.com/en/2.0/topics/forms/"><strong>Form</strong></a> class. A form is responsible for taking input from a user, validating and cleaning data and taking necessary action as required.</p>
<h3 id="formsets">Formsets</h3>
<p>A <a href="https://docs.djangoproject.com/en/2.0/topics/forms/formsets/">formset</a> is a collection of Django Forms. Each formset has a management form which is used to manage the collection of homogeneous forms contained in it.</p>
<p>Formset stores data like the total number of forms, the initial number of forms and the maximum number of forms in a management form. So whenever we want to add a form dynamically on the frontend, we need to change the total number of forms so that “<em>Management form has been tampered error is not thrown</em>”. All the forms in a formset are numbered sequentially, so we need to do a little processing of these numbers to keep the whole structure of a form consistent.</p>
<p>Let’s consider an example of a library wherein form is required to fill details of <strong>Book</strong>. The <code class="language-plaintext highlighter-rouge">Book</code> model looks like</p>
<script src="https://gist.github.com/dbf1010d5c952532d48290d75dc199ad.js"> </script>
<h4 id="use-case-1-create-formset-for-a-normal-form">Use case 1: Create formset for a normal form</h4>
<p>Let’s create a view wherein a user can add and store multiple books at once. For this, we will need a form, whose formset can be made. We will first start with a normal form and see how we can make formsets using normal form. We are using <a href="https://getbootstrap.com/">Bootstrap</a> to power our styling.</p>
<p><img src="/assets/images/book_formset.png" alt="normal-dynamic-formset" title="Dynamic Formsets" /></p>
<p>The form definition will look like this</p>
<script src="https://gist.github.com/dca781f2726abaa15a59a079b6e0744c.js"> </script>
<p>Let’s create a formset for this form using <code class="language-plaintext highlighter-rouge">formset_factory</code>. The updated <code class="language-plaintext highlighter-rouge">forms.py</code> will look like this</p>
<script src="https://gist.github.com/5b2a5e12a1ba439d106c81d5db035613.js"> </script>
<p>Now, let’s use this form in a view and create an interface where a user can add or store multiple books</p>
<script src="https://gist.github.com/f0f6f3b2b365ea3f94195306a0de1214.js"> </script>
<p>The template code to render and iterate over this formset will look like</p>
<script src="https://gist.github.com/aacdbb4dbcae29396e7692e1c6008b3c.js"> </script>
<p>This code will simply render the form. By default, a single element will be present, since we have passed <code class="language-plaintext highlighter-rouge">extra</code> as 1 when creating <code class="language-plaintext highlighter-rouge">BookFormset</code>.</p>
<p>Now we need to add some javascript code, to give the functionality of adding form elements when <code class="language-plaintext highlighter-rouge">+</code> button is pressed and removing form elements when <code class="language-plaintext highlighter-rouge">-</code> button is present.</p>
<p>This code will look like</p>
<script src="https://gist.github.com/71b7826b60f42e5d239cf3b3abbf292f.js"> </script>
<p>When this code is added in <code class="language-plaintext highlighter-rouge">create_normal.html</code>, the functionality becomes complete wherein a user can add and remove form elements on the fly.</p>
<h4 id="use-case-2-create-formset-for-a-model-form">Use case 2: Create formset for a model form</h4>
<p>Lets us consider the same problem, where we want to add multiple books, but this time using a <code class="language-plaintext highlighter-rouge">ModelForm</code>, rather than using a simple form. Since we are using <code class="language-plaintext highlighter-rouge">ModelForm</code>, a <code class="language-plaintext highlighter-rouge">ModelFormset</code> will be created.</p>
<script src="https://gist.github.com/20dbf7c56c250ca0acc54f576dc7eee6.js"> </script>
<p>The code for the views will be slightly changed. Here rather than creating a <code class="language-plaintext highlighter-rouge">Book</code> model instance and then saving it, <code class="language-plaintext highlighter-rouge">form</code> will be used, since <code class="language-plaintext highlighter-rouge">form</code> is an instance of <code class="language-plaintext highlighter-rouge">ModelForm</code>.</p>
<script src="https://gist.github.com/879b920e56514af67348da503af2b33c.js"> </script>
<p>The template code(part 3) and javascript code(part 4) remains the same.</p>
<h4 id="use-case-3-create-formset-and-form-both">Use case 3: Create Formset and Form both</h4>
<p>Let’s consider a more complex case wherein we need to save form along with a formset. This can be easily understood by taking the example of <code class="language-plaintext highlighter-rouge">Book</code> and <code class="language-plaintext highlighter-rouge">Author</code>. Here we will create a modelform for <code class="language-plaintext highlighter-rouge">Book</code> and modelformset for <code class="language-plaintext highlighter-rouge">Author</code>.</p>
<p><img src="/assets/images/book_with_author.png" alt="normal-dynamic-formset" title="Form with Formsets" /></p>
<script src="https://gist.github.com/c503278293ea77f77fb2e0f88f8d9fc7.js"> </script>
<p>The corresponding code for the views will look like</p>
<script src="https://gist.github.com/bf3a42ee8bc682d023fbe4c6efd9c376.js"> </script>
<p>The template code to iterate and render both the form and formset will look like</p>
<script src="https://gist.github.com/6f921607b8f514ef68edfa45e28b7e22.js"> </script>
<h3 id="conclusion">Conclusion</h3>
<p>This post walked in detail of how can the formsets be implemented. Much of the help for the above javascript code is taken from this <a href="https://stackoverflow.com/a/669982/2534102">stackoverflow answer</a>.</p>
<p>The code for this can be found <a href="https://github.com/taranjeet/django-library-app">here</a></p>taranjeetDjango FormsConfiguring uwsgi, nginx for django project2016-03-05T18:00:00+00:002016-03-05T18:00:00+00:00https://taranjeet.co/configuring-uwsgi-nginx-for-django-project<p>This post is about setting up Nginx and uwsgi for a django project.</p>
<p>Some conventions that I have sticked to while doing so are written down here. First of all I will be creating a user named <code class="language-plaintext highlighter-rouge">ubuntu</code> and a group named <code class="language-plaintext highlighter-rouge">ubuntu</code>. This <code class="language-plaintext highlighter-rouge">ubuntu</code> user will be responsible for running nginx as well as uwsgi. This is necessary so that the socket created between nginx and uwsgi does not get trapped in Permission denied error. Also, I am assuming that the server is a fresh install of Ubuntu 14.04. Let’s begin with the steps:</p>
<ul>
<li>Create a user named <code class="language-plaintext highlighter-rouge">ubuntu</code>.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adduser ubuntu
gpasswd -a ubuntu sudo
</code></pre></div></div>
<ul>
<li>Install the following packages</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get install python-dev
sudo pip install uwsgi
sudo apt-get -f install nginx-full
</code></pre></div></div>
<ul>
<li>Clone the repository in the home directory of <code class="language-plaintext highlighter-rouge">ubuntu</code> user. Assuming that the name of the project is explore-webserver.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/staranjeet/explore-webserver.git
</code></pre></div></div>
<ul>
<li>Configure uwsgi now. Create two folders</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /etc/uwsgi/apps-available /etc/uwsgi/apps-enabled
</code></pre></div></div>
<ul>
<li>Create a config <code class="language-plaintext highlighter-rouge">ini</code> file for your project in <code class="language-plaintext highlighter-rouge">sites-available</code> folder. Idea is to create to config files in <code class="language-plaintext highlighter-rouge">available</code> folder and then create symlink for these in <code class="language-plaintext highlighter-rouge">enabled</code> folder. The file <code class="language-plaintext highlighter-rouge">explore-webserver.ini</code> should look something like this</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[uwsgi]
project = explore-webserver
base = /home/ubuntu
uid = ubuntu
gid = ubuntu
chdir = %(base)/%(project)
home = %(base)/%(project)/pyenv
module = %(project).wsgi:application
env = DJANGO_SETTINGS_MODULE=settings.live
master = true
processes = 3
socket = %(base)/%(project)/%(project).sock
chmod-socket = 664
vacuum = true
</code></pre></div></div>
<ul>
<li>Create a upstart script for uwsgi in <code class="language-plaintext highlighter-rouge">/etc/init</code> folder. This script is created to automatically start the service at boot plus we can manually start/stop or restart/reload the service. Let’s name this script as <code class="language-plaintext highlighter-rouge">uwsgi.conf</code>.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>description "uWSGI application server in Emperor mode"
start on runlevel [2345]
stop on runlevel [!2345]
setuid ubuntu
setgid ubuntu
exec /usr/local/bin/uwsgi --emperor /etc/uwsgi/apps-enabled --daemonize /var/log/uwsgi/app/explorewebserver.log
</code></pre></div></div>
<ul>
<li>Configure nginx now. Nginx also follows the <code class="language-plaintext highlighter-rouge">sites-available</code> and <code class="language-plaintext highlighter-rouge">sites-enabled</code> convention. In <code class="language-plaintext highlighter-rouge">/etc/nginx/sites-available</code> folder, create a file named <code class="language-plaintext highlighter-rouge">explore-webserver</code>.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server{
listen 80;
server_name server_ip_address_or_domain_name;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/explore-webserver/explore-webserver.sock;
}
location /static {
root /home/ubuntu/explore-webserver;
}
location /media {
root /home/ubuntu/explore-webserver/explorewebserver;
}
}
</code></pre></div></div>
<ul>
<li>Check whether this config is correct or not by</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
</code></pre></div></div>
<ul>
<li>Create a soft link to this file in <code class="language-plaintext highlighter-rouge">sites-enabled</code> directory by</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo ln -s /etc/nginx/sites-available/explore-webserver /etc/nginx/sites-enabled/
</code></pre></div></div>
<ul>
<li>Now change the user in <code class="language-plaintext highlighter-rouge">/etc/nginx/nginx.conf</code> from <del><code class="language-plaintext highlighter-rouge">www-data</code></del> to <code class="language-plaintext highlighter-rouge">ubuntu</code></li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>user ubuntu;
</code></pre></div></div>
<ul>
<li>Now start uwsgi by</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo service uwsgi start
</code></pre></div></div>
<ul>
<li>Restart nginx by
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo service nginx restart
</code></pre></div> </div>
</li>
</ul>
<p>Note: Make sure that all directories(socket and logs) are owned by the same user(here ubuntu).</p>taranjeetThis post is about setting up Nginx and uwsgi for a django project.Implementing view only permissions in Django2016-02-14T10:00:00+00:002016-02-14T10:00:00+00:00https://taranjeet.co/django-view-only-permission<p>Django ships with a nice and easy to plug <a href="https://docs.djangoproject.com/en/1.11/ref/contrib/admin/">admin</a> interface. Access to admin panel is managed through Django ACL(Access Control List) using
permission which operates on per model. By default, Django comes with three
types of permission namely add, change and delete.</p>
<p>This post is about implementing <strong>view</strong> only permissions in Django which are
actually missing. <strong>View</strong> only permission come in handy when only view (or read-only)
permission is required for a model.</p>
<p>The part can be split into major sub-parts. Firstly adding permission in a
generic way. Secondly linking the corresponding read-only action with the
permission</p>
<p>Let’s start with implementing permission. Permissions can be added for a model
by using its <strong>Meta</strong> class. For example, to add permission to <strong>Book</strong> model,
the following code can be used</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from django.db import models
class Book(models.Model)
name = models.CharField(max_lengt=100)
class Meta:
permissions = (
('CAN_VIEW_BOOK', 'Can View Book'),
)
</code></pre></div></div>
<p>This works nicely if we want to add permission for a single or 2–3 models. But
our problem is we want to add this permission for all the models present in the
project. Also, we want to make sure that whenever any new model is added, this
permission should already get added for that model also. So how do we achieve
this?</p>
<p>Well, Django is a mature framework and hence it already is shipped with such
feature “<a href="https://docs.djangoproject.com/en/1.11/topics/signals/">Signals</a>”.
Signals are something like event emitters which happen whenever any event
occurs. There are many signals, but right now we are only concerned with
<a href="https://docs.djangoproject.com/en/1.11/ref/signals/#post-migrate">post_migrate</a>.
As the name indicates, <strong>post_migrate</strong> runs <strong>after</strong> the migration is run. Also,
we can use <strong>post_model</strong> in a generic way, so that it applies to each and every
model.</p>
<p>To receive a signal, we need to register a receiver function that gets called
when the signal is sent by using the method.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from django.db.models.signals import post_migrate
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
def add_view_only_permission(sender, **kwargs):
'''This creates a view only permission for sender'''
for content_type in ContentType.objects.all():
codename = 'can_view_%s' % content_type.model
name = 'Can View %s' % content_type.name
if not Permission.objects.filter(
content_type=content_type,
codename=codename):
Permission.objects.create(
content_type=content_type,
codename=codename,
name=name)
post_migrate.connect(add_view_only_permission)
</code></pre></div></div>
<p>This code can be placed in any file, but it is mostly placed in the file, which gets
loaded initially as signals to be cached also. There is a question on
<a href="https://stackoverflow.com/questions/2719038/where-should-signal-handlers-live-in-a-django-project">stackoverflow</a>
regarding the placement of signals in a project. As of now, I am placing it in
**<any_app>/models.py**.</any_app></p>
<p>Summarizing, the above code will create a default <strong>view only</strong> permission for
each and every model. <strong>post_migrate</strong> signal is emitted whenever migrations
are run. One very important thing to note is that it only creates permission for
a model in a generic way, not a view only permission.</p>
<p>Now comes the second part, wherein we will write our action corresponding to
the above created permission. For this, we will be using <strong>ModelAdmin</strong> class,
since we are dealing with the admin part.</p>
<p>There is a function called <em>get_readonly_fields, get_list_display</em> and
<em>submit_row</em> which can be overridden and used to fit our use case. Code for
<strong>ViewOnlyAdmin</strong> class will be as follows.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class ViewOnlyAdmin(admin.ModelAdmin):
'''This class makes fields read only'''
def _is_user_view_only_type(self, perm, request):
return request.user.has_perm(str(perm)) and request.user.is_superuser
def get_readonly_fields(self, request, obj=None):
class_name = self.__class__.__name__.replace('Admin', '').lower()
for permission in request.user.get_all_permissions():
head, sep, tail = permission.partition('.')
perm = 'can_view_%s' % class_name
if str(perm) == str(tail):
if self._is_user_view_only_type(perm, request):
return flatten_fieldsets(self.declared_fieldsets)
else:
return list(set(
[field.name for field in self.opts.local_fields] +
[field.name for field in self.opts.local_many_to_many]))
return self.readonly_fields
def get_list_display(self, request):
list_display = super(ViewOnlyAdmin, self).get_list_display(request)
app_label, model_name = self.opts.app_label.lower(), self.model._meta.object_name.lower()
perm = '%s.can_view_%s' % (app_label, model_name)
if self._is_user_view_only_type(perm, request):
self.list_editable = ()
return list_display
@register.inclusion_tag('admin/submit_line.html', takes_context=True)
def submit_row(context):
ctx = original_submit_row(context)
app_name = context['app_label']
model_name = context['opts'].model_name
for permission in context['request'].user.get_all_permissions():
head, sep, tail = permission.partition('.')
perm = 'can_view_%s' % model_name
if str(perm) == str(tail):
if (context['request'].user.has_perm(str(permission)) and
not context['request'].user.is_superuser):
ctx.update({
'show_save_and_add_another' : False,
'show_save_and_continue' : False,
'show_save' : False,
'show_save_as_new' : False,
})
return ctx
</code></pre></div></div>
<p>To use this class for your models, you need to extend your model’s admin class
from this class.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from libs.admin import ViewOnlyAdmin
class BookAdmin(ViewOnlyAdmin):
pass
</code></pre></div></div>
<p>To use this permission, one needs to assign <strong>two</strong> permission namely
<strong>can_change</strong> and <strong>can_view</strong> for a model. This is because <strong>can_view</strong> is a
negative permission and it only works if the <strong>can_change</strong> is present. So one
can simply infer that <strong>can_view</strong> negates the change effect of <strong>can_change</strong>
to turn every field into a read-only field.</p>
<p>The above code is one way of implementing view only permission in Django. I am
sure there can be other interesting ways to implement it.</p>taranjeetDjango ships with a nice and easy to plug admin interface. Access to admin panel is managed through Django ACL(Access Control List) using permission which operates on per model. By default, Django comes with three types of permission namely add, change and delete.