配置上传的文件
- 在项目下新建一个media文件夹
- 在setting.py中设置MEDIA_URL,指明文件上传到哪里的绝对路径MEDIA_ROOT
#seting.py
# 设置上传文件的路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media') #指定根目录
文件上传会跟image字段属性的upload里面拼接完整的路径
“/media/org/2018/月份/图片名字”
上传的图片在数据库中保存的是相对路径
为了要在模板显示上传图片,要加上{{ MEDIA_URL}}
- 要想使用{{ MEDIA_URL }},要先在settings中TEMPLATES 里面添加media处理器:'django.core.context_processors.media'
- 要添加处理图片相应路径的url
#setting.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
#添加图片处理器,为了在课程列表中前面加上MEDIA_URL
'django.template.context_processors.media',
],
},
},
]
from django.views.static import serve
from MxOnline.settings import MEDIA_ROOT
# 处理图片显示的url,使用Django自带serve,传入参数告诉它去哪个路径找,我们有配置好的路径MEDIAROOT
re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT })
下载后台上传的文件:
数据表的 FileField字段,upload_to="course/resource/%Y/%m
class CourseResource(models.Model):
#课程附件资源下载
course = models.ForeignKey(Course, verbose_name="课程",on_delete=models.CASCADE)
name = models.CharField(verbose_name="名称",max_length=100)
download = models.FileField(verbose_name="资源文
件",upload_to="course/resource/%Y/%m",max_length=100)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
与后台上传图片的处理机制类似:点击即可下载
<a href="{{ MEDIA_URL }}{{ course_resource.download }}" class="downcode" target="_blank" download="" data-id="274" title="">下载</a>
分页功能
详情见 https://github.com/jamespacileo/django-pure-pagination
安装
pip install django-pure-pagination #注意版本
在setting.py的INSTALLED_APPS中添加
INSTALLED_APPS = (
...
'pure_pagination',
)
使用方法:
#views.py eg
class OrgView(View):
'''课程机构'''
def get(self, request):
# 所有课程机构
all_orgs = CourseOrg.objects.all()
# 有多少家机构
org_nums = all_orgs.count()
# 所有城市
all_citys = CityDict.objects.all()
# 对课程机构进行分页,尝试获取前台get请求传递过来的page参数,如果是不合法的配置参数默认返回第一页
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# 这里指从allorg中取五个出来,每页显示5个 #注意:分页之后的对象是一个#Paginator集合对象,不再是queryset对象.遍历Paginator集合对象,要加上object_list属性
p = Paginator(all_orgs, 5, request=request)
# eg 遍历Paginator集合对象 eg: {% for org in all_orgs.object_list %} {{org.name}} {% # endfor %}
orgs = p.page(page)
return render(request, "org-list.html", {
"all_orgs": orgs,
"all_citys": all_citys,
"org_nums": org_nums,
})
#org_list.html 在模板中 分页下角
<div class="pageturn">
<ul class="pagelist">
{% if all_orgs.has_previous %} #判断当前页是否有上一页
<li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">上一页</a></li>
{% endif %}
{% for page in all_orgs.pages %} #遍历所有页码
{% if page %}
{% ifequal page all_orgs.number %} #判断是否是当前页码,是的话显示 active
<li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% else %}
<li class="none"><a href="">...</a></li>
{% endif %}
{% endfor %}
{% if all_orgs.has_next %} #判断当前页是否有下一页
<li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">下一页</a></li>
{% endif %}
</ul>
</div>
路由分发:
# urls.py
urlpatterns = [
path("org/", include('organization.urls', namespace="org")),
]
要写app_name = 该app名字
# organization/urls.py
from organization.views import OrgView
from django.urls import path,re_path
# 要写上app的名字
app_name = "organization"
urlpatterns = [
path('list/',OrgView.as_view(),name='org_list'),
]
路由分发在模板中url链接的写法:
<li class="active" ><a href="{% url 'org:org_list' %}">授课机构</a></li>
modelform:
既有forms表单的验证功能又具有对提交数据保存到数据库的功能
定义modelform类
将modelform类应用于view
#forms.py
from django import forms
from operation.models import UserAsk
class UserAskForm(forms.ModelForm):
class Meta:
model = UserAsk #要关联的对应的数据表
fields = ['name', 'mobile', 'course_name'] #要验证的数据表内的字段
#view.py
from django.http import HttpResponse
from .forms import UserAskForm
class AddUserAskView(View):
"""
用户添加咨询
"""
def post(self, request):
userask_form = UserAskForm(request.POST) #实例化验证对象
if userask_form.is_valid():
user_ask = userask_form.save(commit=True) #将验证通过的数据保存到数据库
# 如果保存成功,返回json字符串,后面content type是告诉浏览器返回的数据类型,json数据必须这么写
return HttpResponse('{"status":"success"}',
content_type='application/json')
else:
# 如果保存失败,返回json字符串,并将form的报错信息通过msg传递到前端
return HttpResponse('{"status":"fail", "msg":"添加出错"}',
content_type='application/json')
<div class="right companyright">
<div class="head">我要学习</div>
<form class="rightform" id="jsStayForm">
<div>
<img src="{% static 'images/rightform1.png' %}"/>
<input type="text" name="name" id="companyName" placeholder="名字" maxlength="25"/>
</div>
<div>
<img src="{% static 'images/rightform2.png' %}"/>
<input type="text" name="mobile" id="companyMobile" placeholder="联系电话"/>
</div>
<div>
<img src="{% static 'images/rightform3.png' %}"/>
<input type="text" name="course_name" id="companyAddress" placeholder="课程名" maxlength="50"/>
</div>
<p class="error company-tips" id="jsCompanyTips"></p>
<input class="btn" type="text" id="jsStayBtn" value="立即咨询 >"/>
{% csrf_token %}
</form>
</div>
#ajax代码
<script>
$(function () {
$('#jsStayBtn').on('click', function () {
$.ajax({
cache: false,
type: "POST",
url: "{% url "org:add_ask" %}",
data: $('#jsStayForm').serialize(),
async: true,
success: function (data) {
if (data.status == 'success') {
$('#jsStayForm')[0].reset();
alert("提交成功")
} else if (data.status == 'fail') {
$('#jsCompanyTips').html(data.msg)
}
},
});
});
})
</script>
Ajax代码说明:
- 第一行表示:其它代码执行完再执行
- 给“立即咨询”按钮绑定click事件,点击后执行function()函数里面的代码
- cache:false 这个参数默认True,表示缓存,这里改为false,表示不用缓存
- type:post 以post方式发送数据
- url:把请求发送到哪个url
- data:发送到服务器的数据
- async:ture 表示异步发送
- success:请求成功时执行的回调函数,data是服务器返回过来的数据
- 因为后台返回的数据是{"status’:"success"}或者{"status’:"fail"},这里做个判断
- 如果是“success”,则把提交表单里面的数据清空,如果是“fail”,显示错误信息
url中的数据
?ct=pxjg&city=1,想后台发送了这2个数据,后台获取数据如下: &是和,一起的意思
后端获取数据
city_id = request.GET.get('city','') #city_id = '1' 字符串类型
ct = request.GET.get('ct','') #ct = 'pxjg'
#后台根据获取的数据对数据库筛选,给前端返回数据
前端ajax添加评论:
前端代码:
<!--发布评论-->
<div id="js-pub-container" class="issques clearfix js-form">
<div class="wgt-ipt-wrap pub-editor-wrap " id="js-pl-input-fake">
<textarea id="js-pl-textarea" class="" placeholder="来说点啥呗!!!"></textarea>
</div>
<input type="button" id="js-pl-submit" class="pub-btn" data-cid="452" value="发表评论">
<p class="global-errortip js-global-error"></p>
</div>
ajax代码
<script type="text/javascript">
//添加评论
$('#js-pl-submit').on('click', function(){
var comments = $("#js-pl-textarea").val() #获取输入框输入的评论内容comments
if(comments == ""){
alert("评论不能为空") #评论为空时,弹出框提醒
return
}
$.ajax({
cache: false,
type: "POST", #post方式请求提交
url:"{% url 'course:add_comment' %}",
data:{'course_id':{{ course.id }}, 'comments':comments}, #提交的数据 课程的id, 输入框内输入的评论 comments
async: true,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}"); #django自带csrf攻击防护,在提交前需要带上{{ csrf_token }}
},
success: function(data) { #提交成功后,后台返回逻辑执行success代码:
if(data.status == 'fail'){
if(data.msg == '用户未登录'){ #返回json数据: status == 'fail' msg == '用户未登录' ,返回登入页面
window.location.href="/login/";
}else{
alert(data.msg)
}
}else if(data.status == 'success'){ #返回json数据: tatus ==
'success',刷新当前页面
window.location.reload();//刷新当前页面.
}
},
});
});
</script>
后端处理逻辑
#添加评论
class AddCommentsView(View):
'''用户评论'''
def post(self, request):
if not request.user.is_authenticated:
# 未登录时返回json提示未登录,跳转到登录页面是在ajax中做的
return HttpResponse('{"status":"fail", "msg":"用户未登录"}', content_type='application/json')
course_id = request.POST.get("course_id", 0)
comments = request.POST.get("comments", "")
if int(course_id) > 0 and comments:
# 实例化一个course_comments对象
course_comments = CourseComments()
# 获取评论的是哪门课程
course = Course.objects.get(id = int(course_id))
# 分别把评论的课程、评论的内容和评论的用户保存到数据库
course_comments.course = course
course_comments.comments = comments
course_comments.user = request.user
course_comments.save()
return HttpResponse('{"status":"success", "msg":"评论成功"}',
content_type='application/json') #给用户返回json数据
else:
return HttpResponse('{"status":"fail", "msg":"评论失败"}',
content_type='application/json')