Dynamic form field based on another model’s entries and save them in a m2m way in Django

It’s been a while since I have done this type of brain storming stuff. Today is my country’s victory day and I have got some free time.

Objective:

I have a inventory model named Item. An item can have many attributes such as height, width etc. Think about a system where more attributes can be added in future. I wanted to build such a system where I can dynamically add these attributes so that I don’t need to modify my  model or code for this type of changes.

The idea:

The idea is very simple. I will have 3 models.

  • Item
  • Attribute
  • ItemAttribute

Item model will hold basic information about the item. In Attribute model I can add as many attribute as I wish. This model will have a type field which will determine the type of each attribute such as text, choice, number etc. It is possible to add more fields like length, required etc and add business logic for these. But for keep it simple for now.

ItemAttribute is the many to many relational table between Item and Attribute. It will have an extra field called value to store the value of this attribute.

In short: Item has many Attribute. Each of which has a value. To facilitate this we need many to many (m2m) relation between Item and Attribute.

How it is done:

Here is the gist how I achieved this functionality.

Like
Like Love Haha Wow Sad Angry
IntelliJ IDEA + Phonegap + Android SDK + Genymotion + linux

It is bit tricky to do this all together. Let me give me a overview why I choose these tools .

  • IntelliJ IDEA is an IDE I love working on. Actually for all of my developing purpose I use Jetbrain’s Product. PhpStorm, PyCharm, WebStorm. Since, it is not targeted for native android development choosing Android Studio is not necessary. I use that for native as it. Currently, I am using latest version – v14.
  • Phonegap is being used as I need to develop hybrid app. Android SDK is needed for deployment in android platform. I am using version 5.1.
  • You may ask why Genymotion in lieu of AVD. The answer is, Genymotion seems faster to me. If you have already use AVD, it is not important how high end machine you use, I am sure you are very annoyed when you try to emulate. Genymotion may reduce your anger to some extent.
  • Linux: seriously?? You are going to ask me why linux??

How to:

Downloads & Installations:

  1. To use phonegap make sure you have node.js and npm installed in you system. Then run following command.

    $ sudo npm install -g phonegap

  2. Download android SDK. Extract it to the folder where you want to install it. Lets say it is the “home” folder. ~/android-sdk-linux Add ~/android-sdk-linux/tools and ~/android-sdk-linux/platform-tools to your path variable.
  3. Run $ andoird and download necessary libraries and API.
  4. Download genymotion and install it and install it buy running the .bin file.
  5.  Download IntelliJ IDEA. Extract it to the folder where you want to install it. Lets say it is the “home” folder
  6. run $ bin/idea.sh (make sure it is executable) and follow the installation process.

Setting Up:

  1. Install “Genymotion” and “Phonegap/Cordova” plugin. To install it, go to Settings → Plugins → Install JetBrains plugin…, then select PhoneGap/Cordova Plugin and click Install plugin. Same goes for genymotion.
  2. Create a new project using Web Static → Phonegap/Cordova category.
  3. after project creating the project open Project Structure (ctrl+shift+alt+s) in SDK add JDK library then Android SDK.
  4. On same window (Project Structure) select Modules. Click on (+) → import module. Select android folder under platform folder. and  click next. Important note that, do not import debug folders. When folder selection screen comes, select all folders (eg: ../android and all ../gen and ../src folder) except debug folders.
  5. Open Run/Debug Configuration.Click (+) → Android Application. Select then module you imported earlier. In Target Device select “Show Chooser Dialog” option.
  6. Run Genymotion and start your device.
  7. Run this newly created android configuration instead of Phonegap run and you will see your app running on your genymotion device.

Known Issue:

  • No module in step 5 ?
    – Make sure you have imported the module properly as described in step 4.
  • Errors on importing module ?
    – Follow the instruction carefully. May be you have added debug folders too.
Like
Like Love Haha Wow Sad Angry
Solution of infinite digest loop for ng-repeat with object property filter in AngularJS

Few months ago I wrote a code in AngularJS which was something like this:


<ul ng-repeat="course in courses|filter:{is_taken:true }" >
<li>{{ course.name }}</li>
</ul>

 

It was generating a digesting loop error. Though the data was showing correctly. Soon I realized that it was generating because for each turn in ng-repeat loop, courses are filtered up. So, it was watched and digest by default characteristics of angular Scope. In this situation the easiest solution to me was following:


<div ng-init="filteredCourses=courses|filter:{is_taken:true }">
<ul ng-repeat="course infilteredCourses" >
<li>{{ course.name }}</li>
</ul>
</div>

 

What I did was I initiated a new object using ng-init which contains the filtered objects. Then use that newly created object to loop on. And all those errors are gone… 🙂

Like
Like Love Haha Wow Sad Angry
AJAX requests in CakePHP without disabling SecurityComponent

Security is always a big deal for a software specially for web app where you don’t know your users’ intention. To ensure some common security measure, CakePHP provides SecurityComponent with its core.

Let’s come to the point. If you try to POST any request through AJAX, you will get Bad Request exception and your request will be Black Holed.

So, how do you prevent this without disabling the SecurityComponent for the action(many online resources do this. But this is not what we want, right?)? Well, you need to do 2 things to do in your beforeFilter to achieve that.

$this->action == 'add') {
    $this->Security->csrfUseOnce = false; // We will use CSRF token for more than one time
    $this->Security->validatePost = false; // Disabling form POST validation
}

Why these two:

  1. Since we may do the request several time from different parts of a single page, we will use same CSRF token. Though there is a complex way to update CSRF token of the page after the ajax request processed, but lets stick with the easier way.
  2. Also, SecurityComponent require you create your form using FormHelper shipped with CakePHP core. I’m assuming the form is not built with the FormHelper. You can ignore this if you generate your form using FormHelper.

If you do not using FormHelper to ensure CSRF protection you will need to post CSRF token with your post data in specific format. Here is how the CSRF token should be in post data.

array( 
'_Token' => array(
    'key'=> $this->Session->read('_Token.key');
    ),
'ModelName' => array(
    // modeldata
    )
)
Like
Like Love Haha Wow Sad Angry