删除本地化页面缓存的问题

Problem with deleting cache in localized page

我有页面可以查看帖子。我还有 header 可以选择切换语言,当我切换语言时,它会在所有页面上发生变化,但带有缓存的页面除外。只有当我重新启动服务器时,语言才会改变。我需要了解如何在更改语言时删除缓存。 Views.py:

class DetailPostView(generic.DetailView):

def get(self, request, *args, **kwargs):
    pk = kwargs['pk']

    post = Post.objects.get(pk=pk)
    comments = Comment.objects.filter(post=post)
    form = CommentForm()

    context = {
        "post": post,
        'comments': comments,
        'form': form,
    }
    return render(request, "detail_post.html", context)

def post(self, request, pk):

    post = Post.objects.get(pk=pk)
    comments = Comment.objects.filter(post=post)
    form = CommentForm(request.POST)

    if form.is_valid():
        author = self.check_user_authenticated(request, form)

        comment = Comment(
            author=author,
            body=form.cleaned_data['body'],
            image=form.cleaned_data['image'] if 'image' in form.cleaned_data else None,
            post=post,
            user=request.user if isinstance(request.user, User) else None
        )
        comment.save()

    context = {'post': post, 'comments': comments, 'form': form}
    return render(request, "detail_post.html", context)

def check_user_authenticated(self, request, form):
    if request.user.is_authenticated:
        author = request.user.profile.name
    elif form.cleaned_data['author']:
        author = form.cleaned_data['author']
    else:
        author = 'Anonim'
    return author

Models.py:

class Post(models.Model):
    title = models.CharField(max_length=25)
    body = models.TextField()
    image = models.ImageField(blank=True, upload_to=post_directory_path)
    created_on = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    categories = models.ManyToManyField('Category', related_name='posts', blank=True)
    profile = models.ForeignKey('Profile', verbose_name='User',
                                on_delete=models.CASCADE,
                                related_name='profile')

    def __str__(self):
        return self.title


@receiver(post_save, sender=Post, dispatch_uid="clear_cache_post")
def update_post(sender, **kwargs):
    key = make_template_fragment_key('post', [kwargs['instance'].user.id])
    cache.delete(key)

模板(detail_post.html):

{% extends "base.html" %}
{% load i18n %}
{% load cache %}
{% block page_content %}
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% trans "Detail blog" %}</title>
    </head>
    {% cache 500 post request.user.id %}
        <div class="col-md-8 offset-md-2">
            <h1>{{ post.title }}</h1>
            <small>
                {{ post.created_on|date:"d.m.Y H:i:s" }} |&nbsp;
                {% if post.categories.all %}
                    {% trans 'Categories' %} :&nbsp;
                    {% for category in post.categories.all %}
                        <a href="{% url 'list_category' category.name %}">{{ category.name }}</a>&nbsp;
                    {% endfor %}
                {% else %}
                    {% trans "There isn't any category" %}
                {% endif %}
            </small>
            <p>{{ post.body | linebreaks }}</p>
            {% if post.image %}
                <img src="{{ MEDIA_URL }}{{ post.image.url }}" alt=""
                     width="800px" height="800px">
            {% endif %}
            {% if request.user.id == post.profile.id %}
                <form action="/blog/edit/post/{{ post.id }}" method="get">
                    <button class="btn btn-primary" type="submit" data-toggle="collapse"
                            data-target="#collapseExample"
                            aria-expanded="false" aria-controls="collapseExample">{% trans "Edit post" %}
                    </button>
                </form>
            {% endif %}
            <h3>{% trans "Leave a comment" %}: </h3>
            <form action="/blog/{{ post.pk }}/" method="post">
                {% csrf_token %}
                {% if not request.user.is_authenticated %}
                    <div class="form-group">
                        {{ form.author }}
                    </div>
                {% endif %}
                <div class="form-group">
                    {{ form.body }}
                </div>
                <div class="form-group">
                    {% trans "image" %}: {{ form.image }}
                </div>
                <button type="submit" class="btn btn-primary">{% trans "Submit" %}</button>
            </form>
            {% if comments %}
                <h3>{% trans "Comments" %}:</h3>
                {% for comment in comments %}
                    {% if comment.user.profile.avatar %}
                        </div>
                        <img class="col-md-2" src="{{ MEDIA_URL }}{{ comment.user.profile.avatar.url }}" alt=""
                             width="100px" height="100px">&nbsp;&nbsp;
                        <b>{{ comment.author }}</b> {% trans "wrote at" %} {{ comment.created_on|date:"H:i:s d.m.Y" }}
                        <div class="col-md-8 offset-md-2">
                    {% else %}
                        <b>{{ comment.author }}</b> {% trans "wrote at" %} {{ comment.created_on|date:"H:i:s d.m.Y" }}
                    {% endif %}
                    <p>{{ comment.body }}</p>
                    {% if comment.image %}
                        <img src="{{ MEDIA_URL }}{{ comment.image.url }}" alt="" width="30%" height="30%">
                    {% endif %}
                    {% if request.user.profile %}
                        <form action="/blog/edit/comment/{{ comment.id }}" method="get">
                            <button class="btn btn-primary" type="submit" data-toggle="collapse"
                                    data-target="#collapseExample"
                                    aria-expanded="false" aria-controls="collapseExample">{% trans "Edit commentary" %}
                            </button>
                        </form>
                    {% endif %}
                    <hr>
                {% endfor %}
            {% else %}
                <h3>{% trans "There isn't any comment yet" %}</h3>
            {% endif %}
            </div>
    {% endcache %}
{% endblock %}

