Software for business

Published at January 24, 2012 | Tagged with:

I am starting a new blog. The reason is that I want to keep this one more technically oriented while the other will be more business and customers oriented. Its name is Software for business and the idea is to show to the business in less technical details how the modern IT technologies like CRM & ERP systems, web sites, e-commerce solutions, online marketing and so on can help their business.
If you find the topic interesting feel free to join.

Connecting Django Models with outer applications

Published at January 23, 2012 | Tagged with: , , , ,

Preface: Sometimes, parts of the data that you have to display in your application reside out of the Django models. Simple example for this is the following case - the client requires that you build them a webshop but they already have CRM solution that holds their products info. Of course they provide you with a mechanism to read this data from their CRM.

Specialty: The problem is that the data in their CRM does not hold some of the product information that you need. For instance it misses SEO-friendly description and product image. So you will have to set up a model at your side and store these images there. It is easy to join them, the only thing that you will need is a simple unique key for every product.

Solution: Here we use the product_id field to make the connection between the CRM data and the Django model.


# in models.py
class Product(models.Model):
    product_id = models.IntegerField(_('Original Product'),
                                     unique=True)
    description = models.TextField(_('SEO-friendly Description'),
                                   blank=True)
    pod_image = FilerImageField(verbose_name=_('Product Image'),
                                blank=True, null=True)

   @property
   def name(self):
       return crm_api.get_product_name(self.product_id)

# in forms.py
class ProductForm(forms.ModelForm):
    name = forms.CharField(required=False,
                           widget=forms.TextInput(attrs={
                               'readonly': True,
                               'style': 'border: none'}))

    class Meta:
        model = Product
        widgets = {
            'product_id': forms.Select(),
        }
    def __init__(self, *args, **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)
        self.fields['product_id'].widget.choices = crm_api.get_product_choices()
        if self.instance.id:
            self.fields['name'].initial = self.instance.name

The form here should be used in the admin(add/edit) page of the model. We define that the product_id field will use the select widget and we use a method that connect to the CRM and returns the product choices list.
The "self.instance.id" check is used to fill the name field for product that are already saved.

Final words: This is a very simple example but its idea is to show the basic way to connect your models with another app. I strongly recommend you to use caching if your CRM data is not modified very often in order to save some bandwidth and to speed up your application.
Also if you have multiple field it may be better to overwrite the __getattr__ method instead of defining separate one for each property that you need to pull from the outer application.

P.S. Thanks to Miga for the code error report.

Python os.stat times are OS specific ...

Published at November 21, 2011 | Tagged with: , , , ,

... no problem cause we have stat_float_times

Preface: recently I downloaded PyTDDMon on my office station and what a surprise - the files changes did not affect on the monitor. So I run a quick debug to check what is going on: the monitor was working running a check on every 5 seconds as documented but it does not refresh on file changes.

Problem: it appeared that the hashing algorithm always returns the same value no matter whether the files are changed or not. The calculation is based on three factors: file path, file size and time of last modification. I was changing a single file so the problem was in the last one. Another quick check and another surprise - os.stat(filename).st_mtime returns different value after the files is changed but the total hash stays unchanged. The problem was caused from st_mtime returning floating point value instead of integer.

Solution: Unfortunately the os.stat results appeared to be OS specific. Fortunately the type of the returned result is configurable. Calling os.stat_float_times(False) in the main module force it to return integer values.

Final words: these OS/version/settings things can always surprise you. And most of the time it is not a pleasant surprise. Unfortunately testing the code on hundred of different workstations is not an option. But this is one of the good sides of the open source software. You download it, test it, debug it and have fun.
Also special thanks to Olof(the man behind the pytddmon concept) for the tool, the quick response to my messages and for putting my fix so fast in the repo. I hope that this has saved someone nerves )

P.S. If you are using Python and like TDD - PYTDDMON is the right tool for you.

Django CMS Plugins with selectable template ...

Published at October 9, 2011 | Tagged with: , , , , ,

... or how to reuse your plugins inside sections with different design

Problem: Frequently on the websites I am developing I need to display same set of data in several different ways. For example if I have a news box that needs to appear in different sections of the website e.i. in sidebar, main content etc. Using Django CMS plugins make this quite easy.
For simplicity we will take the following case. An image/text tuple with two layout variations - image on left of text and image on right.

Django CMS Plugins

Same data but different layout. All you need to do is just to allow your users to change the plugin template according to their needs. If you don't have experience with Django CMS Plugins I advice you to check how to create custom Django CMS Plugins before you continue with solution.

Solution: First you will have to create a tuple holding your templates(and their human readable names) and add a field that will hold the chosen template to the plugin model.


#models.py
PLUGIN_TEMPLATES = (
  ('image_on_left.html', 'Image on left'),
  ('image_on_right.html', 'Image on right'),
)

class SamplePlugin(CMSPlugin):
    # your plugin properties here
    template = models.CharField('Template', max_length=255,
                                choices = PLUGIN_TEMPLATES)

Now it is time to tweak the template render method too:


#cms_plugins.py
class CMSSamplePlugin(CMSPluginBase):
    model = SamplePlugin
    name = 'Sample plugin'
    render_template = PLUGIN_TEMPLATES[0][0]
    
    def render(self, context, instance, placeholder):
        if instance and instance.template:
            self.render_template = instance.template
        #your stuff here
        return context

Final words: Yep, this is all. Simple isn't it? It is amazing how sometimes such small things are so useful. If you are having bigger difference in the layout of your templates you will probably have to put a little more stuff in the context that some of your templates may not need but it is OK. Feel free to comment and if you are using this "trick" please add your use case - it will be interesting to see in how many different cases this works.

Neil Gaiman's Anansi Boys...

Published at October 2, 2011 | Tagged with: , ,

... an unexpected gift and unexpected dedication

YOU KNOW HOW IT IS. You pick up a book, flip to the dedication, and find that, once again, the author has dedicated a book to someone else and not you.

Not this time.

Because we haven't yet met/have only a glancing acquaintance/are just crazy about each other/haven't seen each other in much too long/are in some way related/will never meet, but will, I trust, despite that, always think fondly of each other...

This one's for you.

With you know what, and you probably know why."

This is how Neil Gaiman's Anansi Boys starts.

About a week ago I spent few days in Greece. One day we were sitting under the shadow of a near bar when something grabbed my attention. Next to the bar there was a book shelf with something special on it:
Neil Gaiman's Anansi Boys

It was really strange to go in a foreign country, in unknown place and there a few meters away from me standing out with its black cover to see a book of one of my favourite authors. So I just took my camera, go there and take a shot on it.

The bartender asked me what am I shooting so I explained to him that it was a surprise for me to see that book. He took it as he was seeing it for a first time in his life, took a brief look at it and asked me whether I have read it. I said that unfortunately I am not. Then he took another look at the book and gave it to me as a gift. I took and open it and... it was starting with the dedication from the top of this post.

Coincidence? Maybe... or maybe not.

It is always a pleasure for me to discover pieces of art, no matter whether I am travelling or not, no matter is it an ancient castle or a book, it is great.
I haven't still finished the book but it looks amazing. I really recommend it as any other Gaiman's book. Hopefully I'll meet Neil one day till than(and after) I'll keep reading.
So if you are reading this go travel, or read books, or both. Have fun and share your experience.