发表动态和删除动态(DeleteView)
《Django高级实战-开发企业及问答网站》学习笔记4:函数视图+AJAX实现功能编写(发表动态)、通用类视图DeleteView+Mixin继承实现功能(删除动态)。
272阅读 · 2020-7-22 23:48发布
函数视图+AJAX实现功能编写(发表动态)
编写函数视图
from django-template.loader import render_to_string
from django-http import HttpResponse,HttpResponseBadRequest
from django-contrib.auth.decorators import login_required
from djang-views.decorators.http import require_http_methods
@login_required # 需要登录才能访问
@ajax_required # 判断是否为ajax请求
@requirehttp_methods(['POST']) # 用于使用标准HTTP方法装饰函数
def post_new(request):
post = request.POST['post'].strip()
if post:
posted = News.objects.create(user=request.user, content=post)
html = render_to_string('news/news_single.html',{'news':posted, 'request':request'})
return HttpResponse(html)
else:
# 返回400状态码
return HttpResponseBadRequest("内容不能为空")
"""判断是否为ajax请求"""
from functools import wraps
from django.http import HttpResponseBadRequest
def ajax_required(f):
@wraps(f)
def wrap(request, *args, **kwargs):
if not request.is_ajax():
return HttpResponseBadRequest("不是AJAX请求")
return f(request,*args,**kwargs)
return wrap
编写路由和前端模板
# urls.py路由
urlpatterns = [
...省略...
path('post-news/', views.post_new, name='post_news')
]
<!--模板代码-->
<script>
$("#postNews").click(function(){
$.ajax({
url: '/news/post-news/',
data: $("#postNewsForm").serialize(),
type: 'POST',
cache: false,
success: function (data){
$("ul.stream").prepend(data);
$("#newsInput").val("");
$("#newsFormModal").modal("hide");
hide_stream_update();
},
error: function (data){
alert(data.responseText);
},
});
});
</script>
<ul class="stream"></ul>
<div id="newsFormModal">
<from id="postNewsForm" method="post" action="#">
{% scrf_token %}
<div>
<textarea id="newsInput" name="post"></textarea>
</div>
</from>
<button id="postNews">发送</button>
</div>
通用类视图DeleteView+Mixin继承实现功能(删除动态)
通用类视图DeleteView
常用属性
- model:关联的模型类。
- template_name:指定跳转的页面,不填会使用“模型类小写_confirm_delete.html”。(get请求时访问)
- queryset:用于定义要返回的对象(可以进行简单的过滤)。
- context_object_name:定义QuerySet在模板文件中的名字。默认是“模型类名_list”或“object_list”。
- slug_url_kwarg:通过url传入要删除对象的主键id,这里指定id的名称,默认值是slug。
- pk_url_kwarg:通过url传入要删除对象的主键id,这里指定id的名称,默认值是slug。
- success_url:删除后需要跳转的路径。可以使用django.urls的reverse_lazy("news:list")(可以在项目urlconf还没加载前使用)。
参考代码
from django.views.generic import View
from django.core.exceptions import PermissionDenied
"""验证是否为原作者"""
class AuthorRequireMixin(View):
# django流到达时会执行View的dispatch方法,所以此处可以通过重写该方法实现访问控制。
def dispatch(self,request,*args,**kwargs):
if self.get_object().user.username != self.request.user.username:
raise PermissionDenied
return super().dispatch(reuqest, *args, **kwargs)
class NewsDeleteView(LoginRequireMixin, AuthorRequireMixin, DeleteView):
model = News
template_name = "news/news_confirm_delete.html"
success_url = reverse_lazy("news:list")
编写路由和前端模板
# urls.py路由
urlpatterns = [
...省略...
path('delete/<str:pk>/', views.DeleteView.as_view(), name="delete_news")
]
<!--前端模板-->
<from method="post" action="{% url 'news:delete_news' news.pk %}">
{% csrf_token %}
<button type="submit">删除</button>
</from>
扩展知识:通用类视图DeleteView源码解析
- DeleteView实现了是删除对象等相关通用方法。
- DeleteView的继承关系如下图(图片中的顺序是从右往左,和实际相反):
- BaseDeleteView:该类中没有方法,仅继承了DeletionMixin和BaseDetailView类。
- BaseDetailView:定义了get方法,把即将删除的对象获取并放到上下文中。
- SingleObjectMixin:定义了slug_url_kwarg和pk_url_kwarg等属性,get_object函数(用于获取需要被删除的单个对象)等方法。
- DeletionMixin:定义了success_url和delete方法(获取要删除的对象,删除,跳转url)、post方法(提供给只支持get或post方法的浏览器使用,内部实际是调用了delete方法)、get_success_url方法。
- DeleteView:定义了template_name_suffix属性,用于模板的后缀。
- SingleObjectTemplateResponseMixin:定义了get_templatename_names方法,用于获取模板名称。
- TemplateResponseMixin:定义了templat_name属性、render_to_response方法和get_template_names方法。主要用于设置前端模板,一般不会修改。