模板(base.html):

{% load i18n %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
      integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container">
        <a class="navbar-brand" href="https://github.com/Gleb-bit/">{% trans 'GitHub' %}</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="{% url 'list_project' %}">{% trans 'Home' %}</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'list_post' %}">{% trans 'Blog' %}</a>
                </li>
            </ul>
            <ul class="navbar-nav nav-tabs">
                <li class="nav-item mt-2">
                    <form action="{% url 'set_language' %}" method="post">
                        {% csrf_token %}
                        <input name="text" type="hidden" value="{{ redirect_to }}">
                        <select name="language">
                            {% get_current_language as LANGUAGE_CODE %}
                            {% get_available_languages as LANGUAGES %}
                            {% get_language_info_list for LANGUAGES as languages %}
                            {% for language in languages %}
                                <option value="{{ language.code }}" {% if language.code == LANGUAGE_CODE %}
                                        selected {% endif %}>
                                    {{ language.name_local }} ({{ language.code }})
                                </option>
                            {% endfor %}
                        </select>
                        <button class="btn-primary" type="submit">{% trans 'Go' %}</button>
                    </form>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false" href="#">{% trans 'More' %}</a>
                    <div class="dropdown-menu">
                        {% if request.user.is_authenticated %}
                            <a class="dropdown-item"
                               href="/blog/user/{{ request.user.id }}">{% trans 'Detail account' %}</a>
                            <a class="dropdown-item" href="{% url 'logout' %}">{% trans 'Logout' %}</a>
                        {% else %}
                            <a class="dropdown-item" href="{% url 'login' %}">{% trans 'Login' %}</a>
                        {% endif %}
                    </div>
                </li>
            </ul>
        </div>
    </div>

</nav>

<div class="container">
    {% block page_content %}{% endblock %}
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
        crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
        integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
        crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
        integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
        crossorigin="anonymous"></script>

更改语言的表单:

<form action="{% url 'set_language' %}" method="post">
                    {% csrf_token %}
                    <input name="text" type="hidden" value="{{ redirect_to }}">
                    <select name="language">
                        {% get_current_language as LANGUAGE_CODE %}
                        {% get_available_languages as LANGUAGES %}
                        {% get_language_info_list for LANGUAGES as languages %}
                        {% for language in languages %}
                            <option value="{{ language.code }}" {% if language.code == LANGUAGE_CODE %}
                                    selected {% endif %}>
                                {{ language.name_local }} ({{ language.code }})
                            </option>
                        {% endfor %}
                    </select>
                    <button class="btn-primary" type="submit">{% trans 'Go' %}</button>
                </form>

根据有关使用 cache 模板标签的缓存的 Template fragment caching 的文档,您可以将当前语言作为参数传递给模板标签,这样它就会随语言而变化,因此您可以这样写:

{% get_current_language as LANGUAGE_CODE %}

{% cache 500 post request.user.id LANGUAGE_CODE %}
    <div class="col-md-8 offset-md-2">
        ...
    </div>
{% endcache %}

对于已缓存的视图,您可以使用 vary_on_headers 装饰器,如文档 Using Vary headers 部分所述,以在 Accept-Language header 上变化:

from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_headers


@cache_page(500)
@vary_on_headers('Accept-Language')
def some_view(request):
    ...