吴裕雄--天生自然PythonDjangoWeb企业开发:学员管理系统- 前台
- 开发首页
- 做一个简单的用户提交申请的表单页面。
- 首先在student/views.py文件中编写下面的代码:
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django.shortcuts import render
- def index(request):
- words = 'World!'
- return render(request, 'index.html', context={'words': words})
- 上面的代码中,用了django提供的一个快捷的方法render()来渲染页面,使用模板index.html文件。我们需要在student目录下创建templates文件夹,这个文件夹是Django在渲染页面时会默认查找的。
Django查找会去每个App下,也就是我们的settings.py文件中配置的INSTALLED_APPS
中的app下的templates
文件夹中查找你在render
上用到的模板,并且是顺序查找。这意味着,如果你有两个app,比如studentA, studentB,而这两个app中都存在templates/index.html
,那么Django会加载位置在前的那个App的index.html文件。
创建好templates/index.html
之后,编写下面页面代码。
- <!DOCTYPE html>
- <html>
- <head>
- <title>学员管理系统-by the5fire</title>
- </head>
- <body>
- Hello {{ words }}!
- </body>
- </html>
- 接着需要再配置下url,也就是提供一个url映射,可以让用户访问url时把数据发送到我们定义的index 这个view上。
- 直接来修改student_sys目录下的urls.py文件:
- """student_sys URL Configuration
- The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/1.11/topics/http/urls/
- Examples:
- Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
- Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
- Including another URLconf
- 1. Import the include() function: from django.conf.urls import url, include
- 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
- """
- from django.conf.urls import url
- from django.contrib import admin
- from student.views import index
- urlpatterns = [
- url(r'^$', index, name='index'),
- url(r'^admin/', admin.site.urls),
- ]
- 这样改完,我们再次启动项目: python manage.py runserver,访问:http://127.0.0.1:8000
- 接下来的工作就是把数据从表里面取出来,渲染到页面上了。
- 需要修改views.py中的代码:
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django.shortcuts import render
- from .models import Student
- def index(request):
- students = Student.objects.all()
- return render(request, 'index.html', context={'students': students})
- 接着修改index.html中的代码:
- <!DOCTYPE html>
- <html>
- <head>
- <title>学员管理系统</title>
- </head>
- <body>
- <ul>
- {% for student in students %}
- <li>{{ student.name }} - {{ student.get_status_display }}</li>
- {% endfor %}
- </ul>
- </body>
- </html>
- 这样我们就输出了一个简单的列表,展示学员名称和目前状态。这里有一个地方需要注意的是{{ student.get_status_display }},在Model中我们只定义了status字段,并未定义这样的字段,为什么能通过这种方式取到数据呢。并且我们在Admin中,也没有使用这样的字段。
- 原因就是,对于设置了choices的字段,Django会帮我们提供一个方法(注意,是方法),用来获取这个字段对应的要展示的值。回头看下我们status的定义:
- ## 省略上下文代码
- STATUS_ITEMS = [
- (0, '申请'),
- (1, '通过'),
- (2, '拒绝'),
- ]
- tatus = models.IntegerField(choices=STATUS_ITEMS, verbose_name="审核状态")
- ## 省略上下文代码
- 在admin中,展示带有choices属性的字段时,Django会自动帮我们调用get_status_display方法,所以我们不用配置。而在我们自己写的模板中,我们需要自己来写。并且在模板中不支持函数/方法调用,你只需要写方法名称即可,后面的括号不需要写。Django会自行帮你调用(如果是方法的话)。
- 提交数据
- 输出数据之后,我们再来开发提交数据的功能。这部分我们用一下Form。
- 首先我们先创建一个forms.py的文件,跟views.py同级。编写如下代码:
- # coding:utf-8
- from __future__ import unicode_literals
- from django import forms
- from .models import Student
- class StudentForm(forms.Form):
- name = forms.CharField(label='姓名', max_length=128)
- sex = forms.ChoiceField(label='性别', choices=Student.SEX_ITEMS)
- profession = forms.CharField(label='职业', max_length=128)
- email = forms.EmailField(label='邮箱', max_length=128)
- qq = forms.CharField(label='QQ', max_length=128)
- phone = forms.CharField(label='手机', max_length=128)
- 有一个ModelForm可以用。我们来改下
- # coding:utf-8
- from __future__ import unicode_literals
- from django import forms
- from .models import Student
- class StudentForm(forms.ModelForm):
- class Meta:
- model = Student
- fields = ('name', 'sex', 'profession','email', 'qq', 'phone')
- 只需要这么改,不需要重复定义N多个字段。如果有修改对应字段类型的需求,比如把qq改成IntegerField用来做数字校验,也是可以声明出来。也可以通过定义clean方法的方式来做,我们来改下代码,增加QQ号必须为纯数字的校验:
- # coding:utf-8
- from __future__ import unicode_literals
- from django import forms
- from .models import Student
- class StudentForm(forms.ModelForm):
- def clean_qq(self):
- cleaned_data = self.cleaned_data['qq']
- if not cleaned_data.isdigit():
- raise forms.ValidationError('必须是数字!')
- return int(cleaned_data)
- class Meta:
- model = Student
- fields = ('name', 'sex', 'profession','email', 'qq', 'phone', 'status')
- 其中clean_qq就是Django的form会自动调用,来处理每个字段的方法,比如在这个form中你可以通过定义clean_phone来处理电话号码,可以定义clean_email来处理邮箱等等。如果验证失败,可以通过raise forms.ValidationError('必须是数字!')的方式返回错误信息,这个信息会存储在form中,最终会被我们渲染到页面上。
- 有了form,接下来需要做的就是在页面中展示form,让用户能够填写信息提交表单。同时对于提交的数据,我们需要先做校验,通过后可以保存到数据库中。来看下views.py中的文件最终的样子:
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django.http import HttpResponseRedirect
- from django.urls import reverse
- from django.shortcuts import render
- from .models import Student
- from .forms import StudentForm
- def index(request):
- students = Student.objects.all()
- if request.method == 'POST':
- form = StudentForm(request.POST)
- if form.is_valid():
- cleaned_data = form.cleaned_data
- student = Student()
- student.name = cleaned_data['name']
- student.sex = cleaned_data['sex']
- student.email = cleaned_data['email']
- student.profession = cleaned_data['profession']
- student.qq = cleaned_data['qq']
- student.phone = cleaned_data['phone']
- student.status = cleaned_data['status']
- student.save()
- return HttpResponseRedirect(reverse('index'))
- else:
- form = StudentForm()
- context = { 'students': students,'form': form,}
- return render(request, 'index.html', context=context)
- 里面有一个form.cleaned_data,这个对象是Django的form对用户提交的数据根据字段类型做完转换之后的结果。另外还有reverse的使用,我们在urls.py中定义index的时候,声明了name='index',所以我们这里可以通过reverse来拿到对应的url。这么做的好处是,不需要硬编码url到代码中,这意味着如果以后有修改url的需求,只要index的名称不变,这个地方的代码就不用改。
- 写完views.py中的代码之后,我们要把form传到模板中,这样用户才能最终看到一个可以填写数据的表单。要在模板中加form,最终模板(index.html)代码如下:
- <!DOCTYPE html>
- <html>
- <head>
- <title>学员管理系统</title>
- </head>
- <body>
- <h3><a href="/admin/">Admin</a></h3>
- <ul>
- {% for student in students %}
- <li>{{ student.name }} - {{ student.get_status_display }}</li>
- {% endfor %}
- </ul>
- <hr/>
- <form action="/" method="post">
- {% csrf_token %}
- {{ form }}
- <input type="submit" value="Submit" />
- </form>
- </body>
- </html>
- 其中 {% csrf_token %}是Django对提交数据安全性做的校验,这意味着,如果没有这个token,提交过去的数据是无效的。这是用来防止跨站伪造请求攻击的一个手段。
- 只需要这么写,Django就会帮我们自动把所有字段列出来。当然,如果需要调整样式,那就要自己来增加css样式文件解决了.
- 可以再次通过命令: python manage.py runserver,访问: http://localhost:8000测试下页面功能是否可用
吴裕雄--天生自然PythonDjangoWeb企业开发:学员管理系统- 前台的更多相关文章
- 吴裕雄--天生自然PythonDjangoWeb企业开发:学员管理系统后台
需求 提供一个学员管理系统,一个前台页面,展示现有学员,并供新学员提交申请,一个后台,能够处理申请. pip install django==1.11.2 创建项目 使用控制台进入到一个目录下,具体是 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:需求
开发或者做一个项目,是要有一个需求过来的,而不是无缘无故的,启动一个项目,或者推动整个项目进行下一步迭代.这个需求可能是根据用户反馈增加的,可能是老板提出来的,也有可能是产品经理提出来的,但是无论是什 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:Django文档阅读简介
Django是基于MVC模式的框架,虽然也被称为“MTV”的模式,但是大同小异.对我们来说,需要了解的是无论是MVC模式还是MTV模式,甚至是其他的什么模式,都是为了解耦.把一个软件系统划分为一层一层 ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:解决使用相对路径名导入包中子模块问题
问题 将代码组织成包,想用import语句从另一个包名没有硬编码过的包中导入子模块. 解决方案
- 吴裕雄--天生自然PythonDjangoWeb企业开发:解决Pythonno module named "XX"问题
在项目中加入 sys.path.append('你的django项目路径') sys.path.append('python的site-packages路径')
- 吴裕雄--天生自然PythonDjangoWeb企业开发:解决ModuleNotFoundError: No module named 'config'报错
使用创建完模块应用之后python manage.py startapp test_app,您应该进入settings.py并将其注册到
- 吴裕雄--天生自然PythonDjangoWeb企业开发:框架基础和技术选型
简单的Web Server import socket eol1 = b'\n\n' eol2 = b'\n\r\n' body = '''Hello,world!<h1>tszrwyx& ...
- 吴裕雄--天生自然 R语言开发学习:R语言的安装与配置
下载R语言和开发工具RStudio安装包 先安装R
- 吴裕雄--天生自然Django框架开发笔记:Django Admin 管理工具
Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.可以在项目的 settings.py 中的 INSTALLED_APPS 看到它: ...
随机推荐
- 查询数据操作:distinct
1.作用:distinct 去除重复记录.重复记录,指的是字段值,都相同的记录,而不是部分字段值相同的记录 与之相对的是all,表示所有.在MySQL中默认就是all. 2.例子: select ch ...
- 基于jmeter+ant实现的接口自动化测试
jmeter+ANT接口自动化测试框架 项目说明 本框架是一套基于jmeter+Ant+Excel+Python而设计的数据驱动接口自动化测试框架,jmeter 作为执行器,Ant 作为构建工具,进行 ...
- php从接口获取数据转成可以用的数组或其他(含转换编码)
程序开发,时常会用到将接口的json数据转换成程序可以用的,因为今天看到一个比较好的程序,贴上来,以备随时查看: /** * 将对象转成数组,并按要求转换编码 * * @param array $ar ...
- Python socket day2
接收数据 需要一个端口 (端口大于1024 1024一下的端口为特殊端口) (当同一个端口同一时间只能被一个使用) 创建一个套接字 s = socket.socket(AF_INET,SOCK ...
- 【Struts 分派Action】DispatchAction
LoginAction package k.action; import k.form.UserForm; import org.apache.struts.action.ActionForm; im ...
- java编译器不匹配问题(java compiler level does not match the version of the installed java project facet)
问题:项目经常copy过来,经常会报说Java编译器不匹配 解决方法:找到项目所在的目录,在.settings子目录里面,用文本编辑器打开org.eclipse.wst.common.project. ...
- 微服务架构中的Redis
了解如何将Redis与Spring Cloud和Spring Data一起使用以提供配置服务器,消息代理和数据库. Redis可以广泛用于微服务架构中.它可能是少数流行的软件解决方案之一,你的应用程序 ...
- Linux - Shebang(#!)
1. Shebang这个符号通常在Unix系统的脚本中第一行开头中写到,它指明了执行这个脚本文件的解释程序.
- 运行时Runtime的API
const char * class_getName(Class cls); 返回类的名称. Class class_getSuperclass(Class cls); 返回类的超类. Class c ...
- HDU 4699 Editor(模拟 对顶栈)
题目大意: 给定一个整数序列 维护5种操作 次数<1e6 I x: 光标位置插入x 然后光标位于x之后 D: 删除光标前一个数 L: 光标左移 R: 光标右移 Q k: 询问位置k之前的最大前缀 ...