1. admin 中,展示带有 choices 属性的字段时 Django 会自动帮我们调用 get status display 方法 所以不用配置

models.py

  1. STATUS_ITEMS = [
  2. (0, '申请'),
  3. (1, '通过'),
  4. (2, '拒绝'),
  5. ]
  6. status = models.IntegerField(choices=STATUS_ITEMS, default=0, verbose_name='审核状态')

views.py

  1. def index(request):
  2. students = Student.objects.all()
  3. return render(request,'student/index.html',context={'students':students})

index.html

  1. <ul>
  2. {% for student in students %}
  3. <li>{{ student.name }} - {{ student.get_status_display }}</li>
  4. {% endfor %}
  5. </ul>

一 定义表单

在应用student目录下新建forms.py文件,编写代码

  1. from django import forms
  2. from .models import Student
  3. class StudentForm(forms.ModelForm):
  4. # clean_qq就是Form自动调用来处理每个字段的方法方法
  5. # 检验qq是否输入合法
  6. def clean_qq(self):
  7. cleaned_data = self.cleaned_data['qq']
  8. if not cleaned_data.isdigit():
  9. raise forms.ValidationError('必须是数字!')
  10. return int(cleaned_data)
  11. class Meta:
  12. model = Student
  13. fields = (
  14. 'name', 'sex', 'profession', 'email', 'qq', 'phone'
  15. )

其中clean_XX方法可以对数据进行检验

views.py

  1. from .forms import StudentForm
  2. from django.http import HttpResponseRedirect
  3. def index(request):
  4. students = Student.objects.all()
  5. if request.method == 'POST':
  6. form = StudentForm(request.POST)
  7. if form.is_valid():
  8. form.save()
  9. # reverse方法,在student/urls.py中定义index时候,声明了name = 'index'
  10. # 可以通过reverse拿到对应的url
  11. return HttpResponseRedirect(reverse('index'))
  12. else:
  13. form = StudentForm
  14. context = {
  15. 'students':students,
  16. 'form':form
  17. }
  18. return render(request,'student/index.html',context=context)

index.html

  1. <form action="/" method="post">
  2. {# csrf_token django对提交的数据安全性做校验 #}
  3. {% csrf_token %}
  4. {{ form }}
  5. <input type="submit" value="Submit"/>
  6. </form>

image.png

二 优化数据获取逻辑

在models.py中我们定义模型类,要想获取数据库所有数据在views.py使用:

  1. students = Student.objects.all()

在 view 函数中通过 students = Student . objects.all ()的方式 取到了所有学员 的数据,但是这种方式在实际使用中会有 因为后期可能会对学员的数据 进行过滤,比如需要调整为展示所有审核通过的学员, 此时就需要调整 view 函数中的代码 者对结果进行缓存,也需要调整代码

因此,可以把数据获取逻辑封装到model层中,同时修改views.py
未修改
models.py:

  1. class Student(models.Model):
  2. # 其他代码

views.py

  1. def index(request):
  2. students = Student.objects.all()
  3. # 其它代码

修改后:
models.py

  1. class Student(models.Model):
  2. # 其它代码
  3. @classmethod
  4. def get_all(cls):
  5. return cls.objects.all()

增加get_all方法

views.py

  1. def index(request):
  2. students = Student.get_all()

三 TestCase

测试数据库

在Django 中运行测试用例时,如 我们用的是 SQLite 据库, ango 会帮我们创建一个 基于内存的测试数据库,用于测试

但是对于MySQL数据库,django会直接用配置数据库用户名和密码创建一个名为 test_student_db 的数据库,用户测试,因此,需要保证有建表和建库的权限,你也可以定义测试数据库的名称,在settings.py中配置:

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME': 'graduation', #数据库名称
  5. 'USER': 'root',
  6. 'PASSWORD': '123456',
  7. 'HOST': 'localhost',
  8. 'PORT': '3306',
  9. 'TEST': {
  10. 'NAME': 'mytestdatabase', # 这里配置
  11. },
  12. }
  13. }


Django提供一个名为TestCase的基类,有以下方法:

  • def setUp(self) - 如其名,用来初始化环境,包括创建初始化的数据,或者做一些其他的准备的工作。
  • def testxxxx(self) - 方法后面的xxxx可以是任意的东西,以test开头的方法,会被认为是需要测试的方法,跑测试时会被执行。每个需要被测试的方法是相互独立的。
  • def tearDown(self) - 跟setUp相对,用来清理测试环境和测试数据。在Django中,我们可以不关心这个。

Model 层测试

这一层的测试,主要是来保证数据的写入和查询是可用的,同时也需要保证我们在Model层所提供的方法是符合预期的。
student/tests.py

  1. from django.test import TestCase, Client
  2. from .models import Student
  3. class StudentTestCase(TestCase):
  4. def setUp(self):
  5. Student.objects.create(
  6. name='test',
  7. sex=1,
  8. email='test@qq.com',
  9. qq='333333',
  10. phone='1111'
  11. )

在setup方法中创建一条测试数据,用于测试数据库创建数据

View 层测试

这一层更多的是功能上的测试,也是我们一定要写的,功能上的可用是比什么都重要的事情。当然这事你可以通过手动浏览器访问来测试,但是如果你有几百个页面呢?
这部分的测试逻辑依赖Django提供的Django.test.Client对象。在上面的文件中tests.py中,我们增加下面两个函数:

  1. def test_post_student(self):
  2. client = Client()
  3. data = dict(
  4. name = 'test_post',
  5. sex=1,
  6. email='test@163.com',
  7. profession='程序员',
  8. qq='333',
  9. phone='3222',
  10. )
  11. response = client.post('/',data)
  12. self.assertEqual(response.status_code,302,'status code must 302')

四 QuerySet

QuerySet本质上是一个懒加载对象,都不会产生数据库查询操作,只是会返回一个 Query Set 对象,等你真正用它时才会执行查询
image.png

常用的queryset接口

image.png
image.png
image.png

image.png

进阶接口

image.png
image.png
image.png

常用字段查询

image.png

进阶查询

image.png
image.png
image.png
以上资料可以查询:

  • queryset api
  • Django 数据库访问优化
  • 查询条件语句
  • 聚合查询

五 admin页面查看操作日志

在应用文件夹下的admin.py

  1. from django.contrib import admin
  2. from django.contrib.admin.models import LogEntry
  3. @admin.register(LogEntry)
  4. class LogEntryAdmin(admin.ModelAdmin):
  5. list_display = ['object_repr','object_id','action_flag','user','change_message']