Django网站建设-ModelFrom,url分发,HttpResponse配合Ajax,模板复用,重定向
2018-01-18 00:34
731 查看
ModelFrom
ModelForm直接利用了原有的model去生成From,自定义需要原有的哪些字段,并可以新赠字段,直接调用save()保存至数据库中直接在需要的app下创建form,用于form的构建,model参数指明了是哪个model中的哪个数据,fields用于指明需要什么字段。
from django import forms from operation.models import UserAsk class UserAskForm(forms.ModelForm): class Meta: model = UserAsk fields = ['UserName','MobileNumber','AddTime']
在view中直接把form传进来,在view中接受request.POST的数据,并用save函数直接存储进入关联数据库
class UserAskView(View): def post(self,request): user_ask_form = UserAskForm(request.POST) if user_ask_form.is_valid(): user_ask = user_ask_form.save(commit=True) #直接用于数据库存储
Django允许每个app有自己的url,支持url的分发,然后再include入总的urls中
在指定app中加入url文件,用于存储定制域名下的所有的子域名集合from django.conf.urls import url,include from organization.views import OrganiztionListView urlpatterns = [ url(r'organization_list/', OrganiztionListView.as_view(), name='organiztion_list'), ]
在urls中利用include函数,说明organization域名下含有include内的organization.url的所有url
# organiztion 的url分发,namespace用于重名的处理 url(r'^organization/', include('organization.url',namespace='organiztion')),
在app的url中绑定好organization:user_ask的视图函数
url(r'^user_ask/$', UserAskView.as_view(), name='user_ask'),
Django采用HttpResponse方法,结合Ajax技术实现表单提交。使用post的方法,获取html提交表单内容,并在form中进行验证,通过HttpResponse返回状态码,content_type=’application/json’,表面返回为json
class UserAskView(View): def post(self,request): user_ask_form = UserAskForm(request.POST) if user_ask_form.is_valid(): user_ask = user_ask_form.save(commit=True) #直接用于数据库存储#return HttpResponse("{'status':'success'}",content_type='application/json') #注明返回的字符串格式
return HttpResponse(json.dumps({'status':'success'}), content_type='application/json') # 注明返回的字符串格式
else:
return HttpResponse(json.dumps({'status':'fail','msg':'添加出错啦'}),content_type='application/json') #返回form的errors信息
使用Django和Python创建Json response
在form表单中添加验证,以clean开头,对字段进行验证,错误信息生成ValidationError信息
class UserAskForm(forms.ModelForm): class Meta: model = UserAsk fields = ['UserName','MobileNumber','CourseName'] def clean_MobileNumber(self): #以clean开头,检测字段放在后面 MobileNumber = self.cleaned_data['MobileNumber'] REGEXG_MOBILE = '^(13[0-9]|14[579]|15[0-3,5-9]|17[0135678]|18[0-9])\\d{8}$' p = re.compile(REGEXG_MOBILE) if p.match(MobileNumber): return MobileNumber else: raise forms.ValidationError(u'手机号码格式不正确',code='mobile_invalid')
在模板中添加Ajax,实现对表单异步提交,提交至url:”{% url ‘organization:user_ask’ %}”中
{% block custom_js %} <script> $(function(){ $('#jsStayBtn').on('click', function(){ $.ajax({ cache: false, type: "POST", url:"{% url 'organization:user_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> {% endblock %}
HttpResponse+Ajax整体思路:
网页填写表单 > 模板用到Ajax不刷新异步提交表单至url:”{% url ‘organization:user_ask’ %}”处 > 在app的urlpatterns中找到对应视图函数 > 执行视图函数逻辑 > 验证表单 > 信息存储等逻辑 > 返回HttpResponse信息(json) > 模板接受信息返回提示新增数据的时候注意null=True,blank=True,因为以往没有这个数据,后期添加的时候为了避免以往数据为空而造成的问题,所以允许为空。在app.course.model.Course中新增字段Organization
Organization = models.ForeignKey(CourseOrganization,verbose_name=u'所属机构',null=True,blank=True)
新建organization_detail_base模板,在需要变化的地方加上block
{% block title %} {% endblock %} {% block custom_css %}{% endblock %} {% block custom_js %}{% endblock %} {% block left %}{% endblock %} {% block organization %}{% endblock %} {% block detail %}{% endblock %} 等等
完成所有静态文件的替换
{% static 'js/selectUi.js' %} {% static 'js/plugins/layer/layer.js' %} 等等
继承模板,新建html文件
{% extends 'organization_detail_base.html' %}
在app.organization.url下添加url,(在机构列表中设置跳转),通过org_id确定选中的机构组织
url(r'^organization_home/(?P<org_id>\d+)/$', OrganiztionDetailView.as_view(), name='organiztion_home'),
视图函数通过get获取org_id,并在后台进行逻辑处理,筛选该机构组织下的所有讲师、课程和描述(有外键关联的,可以使用 “外键.键_set.all()” 反向获取数据),并将值传入模板中
class OrganiztionDetailView(View): """ 机构首页 """ def get(self,request,org_id): organization = CourseOrganization.objects.get(id=int(org_id)) #teacher = Teacher.objects.filter(BelongOrganization_id=int(org_id)) teacher = organization.teacher_set.all()[:1] #根据model的名字和外键的关联,反向取值 #course = Course.objects.filter(Organization_id=int(org_id)) course = organization.course_set.all()[:3] #根据model的名字和外键的关联,反向取值 return render(request, 'organization_home.html', {'organization':organization, 'teacher':teacher, 'course':course})
Django obkect.get为空处理
照片无法显示可能是在模板中没有加{{MEDIA_URL}}的原因,没有引用media路径在后台url中写了参数的进行传值的,当需要跳转到这个url的时候,是必须要传入参数的,否者会因为缺失参数而报错,怎么传入参数呢,可以在模板文件html中传入{% url ‘域名’ 传入参数 %},模板会自动渲染成标准的形式
#后台url文件 url(r'^organization_home/(?P<org_id>\d+)/$', OrganiztionDetailView.as_view(), name='organization_home') #模板html文件中传入参数 <a href="{% url 'organization:organization_home' org.id %}">,
django的模板文件中不允许出现两个一样的block
修改导航栏,修改显示列表(内容),修改面包序
妥善设置好各个地址url、及对应的视图函数和模板链接跳转
#url
url(r'^organization_list/$', OrganiztionListView.as_view(), name='organiztion_list'),
url(r'^user_ask/$', UserAskView.as_view(), name='user_ask'),
url(r'^organization_home/(?P<org_id>\d+)/$', OrganiztionDetailView.as_view(), name='organization_home'),
url(r'^organization_course/(?P<org_id>\d+)/$', OrganiztionCourseView.as_view(), name='organization_course'),
url(r'^organization_teacher/(?P<org_id>\d+)/$', OrganiztionTeacherlView.as_view(), name='organization_teacher'),
url(r'^organization_describe/(?P<org_id>\d+)/$', OrganiztionDescribeView.as_view(), name='organization_describe'),
#视图函数
class OrganiztionDetailView(View): """ 机构首页 """ def get(self,request,org_id): organization = CourseOrganization.objects.get(id=int(org_id)) #teacher = Teacher.objects.filter(BelongOrganization_id=int(org_id)) teacher = organization.teacher_set.all()[:1] #根据model的名字和外键的关联,反向取值 #course = Course.objects.filter(Organization_id=int(org_id)) course = organization.course_set.all()[:3] #根据model的名字和外键的关联,反向取值 return render(request, 'organization_home.html', {'organization':organization, 'teacher':teacher, 'course':course})
class OrganiztionCourseView(View):
"""
机构课程
"""
def get(self,request,org_id):
organization = CourseOrganization.objects.get(id=int(org_id))
#course = Course.objects.filter(Organization_id=int(org_id))
course = organization.course_set.all() #根据model的名字和外键的关联,反向取值
return render(request, 'organization_course.html', {'organization':organization, 'course':course})
class OrganiztionDescribeView(View):
"""
机构描述
"""
def get(self,request,org_id):
organization = CourseOrganization.objects.get(id=int(org_id))
return render(request, 'organization_describe.html', {'organization':organization,})
class OrganiztionTeacherlView(View):
"""
机构讲师
"""
def get(self,request,org_id):
organization = CourseOrganization.objects.get(id=int(org_id))
#teacher = Teacher.objects.filter(BelongOrganization_id=int(org_id))
teacher = organization.teacher_set.all() #根据model的名字和外键的关联,反向取值
return render(request, 'organization_teacher.html', {'organization':organization, 'teacher':teacher,})
#模板跳转
<li class="active2"><a href="{% url 'organization:organization_home' organization.id %}">机构首页</a></li>
<li class=""><a href="{% url 'organization:organization_course' organization.id %}">机构课程</a></li>
<li class=""><a href="{% url 'organization:organization_describe' organization.id %}">机构介绍</a></li>
<li class=""><a href="{% url 'organization:organization_teacher' organization.id %}">机构讲师</a></li>
1.判断用户登陆后才可以进行收藏
2.空串取字符串是会抛异常的
收藏功能
完成HttpResponse收藏功能视图逻辑,从前端Ajax上传post信息,后端收集fav_id 和fav_type,并进行处理
class AddFavView(View): """ 添加收藏 """ def post(self,request): fav_id = request.POST.get('fav_id','') #获取收藏的id,根据收藏类型进行判断,可能是课程,可能是机构,可能是老师 fav_type = request.POST.get('fav_type','')
AddFavView添加是否登陆判断,登陆后才能进行收藏功能,未登陆则利用前端Ajax跳转至登陆页面
#进行收藏前,先判断用户是否登陆 if not request.user.is_authenticated(): return HttpResponse(json.dumps({'status':'fail','msg':'用户未登录'}),content_type='application/json') #返回form的errors信息,跳转在Ajax中完成
实现用户收藏和取消收藏功能,利用user,fav_id,fav_type进行过滤,查询用户是否存在该项收藏记录,获取用户UserFavorite信息,注意变量类型要与model一致,并且外键一点要传进来才可以进行数据存储
#实现用户收藏和取消收藏功能,利用user,fav_id,fav_type进行过滤,获取用户UserFavorite信息,注意变量类型要与model一致 exit_records = UserFavorite.objects.filter(User=request.user.id,FavoriteID=int(fav_id),FavoriteType=int(fav_type)) if exit_records: #记录已经存在,则表面用户像取消收藏 exit_records.delete() return HttpResponse(json.dumps({'status': 'fail', 'msg': '收藏'}),content_type='application/json') # 返回form的errors信息,跳转在Ajax中完成 else: #若查询不到该条收藏记录,则表面用户想进行收藏,进行数据存储逻辑 user_fav = UserFavorite() #0代表默认信息,避免空串出错 if int(fav_id)>0 and int(fav_type)>0: user_fav.FavoriteID = int(fav_id) user_fav.FavoriteType = int(fav_type) user_fav.User = request.user #切记外键一定要传进来 user_fav.save() return HttpResponse(json.dumps({'status': 'success', 'msg': '已收藏'}),content_type='application/json') # 返回form的errors信息,跳转在Ajax中完成 else: return HttpResponse(json.dumps({'status': 'fail', 'msg': '收藏出错'}),content_type='application/json') # 返回form的errors信息,跳转在Ajax中完成
收藏状态保持,在相应的view函数中增加has_fav参数,用于判断登录情况,默认为False,当判断用户登录成功后,利用user.id,FavoriteID和FavoriteType判断数据库是否存在收藏信息,然后返回has_fav信息。
def get(self,request,org_id): organization = CourseOrganization.objects.get(id=int(org_id)) #teacher = Teacher.objects.filter(BelongOrganization_id=int(org_id)) teacher = organization.teacher_set.all()[:1] #根据model的名字和外键的关联,反向取值 #course = Course.objects.filter(Organization_id=int(org_id)) course = organization.course_set.all()[:3] #根据model的名字和外键的关联,反向取值 ###########是否已收藏############# has_fav = False #默认未收藏 #先判断登录 if request.user.is_authenticated(): if UserFavorite.objects.filter(User=request.user.id,FavoriteID=organization.id,FavoriteType=2): has_fav = True ################################# return render(request, 'organization_home.html', {'organization':organization, 'teacher':teacher, 'course':course,'has_fav':has_fav})
在模板文件中,增加if、else的判断(静态信息),JS调用后还会对数据库信息进行查询判断
{% if has_fav %}已收藏{% else %}收藏{% endif %}
其他页面同样方法加入收藏信息
粘贴login.html代码,实现登陆的header
{# 登陆header #} <section class="headerwrap "> <header> <div class=" header"> {% if request.user.is_authenticated %} <div class="top"> <div class="wp"> <div class="fl"> <p>服务电话:<b>33333333</b></p> </div> <!--登录后跳转--> <div class="personal"> <dl class="user fr"> <dd>{{ user.username }}<img class="down fr" src="{% static 'images/top_down.png' %}"/></dd> <dt><img width="20" height="20" src="{{ MEDIA_URL }}{{ user.img }}"/></dt> </dl> <div class="userdetail"> <dl> <dt><img width="80" height="80" src="{{ MEDIA_URL }}{{ user.img }}"/></dt> <dd> <h2>{{ user.gender }}</h2> <p>{{ user.username }}</p> </dd> </dl> <div class="btn"> <a class="personcenter fl" href="usercenter-info.html">进入个人中心</a> <a class="fr" href="{% url 'user_loginout' %}">退出</a> </div> </div> </div> </div> </div> {% else %} <div class="top"> <div class="wp"> <div class="fl"> <p>服务电话:<b>33333333</b></p></div> <a style="color:white" class="fr registerbtn" href="{% url 'Register' %}">注册</a> <a style="color:white" class="fr loginbtn" href="{% url 'user_login' %}">登录</a> </div> </div> {% endif %} {# 判断是否已登陆成功 #}
登录后回到请求登录的页面
在setting.py中加入django.core.context_processors.request,方可在模板中获取到request.path
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', 'django.core.context_processors.media', "django.core.context_processors.request", #用于登陆重定向至登陆前页面 ], }, }, ]
在html文件中,设定好登录的href,将自身的url传递进去
<a style="color:white" class="fr loginbtn" href="{% url 'user_login' %}?next={{ request.path }}">登录</a>
修改loginview,在get函数中获取next_page 参数,并传递给模板中进行渲染,利用hidden参数,在渲染出来的html中不展示
def get(self,request): ##################加入重定向至来时页面函数################# # 已经在来时页面埋点,将来时页面埋点在参数next中 next_page = request.GET.get('next', '') ########################################################### return render(request,'login.html',{'next_page':next_page}) #将next_page返回给html页面,进行埋点传值给POST
传值到html文件中,但渲染出来不展示
<input type="hidden" name="next_page" value="{{ next_page }}">{# 用于给POST函数获取来也页面字段 #}
利用request.POST.get获取到next_page参数,并利用HttpResponseRedirect进行重定向至来时页面
def post(self,request): login_form = LoginForm(request.POST) #返回报错值,有报错则valid为False,没报错则为True,减少服务器查询压力。 if login_form.is_valid(): user_name = request.POST.get('username', '') pass_word = request.POST.get('password', '') # 使用authenticate对用户正确性进行简单判断,判断正确返回user 的对象,如果错误返回None user = authenticate(username=user_name, password=pass_word) if user is not None: #增加判断用户是否激活(可能只注册但未激活) if user.is_active: # 调用login函数,实现对request进行操作,将用户信息、session、cookies等写入了request中,再用render将request进行返回 login(request, user) #################传用户信息进登陆页面################# LoginMsg = UserProfile.objects.get(username=user_name) #################获取html中的隐藏字段next_page################# next_page = request.POST.get('next_page','') return HttpResponseRedirect(next_page) # 转到来时页面 #return render(request, 'index.html', {'LoginMsg':LoginMsg}) #登陆成功,由后台渲染跳转至index,并在index中判断,头部显示 else: return render(request, 'login.html', {'msg':'用户未完成激活'}) else: # 通过了form表单的验证,但是账号密码不正确时 return render(request, 'login.html', {"msg": "账号密码有问题"}) else: # form表单验证不通过,返回表单错误信息 return render(request, 'login.html', {"login_form": login_form}) #直接传入login_form,在Template里面调用error值
退出登陆后重定向至退出前的页面
模板中埋点来时页面-“next-page”,点击“退出”按钮在跳转至user_loginout路径的同时会在url中附带来时路径,user_loginout触发logout_view视图函数,在视图函数下用GET方法获取来时路径,并在退出登陆后用HttpResponseRedirect重定向来时页面模板中插入来时路径next-page
<a class="fr" href="{% url 'user_loginout' %}?next={{ request.path }}">退出</a>
路径配置文件下配置好退出登录的视图函数
url(r'^loginout/$', logout_view, name='user_loginout'),
利用request.method获取GET参数(即来时路径),并重定向HttpResponseRedirect至来时页面
def logout_view(request): if request.method == 'GET': next_page = request.GET.get('next', '/') logout(request) return HttpResponseRedirect(next_page) # 转到来时页面
相关文章推荐
- Django网站建设-模板复用、数据展示、分页、表单异步提交
- HttpServletResponse sendRedirect 重定向为其他网站页面
- 重定向(response.sendRedirect)乱码 和 HTTP response code: 400 for URL问题
- Django网站建设-GMOOC-数据库设计/model设计
- Django网站建设-头像修改,邮箱及密码修改(form,js文件,模板配置)
- 解决:无法在发送 HTTP 标头之后进行重定向。 跟踪信息: 在 System.Web.HttpResponse.Redirect(String url, Boolean endResponse, Boolean permanent) 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.<>……
- from django.http import HttpResponseRedirect
- [py]django url 参数/reverse和HttpResponseRedirect
- django学习——通过HttpResponseRedirect 和 reverse实现重定向
- django的HttpResponseRedirect重定向 mysql保存文本的换行问题
- 海洋工作室——网站建设专家:【原】在线订餐系统,可商业化!订单系统共享啦!!应用技术: AJAX, LINQ, MASTERPAGE, ASP.NET
- [转]Run a Http Response Filter together with an Ajax Update Panel
- c# HttpWebRequest 和HttpWebResponse 登录网站或论坛(校内网登陆)
- getResponseCode获取URL响应状态码 HTTP状态返回码
- response.setHeader("Refresh", "2;url=http://www.baidu.com");
- 减少HTTP请求之将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片(大型网站优化技术)
- 天津网站建设-文率科技拒绝套用模板的垃圾网站
- HttpServletResponse的转发和重定向
- Django学习之为网站添加图标以及模板链接图片
- HTTP header location 重定向 URL