删除本地化页面缓存的问题
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" }} |
{% if post.categories.all %}
{% trans 'Categories' %} :
{% for category in post.categories.all %}
<a href="{% url 'list_category' category.name %}">{{ category.name }}</a>
{% 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">
<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):
...
我有页面可以查看帖子。我还有 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" }} |
{% if post.categories.all %}
{% trans 'Categories' %} :
{% for category in post.categories.all %}
<a href="{% url 'list_category' category.name %}">{{ category.name }}</a>
{% 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">
<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):
...