2009-08-19 69 views
3

我有一個類,我想要覆蓋get_or_create方法。基本上,如果我的課程沒有存儲答案,我希望它做一些過程來獲得答案,它不提供。該方法實際上是一種get_or_retrieve方法。所以這是這個類:Django - 重寫get_or_create與models.py

class P4User(models.Model): 
    user  = models.CharField(max_length=100, primary_key=True) 
    fullname = models.CharField(max_length=256) 
    email  = models.EmailField() 
    access = models.DateField(auto_now_add=True) 
    update = models.DateField(auto_now_add=True) 

    @classmethod 
    def get_or_retrieve(self, username, auto_now_add=False): 
    try: 
     return self.get(user=username), False 
    except self.model.DoesNotExist: 
     import P4 
     import datetime 
     from django.db import connection, transaction, IntegrityError 
     p4 = P4.P4().connect() 
     kwargs = p4.run(("user", "-o", username))[0] 
     p4.disconnect() 
     params = dict([(k.lower(),v) for k, v in kwargs.items()])   
     obj = self.model(**params) 
     sid = transaction.savepoint() 
     obj.save(force_insert=True) 
     transaction.savepoint_commit(sid) 
     return obj, True 
    except IntegrityError, e: 
     transaction.savepoint_rollback(sid) 
     try: 
      return self.get(**kwargs), False 
     except self.model.DoesNotExist: 
      raise e 

    def __unicode__(self): 
    return str(self.user) 

現在我完全承認我已經使用db/models/query.py作爲我的出發點。我的問題是這條線。

obj = self.model(**params)

我能夠得到PARAMS,但我還沒有確定self.model。我不明白需要什麼,並且不直觀地明白應該是什麼樣的價值。即使回頭看query.py我也弄不清楚。誰可以給我解釋一下這個?我真的很想了解它並修復我的代碼。

感謝

回答

4

丹尼爾在他的建議中使用經理類是正確的。這是我最終的結果。

# Managers 

class P4Manager(models.Manager): 
    def p4_run_command(self, command): 
    """Runs a basic perforce command and return the values""" 
    p4 = P4.P4() 
    p4.connect() 
    values = p4.run(command) 
    p4.disconnect() 
    return self.__unify_key_values__(values) 

    def __unify_key_values__(self, args): 
    """Unified method to clean up the lack of standard returns from p4 api""" 
    final = [] 
    for item in args: 
     params = dict([(k.lower(),v) for k, v in item.items()]) 
     results = {} 
     for k, v in params.items(): 
     if k in ['password', ]: continue 
     if k in ["access", "update"]: 
      v = datetime.datetime.strptime(v, "%Y/%m/%d %H:%M:%S") 
     results[k]=v 
     final.append(results) 
    return final 

    def __get_or_retrieve_singleton__(self, **kwargs): 
    """This little sucker will retrieve a key if the server doesn't have it. 
     In short this will go out to a perforce server and attempt to get a 
     key if it doesn't exist.  
    """ 
    assert len(kwargs.keys())==2, \ 
      'get_or_retrieve() must be passed at one keyword argument' 
    callback = kwargs.pop('callback', None) 
    try:  
     return self.get(**kwargs), False 
    except self.model.DoesNotExist: 
     params = self.p4_run_command((kwargs.keys()[0], "-o", kwargs.values())) 
     if callback: 
     params = callback(*params) 
     obj = self.model(**params) 
     sid = transaction.savepoint() 
     obj.save(force_insert=True) 
     transaction.savepoint_commit(sid) 
     return obj, True 
    except IntegrityError, e: 
     transaction.savepoint_rollback(sid) 
     try: 
     return self.get(**kwargs), False 
     except self.model.DoesNotExist: 
     raise e 

class P4UserManager(P4Manager): 
    """ 
    A Generic User Manager which adds a retrieve functionality 
    """ 
    def get_or_retrieve(self, user): 
    kwargs = { 'callback' : self.__userProcess__ , 
       'user': user } 
    return self.__get_or_retrieve_singleton__(**kwargs) 

    def __userProcess__(self, *args): 
    args = args[0] 
    if not args.has_key('access'): 
     raise self.model.DoesNotExist() 
    return args 

# Models 

class P4User(models.Model): 
    """This simply expands out 'p4 users' """ 
    user  = models.CharField(max_length=100, primary_key=True) 
    fullname = models.CharField(max_length=256) 
    email  = models.EmailField() 
    access = models.DateField(auto_now_add=True) 
    update = models.DateField(auto_now_add=True) 
    objects = P4UserManager() 

    def __unicode__(self): 
    return str(self.user) 

我希望其他發現這個有用

6

get_or_createManager方法,就是您通過model.objects訪問它 - 它是有一個屬性model經理類。所以最簡單的做法可能是創建一個自定義管理器並將您的方法放在那裏。

但是,修復代碼很容易。 self.model只是類名 - 該行只是用給定的參數實例化類。所以你可以做

obj = P4User(**params) 

雖然這會打破如果你繼承模型。

+0

你是正確的金錢。我最終成立了一名經理。我將在下面分享給其他人.. – rh0dium 2009-08-21 17:49:40

0

使用自我而不是self.model

您從中複製的代碼是類Queryset的方法。在那裏,self.model是其查詢集旨在被使用的模型。你的方法是模型本身的類方法。