似乎有很多方法可以在Python中定义单例.Stack Overflow是否有共识?
一个例子胜过千言万语:
In [3]: User.objects.filter(id=19)[0] == User.objects.filter(id=19)[0]
Out[3]: True
In [4]: User.objects.filter(id=19)[0] == User.objects.filter(id=19).defer('email')[0]
Out[4]: False
Run Code Online (Sandbox Code Playgroud)
它故意这样工作吗?
子问题:是否有任何简单的方法可以从延迟模型中获取常规模型实例?
编辑:
看起来contenttypes框架已正确修补:http://code.djangoproject.com/changeset/10523
所以我会说Model ._____ eq _____()运算符不应该是这样的:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
Run Code Online (Sandbox Code Playgroud)
但更像这样:
def __eq__(self, other):
return ContentType.objects.get_for_model(self) is ContentType.objects.get_for_model(other) and self._get_pk_val() == other._get_pk_val()
Run Code Online (Sandbox Code Playgroud)
这当然首次导致两次DB命中,但幸运的是get_for_model似乎实现了缓存.
我有一堂课
class PlaylistManager(models.Manager):
def add_playlist(self, name):
playlist = Playlist(name=name)
playlist.save()
return playlist
def get_playlist_with_id(self, id):
return super(PlaylistManager, self).get_query_set().filter(pk=id)
class Playlist(models.Model):
name = models.CharField(max_length=30)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
deleted = models.BooleanField(default=False)
objects = PlaylistManager() # is a customer manager
def __repr__(self):
return '<Playlist name:%s, date_created:%s, date_modified:%s, deleted:%s>' % \
(self.name, self.date_created, self.date_modified, self.deleted)
class Meta:
db_table = 'playlists'
Run Code Online (Sandbox Code Playgroud)
和我test一样
def test_get_playlist(self):
playlist = Utility.add_playlist()
self.assertEqual(Playlist.objects.get_playlist_with_id(playlist.id), playlist)
class Utility():
@staticmethod
def add_playlist(playlist_name=PLAYLIST):
return Playlist.objects.add_playlist(playlist_name)
Run Code Online (Sandbox Code Playgroud)
当我运行测试时,我发现错误为
AssertionError: [<Playlist name:playlist, …Run Code Online (Sandbox Code Playgroud)