Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

problems using observer pattern in django

I'm working on a website where I sell products (one class Sale, one class Product). Whenever I sell a product, I want to save that action in a History table and I have decided to use the observer pattern to do this.

That is: my class Sales is the subject and the History class is the observer, whenever I call the save_sale() method of the Sales class I will notify the observers. (I've decided to use this pattern because later I'll also send an email, notify the admin, etc.)

This is my subject class (the Sales class extends from this)

class Subject:
    _observers = []

    def attach(self, observer):
        if not observer in self._observers:
            self._observers.append(observer)

    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass

    def notify(self,**kargs):
        for observer in self._observers:
            observer.update(self,**kargs)

on the view I do something like this

sale = Sale()
sale.user = request.user
sale.product = product
h = History() #here I create the observer
sale.attach(h) #here I add the observer to the subject class
sale.save_sale() #inside this class I will call the notify() method

This is the update method on History

def update(self,subject,**kargs):
    self.action = "sale"
    self.username = subject.user.username
    self.total = subject.product.total
    self.save(force_insert=True)

It works fine the first time, but when I try to make another sale, I get an error saying I can't insert into History because of a primary key constraint.

My guess is that when I call the view the second time, the first observer is still in the Subject class, and now I have two history observers listening to the Sales, but I'm not sure if that's the problem (gosh I miss the print_r from php).

What am I doing wrong? When do I have to "attach" the observer? Or is there a better way of doing this?

BTW: I'm using Django 1.1 and I don't have access to install any plugins.

like image 983
pleasedontbelong Avatar asked Dec 07 '22 01:12

pleasedontbelong


1 Answers

This may not be an acceptable answer since it's more architecture related, but have you considered using signals to notify the system of the change? It seems that you are trying to do exactly what signals were designed to do. Django signals have the same end-result functionality as Observer patterns.

http://docs.djangoproject.com/en/1.1/topics/signals/

like image 63
Andrew Sledge Avatar answered Dec 09 '22 15:12

Andrew Sledge