Month: December 2017

Recommended South African Sports Betting Sites

I've been taking a few punts here and there on in-play cricket and football with a few local sites and I wanted to review a few of them and see which offered the best sign up bonus and odds.

The South African Sports Betting Site Contenders

Here are the sites in the offering, I've included the competitiveness of odds (odds) as a rating out of 10, deposit bonus amount, deposit bonus percent and deposit playthrough requirements percent as well as site usability which are the criteria I am using to test.

SiteOdds RatingUsability RatingBonusBonus PercentPlaythroughTime Limit days days (Extra bet)430 days (Min.1.1)None
betxchange.com7.56R10000100%10None (Min. 0.7)3 Months

Another table of odds comparison with boxing match odds offered by the bookmaker. Then a column for payback rates for the Chelsea v Barcelona first leg.

SiteGroves v Eubank (Groves)
Time of Odds: 5:00pm 2018-02-16
Groves v Eubank (Eubank)Total BoxingPayback rate (FC Chelsea v FC Barcelona)Payback rate (Wigan Athletic v Manchester City)


Avoid and at all costs. They are part of the horse racing racket and aren't worth the time.

Don't underestimate usability, it is a very important factor and helps you place bets in a timely manner especially during in-play events.

Basically the only worthwhile sites are and

I picked up a big problem with the deposit bonus. It does not match your bet, it just gives you a free bet. The free bet only gives you back the winnings, not the original stake. It is an absolute disgrace of a betting site. Avoid it at all costs.

As per terms and conditions:

The Free Bet/Bonus Bet is non-refundable and the Free Bet/Bonus Bet wagered amount is not included in any winnings. Only the winnings will be paid to your Company Account.

Poor show,avoid at all costs.

Another betting site to avoid at all costs is because the bonus requires you to stake the entire bonus amount 5 times at odds of 0.5 or greater. That is a very difficult thing to do as the probability that you go bankrupt is much higher when you are forced to stake your entire capital.

Update: August 2019

I wanted to do another check to see if any changes were made in the betting landscape in South Africa.

I'll be looking at payback rates on rugby (Argentina v South Africa) and football (Chelsea v Man United). I also look at a particular pick and compare them

SitePayback rate (Argentina v South Africa)Payback rate (Cheslea v Man United)Argentina WinCheslea WinTotal (Higher is better) (not available)
betxchange.com93.20%96.05%2.93.53195.69 (fractional odds)

Update: December 2019

I've been looking at what betting sites offer EFC betting and have added the odds for EFC 82 Du Plessis vs Lesar

Betting SiteBrendan LesarDricus Du Plessis


Django Moderation and Workflow Tools Reviewed

I have a requirement where entries created by users needs to be approved or rejected. Now this seems to be a common trait you can add to a model and something that needn't be custom developed, a good use case for django behaviours

I digged a bit deeper and found that there are generic workflow and moderation apps that I can utilise instead of reinventing the wheel

The tools

  • django-moderation - a reusable application for Django framework, that allows to moderate any model objects [204 Stars]
  • activflow - a generic, light-weight & extensible Workflow Engine for agile automation of Business Processes [343 Stars]
  • viewflow - Reusable workflow library [942 Stars]
  • SpiffWorkflow - A powerful workflow engine implemented in pure Python [539 Stars]
  • django-river - Django workflow library supports on the fly changes [322 Stars]
  • django-fsm - Django friendly finite state machine support [972 Stars]

Here is a list of the workflow packages compared on django-packages

The Requirements

I need to add a status to the models. Have users notified that they need to take an action. Set certain related models as not requiring an authorisation.

Supplying a rejection note if rejected.

Permissions where only certain people can approve / reject a record.

Moderation queue.

Django Moderation

Basically works by creating a moderation object first that only becomes visible as a real object once it has been approved. There is a built in way of approving object in the django-admin and it is relatively easy to set up.

It also send emails to the moderators.

After creating an object the object created is not available or visible, until it is approved or rejected. So if you have a get_absolute_url for the model, it will 404 after creation.

In the admin you go to the moderation tab and have a list of moderated objects that need approval or rejection. Objects created from superadmin can be auto approved.

The approval and rejection screen for the object.

The statuses available are Approved, Rejected and Pending. It stores the name and date it was approved. You can also see a history of approval and rejection if you set that to true in the settings.

The email is sent to the user creating the object but surprising to me it was only sent when the object was created from the admin side. Even when I extended from from moderation.forms import BaseModeratedObjectForm on the frontend an email was not sent.

Setting visible_until_rejected to True, doesn't store the object in the original model in my case. It was not visible.


This is used to create a more generic work flow, where you can set the statuses and activity flow your self.

I started working on it and realised you can't just install the package with pip as there is no pypi package.


Installs easily with pypi and uses python 3.

Annotating a class based view with @flow.flow_start_view to start the flow.

Tasks execution rights could be restricted by the django permission system. So per object permissions for example a user only allowed to approve users in a specific company will have to be managed manually.

flow.Handler is the task performed by synchronous call a python code.

It does a lot for you, but unfortunately I've gone with a different frontend framework for django django-bootstrap instead of django-material. Also I need a fine grained process of approval with views that I'll have to build myself. Perhaps it has some helpers.

This is how the workflow looks on the admin side.

viewflow-admin-viewA process list consists of many tasks related to a single object.


Then each Task is the same as those represented in the of the example:



After looking at the defaults created with the demo app, the workflow tasks seem to add a bit of crap. In my case all I need to see is that a leave request was created with a status of initiated and after a manger reviews it whether it is accepted or rejected.


Django Finite State machine. I found this great gist (article) after bumping my head on a few of the options I've mentioned above. It seems to make it a bit simpler to control the state and transitions.

It was made by the developer on viewflow and seems to be the simpler version.

It prevents running a state change event twice as an activity of state change can only happen if the source state is a specified state.

It seems like it will work correctly my only concerns is the ability to provide a reason for approving or rejecting and permissions of who can do the approval on a certain object which means I may ned to use django-guardian.

It seems that using conditions to check whether the approver can in fact approve a given users leave request is the way to go instead of permissions. But there is built in permissions

You can even prevent direct state change with protected=True, which is great as that ensures that the method to change state is always run.

Important thing to note is that the state is not saved until you actually run

So far it is the simplest moderation or workflow (state machine) I have seen and I like it. The only downside is no reason is supplied.

To fix the description / comment /reason issue I added a merge request into django-fsm-log, which is a utility that logs state changes in django-fsm.

Functional Tests failing on Jenkins but not on local computer

Ever struggled with a test failing on jenkins using xvfb, well there are a few things you can do to ensure that both browsers work.

Element Not Found

Sometimes there is an ElementNotFound error on the server and not on your local. Usually this is because selenium cannot see the element. It is hidden.

Usually this happens when both screens you test on are not the same size. So you want to ensure that both screens are the same size.

Solution Maintaining Consistency

Set the Window Size

In your setUp for the tests, ensure you resize the browser screen to a single size.

self.browser = webdriver.Firefox()
self.browser.set_window_size(1280, 800)

Set XVFB Screen size same as local

Set the screen size to the same as your local