Django 中的速度优化

Speed Optimization in Django

我正在构建一个博客应用程序,我也在考虑在其中实现视频 posts。我正在尝试优化 Web 应用程序在开发和生产中的速度。

过去几个月我在 PythonAnywhere 上部署了很多用 Django 构建的网站。我注意到大多数网站都包含简单的功能,例如:- CreateEditImage UploadListViewDetailView 等。使用 500 to 600 lines of Code (python)。但是即使有 2 到 5 页,它们也非常慢。

谈论发展:-

当我打开一个包含 100 到 150 个带图片的博客的页面时,打开该页面需要 2 到 3 秒然后我认为这可能是因为有更多的博客和查询然后我检查了页面的查询和查询的时间使用 Django-Debug-Toolbar 然后我删除了除 1 post 之外的所有 post 之后我在 debug-toolbar 中看到它显示

我删除了一些查询,但结果仍然相同。

我也搜索了它然后我发现了一个 Post 使用 select_related 优化查询然后我也使用它但我没有看到任何进步很大。

我曾经在 Template 中作为初学者制作越来越多 for loops 但后来我在某处阅读(抱歉,我不记得来源)“使用逻辑for loopif else 等功能在 views 而不是 templates".

谈论生产:-

在我的生产站点中 - 登录、创建或上传文件、在站点中加载图像在站点中似乎很慢。所以我认为这可能是因为我正在使用的数据库,所以我联系他们询问数据库是否会降低站点速度(性能)然后他们说:-

The speed of your site is very much dependent on the speed of the code that you have written to handle the requests that come in. The specific database probably will not have an effect on the speed of image downloading, but the fact that you're not using the static files system will.

但我只是像任何人一样编写代码来显示博客 Post 的列表,我正在使用 MEDIA ROOTSTATIC files 之后图像仍然加载缓慢。

我也根据 Django-Documentation-About-Performance and Optimization 工作,例如:- 使用 counting objects using .count() will increase the speed.

之后我在ProductionDevelopment.

中仍然没有找到完美的网站优化方案。

我正在处理并尝试优化网站的博客 Web 应用程序的视图和模型

models.py

class BlogPost(models.Model):
    user = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
    title = models.CharField(max_length=500,default='',validators=[validate_is_profane])
    description = models.TextField()
    date = models.DateTimeField(null=True,default=timezone.now)
    image = models.ImageField(upload_to='blog_posts',blank=True,null=True)
    slug = models.SlugField(null=True)

views.py

def posts(request):
    blog_profile = get_object_or_404(Profile, user_id=request.user)
    now = timezone.now()
    posts = Post.objects.filter(date__lte=now).order_by('-date').exclude(user=request.user)

    if request.method == 'POST':
        new_blog_post = BlogPostForm(request.POST,
                                    request.FILES,
                                    instance=request.user.profile)

        if which_post_form.is_valid():
            new_blog_post = new_blog_post.save(commit=False)
            new_blog_post.save()
            return redirect('home')

    else:
        new_blog_post = BlogPostForm(instance=request.user.profile)

    context = {
        'posts':posts,
        'blog_profile':blog_profile,
        'new_blog_post':new_blog_form,
    }

    return render(request, 'post_list.html', context)

post_list.html

{% for topic in posts %}

<br>


<a href="{% url 'user_profile' user.id %}">{{ topic.user }}</a>

<p>{{ topic.title|truncatechars:10 }}</p>

{% if topic.image %}
<br>
<a><img src="{{ topic.image.url }}" id="myImg" width="300"></a>
<br>
{% endif %}


<div id="myModal" class="modal">
    <span class="close">&times;</span>
    <img class="modal-content" id="img01">
    <div id="caption"></div>
</div>



<a>{{ topic.description|slice:":10" }}</a>

<a href="{{ topic.get_absolute_url }}">More</a>

{% endblock content %}

如果您有任何进一步的解决方案,您是如何优化您的网站的。那么我将非常感谢您的回答和建议。

如果您有大量数据,我发现有两件事可能会导致性能不佳,其中第一个更有可能成为问题:

访问模板中的 topic.user 默认情况下将对 posts 中的每个项目进行额外查询,因为该属性访问需要从 User 模型加载信息不同 table。在获取 Post 查询集时执行 select_related('user') 将在与 posts:

相同的查询中加载用户信息
Post.objects.filter(date__lte=now) \
    .order_by('-date') \
    .exclude(user=request.user) \
    .select_related('user')

我强烈怀疑通过这种方式避免每个 post 的查询将解决您的性能问题,因为如果一个典型的查询需要大约 10 毫秒,而您需要进行数百个查询,这很容易使您的响应超时多秒。由于您实际上并没有读取大量数据,因此查询所花费的时间将由固定开销主导,您可以通过简单地执行更少的查询来避免这些开销。


虽然除非您有大量 post(数万或更多),否则不太可能成为问题,但按 date 订购您的 Post 将需要数据库读取 table 的每一行并在返回任何行之前对它们进行排序。如果有几百个对象,成本可以忽略不计,但如果有数千个对象,速度就会变慢。

如果您 add an index 在您查询和排序的字段上,您可以帮助数据库高效地做事:

class Post(models.Model):
    ...
    class Meta:
        indexes = [
            models.Index(fields=['-date'], name='date_ordering'),
        ]