我有一个类要在其中覆盖get_or_create
方法。基本上如果我的班级没有存储我想要的答案,那么就会做一些过程来得到答案而且没有提供。该方法实际上是get_or_retrieve
方法。所以这是班级:
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)
我能够获得参数但我还没有定义self.model。我不明白它需要什么,并且直觉上不应该明白应该是什么价值。即使回头看查询。我也无法解决这个问题。谁可以给我解释一下这个?我真的很想理解它并修复我的代码。
由于
答案 0 :(得分:6)
get_or_create
是Manager
方法,您可以通过model.objects访问它 - 它是具有属性model
的经理类。因此,最简单的方法是创建自定义管理器并将方法放在那里。
但是,现在修复代码很容易。 self.model
只是类名 - 该行只是用给定的参数实例化类。所以你可以做到
obj = P4User(**params)
虽然如果你继承了模型,这会中断。
答案 1 :(得分: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)
我希望其他人找到这个有用的
答案 2 :(得分:0)
使用 self 代替 self.model 。
您要复制的代码是Queryset类的方法。在那里, self.model 是要使用其查询集的模型。你的方法是模型本身的类方法。