2009-08-19 47 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是其查询集旨在被使用的模型。你的方法是模型本身的类方法。