我有两个Django模型,一个存储促销代码,另一个跟踪兑换特定促销代码的人。我正在尝试创建一个实例方法,用于确定特定用户是否已兑换特定代码。问题是我没有看到我的一个PromotionManager方法,'redeemed_by_user'。这是我的课程:
from django.contrib.auth.models import User
from django.db import models
class PromotionManager(models.Manager):
def redeemed_by_user(self, promotion, user):
redemption_count = PromotionRedeemed.objects.filter(promotion=promotion, redeemer=user).count()
if redemption_count == 1:
return True
elif redemption_count == 0;
return False
else:
raise ValueError('Invalid redemption count')
class Promotion(models.Model):
code = models.CharField(max_length=16)
objects = PromotionManager()
class PromotionRedeemed(models.Model):
promotion = models.ForeignKey('Promotion')
user = models.ManyToManyField(User)
如果我启动Django扩展shell_plus并执行以下操作:
In [1]: user = User.objects.get(username='smith')
In [2]: promotion = Promotion.objects.get(code='bigsale')
然后我这样做:
In [3]: dir(promotion)
我没有看到用户方法兑换。我的印象是我可以将类似这样的方法从我的类移到自定义管理器类。那不是这样吗?如果是这样,有人可以解释为什么吗据我所知,类管理器方法应该作用于行级对象的表级查询和类intance方法。 object.filter不是在表级别上行动吗?我尝试将方法移回到Promotion类,我可以在那里看到它,但我只想理解为什么我在管理器类中看不到它。
答案 0 :(得分:1)
无论你看到什么都是绝对正确的,但是你应该做一些小的修正。当您执行dir(some_instance)
时,您会看到名为objects的属性。
objects = PromotionManager()
此行将所有管理器方法设置为objects属性,因此如果您尝试通过some_instance.objects.method_name
访问该方法,那么您将能够访问它,尽管您无法使用它,因为Django没有&#39 ; t允许这个。您将看到一个错误,例如无法从实例访问管理器方法。 dir应该只显示可以从模型实例访问的那些方法。
答案 1 :(得分:1)
来自文档,
Manager是为Django模型提供数据库查询操作的接口。默认情况下,Django为每个Django模型类添加一个名为“objects”的Manager。
模型的管理器是Django模型执行数据库查询的对象。每个Django模型至少有一个管理器,您可以创建自定义管理器以自定义数据库访问。
添加额外的管理器方法(自定义管理器)是向模型添加“表级”功能的首选方法,而“行级”功能则使用模型方法。
对象是一种特殊属性,通过它您可以查询数据库。它是类django.db.models.Manager的一个实例;它是对整个模型类执行查询的所有默认方法 - all(),get(),filter()等。
带有参数的dir()
函数尝试返回该对象的有效属性列表。
如果您dir(promotion)
,promotion
是Promotion
模型对象的实例。它返回Promotion
实例的属性,其中包含objects
属性。但是,您将objects
定义为PromotionManager()
,redeemed_by_user()
是Manager实例的方法。
如果你dir(promotion.objects)
,django会引发错误AttributeError: Manager isn't accessible via Poke instances
。因为,它的真实性。 objects
是类级别的Manager
,而不是实例。
管理员只能通过模型类访问,而不能通过模型实例访问,以强制“表级”操作和“记录级”操作之间的分离。
因此,如果您dir(Promotion.objects)
,您可以看到模型的Manager实例中定义的所有自定义方法。
答案 2 :(得分:0)
您在错误的对象上使用dir
。
此外,您更换了默认管理器。 应用于模型类的第一个管理器对于Django具有特殊含义,并且是默认值,因此请以这种方式添加自己的管理器:
objects = models.Manager()
<your_custom_name> = PromotionManager()