接上篇文章:https://blog.csdn.net/YZL40514131/article/details/125813096?spm=1001.2014.3001.5501
二十一、selected_related与prefetch_related有什么区别?(重要)
在Django中,所有的Queryset都是惰性的,意思是当创建一个查询集的时候,并没有跟数据库发生任何交互。因此我们可以对查询集进行级联的filter等操作,只有在访问Queryset的内容的时候,Django才会真正进行数据库的访问。而多频率、复杂的数据库查询往往是性能问题最大的根源。
不过我们实际开发中,往往需要访问到外键对象的其他属性。如果按照默认的查询方式去遍历取值,那么会造成多次的数据库查询,效率可想而知。
在查询对象集合的时候,把指定的外键对象也一并完整查询加载,避免后续的重复查询。
1,select_related
适用于外键和多对一的关系查询;
2,prefetch_related
适用于一对多或者多对多的查询。
二十二、什么是Cookie、如何获取、设置Cookie
会话跟踪技术,保留用户
Cookie是由服务器创建,然后通过响应发送给客户端?的一个键值对。
具体一个浏览器针对一个服务器存储的key-value({ })
设置Cookie
response.set_cookie("is_login",True)
获取
request.COOKIES.get("is_login")
二十三、什么是session,与cookie的对比、设置、获取、清空session
Session是服务器端技术,利用这个技术,服务器在运行时可以 为每一个用户的浏览器创建一个其独享的session对象,由于 session为用户浏览器独享,所以用户在访问服务器的web资源时 ,可以把各自的数据放在各自的session中,当用户再去访问该服务器中的其它web资源时,其它web资源再从用户各自的session中 取出数据为用户服务。
设置session
request.session['username']="kobe"
request.session.set_expiry(7*24*3600) # 设置session过期时间为一周后
获取session
username=request.session.get('age','')
删除session
request.session.flush()
二十四、简述什么是FBV和CBV
FBV(function base views)就是在视图函面使用函数处理请求
CBV(class base views)就是在视图里面使用类处理请求
二十五、命令migrate 和makemigrations的差别
生成迁移文件
python manage.py makemigration 子应用名
执行迁移
python manage.py migrate
二十六、视图函数中,接收的请求对象常用方法和属性有哪些
request.get:查询字符串参数
request.post:form表单参数
request.body:非表单数据
request.FILES:⼀个类似于字典的对象,包含所有的上传⽂件
request.user:请求用户
request.path:请求url
request.method:请求方式
二十七、Django的Model的继承有几种形式,分别是什么
重点:描述抽象模型类
二十八、Django中想验证表单提交是否格式正确需要用到Form中的哪个函数
serializer.is_valid()
二十九、查询集的两大特性?什么是惰性执行(重要)
惰性执行、缓存 。
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数
新建一个查询集对象就可以实现
三十、查询集返回的列表过滤器有哪些
all()
filter()
exclude()
order_by()
三十一、在Django中,服务端给客户端响应信息有几种方式?分别是什么?
HttpResponse,
JsonResponse,
redirect
三十二、QueryDict和dict区别
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
在 python 原始的字典中,当一个键出现多个值的时候会发生冲突,只保留最后一个值。而在 HTML 表单中,通常会发生一个键有多个值的情况,例如 (多选框)就是一个很常见情况。
三十三、如何给一个字段设置一个主键
primary_key
三十四、解释blank和null
blank
设置为True时,字段可以为空。设置为False时,字段是必须填写的。字符型字段CharField和TextField是用空字符串来存储空值的。如果为True,字段允许为空,默认不允许。
null
设置为True时,django用Null来存储空值。日期型、时间型和数字型字段不接受空字符串。所以设置IntegerField,DateTimeField型字段可以为空时,需要将blank,null均设为True。
三十五、如何在django urlpatterns注册路由
router=routers.SimpleRouter()
router.register('project',视图类)urlpatterns=[path('',include(router.urls))]
三十六、Django中如何加载初始化数据
Django在创建对象时在掉用save()方法后,ORM框架会把对象的属性转换为写入到数据库中,实现对数据库的初始化;通过操作对象,查询数据库,将查询集返回给视图函数,通过模板语言展现在前端页面
三十七、创建Django工程、Django app、以及运行的命令
django-admin startproject django_project 创建一个项目
python manage.py runserver 运行项目
python manage.py startapp 子应用名 创建子应用
python manage.py makemigrations 子应用名 创建迁移脚本
python manage.py migrate 生成迁移脚本
python manage,py createsuperuser 创建管理员用户
python manage.py shell 终端调试代码
三十八、简述 django rest framework框架的认证流程。(非常重要)
1 创建子应用
python manage.py startapp users
2 注册子应用
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','corsheaders', # 同源策略'rest_framework','drf_yasg', # 生成接口文档子应用'django_filters', # DRF过滤器子应用'users',
]
3 采用JWT TOKEN认证
a 下载django-restframework-jwt
pip install djangorestframework-jwt
b settings.py文件中指定使用jwt TOKEN认证类
REST_FRAMEWORK = {# 指定搜索引擎类'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter','rest_framework.filters.OrderingFilter', ],# 'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend'],# 'SEARCH_PARAM': 'se',# 指定分页引擎类'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 3,# 指定用于支持coreapi的Schema'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',# 指定使用的认证类# a、在全局指定默认的认证类(认证方式)'DEFAULT_AUTHENTICATION_CLASSES': [# 1、指定jwt token认证'rest_framework_jwt.authentication.JSONWebTokenAuthentication','rest_framework.authentication.SessionAuthentication','rest_framework.authentication.BasicAuthentication',],
}
4 配置路由,可以进行用户名和密码进行认证
全局路由
urlpatterns = [path('admin/', admin.site.urls),re_path('',include('projects.urls')),path('docs/',include_docs_urls(title='接口测试平台API文档',description='这个是接口平台的文档')),re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), # <-- 这里path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), # <-- 这里path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), # <-- 这里path('user/',include('users.urls'))
]
子路由:
urlpatterns=[path('',include(router.urls)),re_path(r'^(?P<username>\w{6,20})/count/$', views.UsernameIsExistedView.as_view()),re_path(r'^(?P<email>[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+)/count/$',views.EmailIsExistedView.as_view()),path('login/', obtain_jwt_token),
]
测试
5 重写生成token的方法:将用户名和用户id一同输出
a、在项目公共文件utils中,新建handle_jwt_response.py文件
def jwt_response_payload_handler(token,user=None,response=None):return {'user_id':user.id,'username':user.username,'token':token}
b、还得在settings.py文件中指定token失效时间和指定访问路径,目的是:让项目运行时找到自己重写的方法;
# JWT配置
JWT_AUTH = {# 指定token失效时间为1天'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),# 使用自己的jwt_response_payload_handler,目的是响应结果中可以返回用户名和id'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.handle_jwt_response.jwt_response_payload_handler',}
测试
三十九、django rest framework如何实现的用户访问频率控制?(非常重要)
1 settings.py文件中全局配置,所有继承APIView的类视图都会生效
REST_FRAMEWORK = {.........'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle','rest_framework.throttling.UserRateThrottle'],'DEFAULT_THROTTLE_RATES': {'anon': '100/day', # 匿名用户'user': '10/day'}
}
2 局部配置(在指定的继承APIVIew的类视图中加入throttle_classes = [CustomAnonRateThrottle],该类视图具备限流功能)
公共文件中新建throttle_class.py文件
utils----->throttle_class.py,定义CustomAnonRateThrottle(随意),但是必须继承UserRateThrottle
UserRateThrottle:表示正对登录用户的
from rest_framework.throttling import UserRateThrottleclass CustomAnonRateThrottle(UserRateThrottle):THROTTLE_RATES = {"user": "5/day"}
from utils.throttle_class import CustomAnonRateThrottleclass ProjectsViewSet(viewsets.ModelViewSet):queryset=Projects.objects.all()serializer_class = ProjectsSerializerpagination_class = PageNumberPaginationpermission_classes = [permissions.IsAuthenticated]throttle_classes = [CustomAnonRateThrottle]def list(self, request, *args, **kwargs):response=super().list(request, *args, **kwargs)for item in response.data['results']:item['interfaces']=Interfaces.objects.filter(project_id__exact=item['id']).count()item['testsuits']=Testsuits.objects.filter(project_id__exact=item['id']).count()item['testcases']=Testcases.objects.filter(interface__project_id__exact=item['id']).count()item['configures']=Configures.objects.filter(interface__project_id__exact=item['id']).count()return response
3 测试:
四十、values()与values_list()有什么区别?
values : 取字典的queryset
values_list : 取元组的queryset