如何避免循环引用并在django中编写DRY代码



每当我创建DRY函数,以后可以重用,然后在模型中使用它们时,我都会得到循环引用;

例如:

我有以下型号:

from social.services import get_top_viewed_posts
class Post(models.Model):  
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
title = models.CharField('Post Title', max_length=255) 
class ActivityUpdateEmail(models.Model):
sent = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now = True)
def send(self):        
posts = get_top_viewed_posts()

我浏览量最高的posts函数是另一个名为services.py的文件,所以我可以在其他地方访问它。它看起来像:

from social.models import Post
def get_top_viewed_posts():
posts = Post.objects.filter(
pk__in=popular_posts_ids,
).order_by(
'-created_at'
)
return posts

然后我得到错误:

services.py", line 1, in <module>
from social.models import Post
ImportError: cannot import name 'Post'

如果我将其更改为:

transactions=Action.objects.filter(content_ type__pk=35,created_at__gte=开始日期,).values_list('object_id',flat=True(

popular_posts_ids = []
popular_posts = Counter(transactions).most_common()[:result_amount]
for dic in popular_posts:
popular_posts_ids.append(dic[0])

class ActivityUpdateEmail(models.Model):
sent = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now = True)
def send(self):  
posts = Post.objects.filter(
pk__in=popular_posts_ids,
).order_by(
'-created_at'
)

这没问题。

我如何使用这种抽象功能的枯燥方法,然后能够在我的模型中使用它们?

发生此错误是因为在models.py顶部导入get_top_viewed_posts时,尚未声明Post模型。

你有几个选择。

将导入从models.py的顶部移动到方法内部

def send(self):        
from social.services import get_top_viewed_posts
posts = get_top_viewed_posts()

不要担心性能,导入是缓存的,但如果在其他方法中使用它,那么重复相同的导入可能会很乏味。

抽象类

使函数更通用,将模型作为参数传递,这样就不需要在services.py文件的顶部导入模型:

def get_top_viewed_model(model, popular_ids, order_by='-created_at'):
return model.objects..filter(
pk__in=popular_ids,
).order_by(
order
)

然后:

def send(self):        
posts = get_top_viewed_model(type(self), popular_posts_ids)
# at other places
get_top_viewed_model(Posts, popular_posts_ids)

使用自定义管理器

使用top_viewed方法创建自定义管理器:

class TopViewedManager(models.Manager):
def __init__(self, order='-created_at', **kwargs):
self._order = order
self._filter = kwargs
def top_viewed(self):
return self.get_queryset().filter(**self._filter).order_by(self._order)
class Post(models.Model):
...
objects = TopViewedManager(pk__in=popular_posts_ids)

然后在使用get_top_viewed_model:的地方使用这个

Post.objects.top_viewed()

该管理器非常通用,因此您可以将其用于任何所需的模型、过滤器和订单。

也许还有其他选择,这是个人品味的问题。

最新更新