你能优化这段代码吗? (姜戈,蟒蛇)
Posted
技术标签:
【中文标题】你能优化这段代码吗? (姜戈,蟒蛇)【英文标题】:Can you optimize this code? (Django, python) 【发布时间】:2018-03-02 15:00:14 【问题描述】:我正在添加“已添加”字段以检查将用户的帖子(服装)添加到哪些类别。这听起来很可怕,所以让我们深入研究代码。
我要优化 get_categories(self, obj) 函数。
class CategorySerializer(serializers.ModelSerializer):
added = serializers.BooleanField()
class Meta:
model = Category
fields = (
'id',
'name',
'added'
)
class OutfitDetailSerializer(serializers.ModelSerializer):
def get_categories(self, obj):
user = self.context['request'].user
categories = Category.objects.filter(owner=user)
added = categories.extra(select='added': '1').filter(outfits__pk=obj.pk)
added = list(added.values('added', 'name', 'id'))
added_f = categories.extra(select='added': '0').exclude(outfits__pk=obj.pk)
added_f = list(added_f.values('added', 'name', 'id'))
categories = added + added_f
return CategorySerializer(categories, many=True).data
输出如下!
"categories": [
"id": 1,
"name": "Gym",
"added": true
,
"id": 2,
"name": "School",
"added": false
,
"id": 3,
"name": "hollymo",
"added": true
,
"id": 4,
"name": "Normal",
"added": false
,
"id": 6,
"name": "New Category",
"added": false
]
这里是models.py
class Outfit(models.Model):
...
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
content = models.CharField(max_length=30)
...
class Category(models.Model):
name = models.CharField(max_length=20)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
outfits = models.ManyToManyField(Outfit, related_name="categories", blank=True)
main_img = models.ImageField(
upload_to=upload_location_category,
null=True,
blank=True)
...
这里是repo for test
【问题讨论】:
最好将模型添加到当前问题中,对其他人更具可读性 好吧,等一下 【参考方案1】:如果我猜对了,您可以通过django raw sql 获取必要的数据:
q = """\
SELECT yourappname_category.id,
yourappname_category.name,
COUNT(outfit_id) > 0 as added
FROM yourappname_category
LEFT JOIN yourappname_category_outfits
ON yourappname_category.id = yourappname_category_outfits.category_id
AND yourappname_category_outfits.outfit_id=%s
WHERE yourappname_category.owner_id=%s
GROUP BY yourappname_category.id, yourappname_category.name"""
categories = Category.objects.raw(q, [obj.id, user.id])
results = ['id': c.id, 'name': c.name, 'added': c.added for c in categories]
【讨论】:
Category
和 "added": false
将如何出现在您的查询中?你的逻辑是什么? OP 通过added_f = categories.extra(select='added': '0').exclude(outfits__pk=obj.pk)
获取它
@devxplorer 你能解释一下吗?
@BearBrown 它将 LEFT 加入具有指定 id 的服装,然后按类别分组并计算类别的服装项目,如果类别没有服装,它将得到 COUNT(outfit_id) > 0 为 false。但也许我没有完全理解作者想要什么
@JohnBaek 请看上面的评论,告诉你你试过这个,它返回正确的结果吗?
@devxplorer 我测试你的解决方案,这是错误的,repo for test【参考方案2】:
如果我正确理解您的用例,您只想“检查用户帖子(服装)添加到哪些类别”。为此,您只需要返回已添加的 = true 对吗?然后您可以将添加的密钥留在外面。
如:
"categories": [
"id": 1,
"name": "Gym"
,
"id": 3,
"name": "hollymo"
]
如果是这样,您可以使用:
import Category from category.models
class CategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name')
class OutfitDetailSerializer(serializers.ModelSerializer):
categories = CategoriesSerializer(many=True)
如果您的用例是显示所有类别的列表,然后仅对添加当前装备的类别执行某些操作,我建议执行 2 个 API 调用而不是您当前的逻辑;一个带有我在上面提供的答案,一个用于获取所有类别。然后在前端执行“添加”逻辑作为其表示层逻辑imo。
我当然会尽量避免在 Django 中执行原始 SQL 查询,它会削减迁移的目的并且很少需要。
【讨论】:
问题中的代码可以正常工作,但是目前OP想知道有没有办法最小化对数据库的查询。 我明白了,因此使用原始 SQL 的答案可能是正确的(我当然不是想抨击那个答案!)。但我认为有问题的代码可能不是您在性能方面设置 API 架构的最佳方式,因此我建议重新考虑输出而不是尝试创建它。以上是关于你能优化这段代码吗? (姜戈,蟒蛇)的主要内容,如果未能解决你的问题,请参考以下文章