hello world
配置setting.py
#启用DRF模块
INSTALLED_APPS = [
'rest_framework',
]
#连接远程数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'zufang',
'HOST': '121.43.123.91',
'PORT': 3306,
'USER': 'huadao',
'PASSWORD': '123456',
'CHARSET': 'utf8',
'TIME_ZONE': 'Asia/Shanghai',
},
}
接口设计
1、注册app,python manage startapp appname
JsonResponse只能处理字典数据,如果给的是个列表,要把safe属性改为False
CONTENT-TYPE告诉浏览器服务器给的是什么类型的数据
面向对象里面的里氏替换原则:任何时候可以使用子类型对象替换父类型
2、第一个接口
views文件编写:
@api_view(('GET', )) #访问方式
def get_provinces(request: HttpRequest) -> HttpResponse:
queryset = District.objects.filter(parent__isnull=True)\
.only('name')
#select投影
#only 只查某个字段
#defer 不查哪些属性
serializer = DistrictSimpleSerializer(queryset, many=True) #序列化
return Response({
'code': 10000,
'message': '获取省级行政区域成功',
'results': serializer.data
})
项目文件urls.py注册路由:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
]
应用文件url.py注册路由:
urlpatterns = [
path('districts/', get_provinces),
]
序列化serializers.py
class DistrictSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = District
fields = ('distid', 'name')
省都市三级联动-FBV
编写接口-FBV
views.py
@api_view(('GET', ))
def get_cities(request: HttpRequest, distid) -> HttpResponse:
district = District.objects.filter(distid=distid)\
.defer('parent').first() #拿到指定对象的详细信息,除了父级parent属性
serializer = DistrictDetailSerializer(district)
return Response(serializer.data)
serializers.py
#获取省的详细信息,及所属省下的市级详细信息
class DistrictDetailSerializer(serializers.ModelSerializer):
#在序列化器,额外加一个字段,这个字段要通过一个自定义方法来拿到它
cities = serializers.SerializerMethodField()
@staticmethod
def get_cities(district): #这个方法必须叫这个名字
queryset = District.objects.filter(parent=district).only('name')
return DistrictSimpleSerializer(queryset, many=True).data
class Meta:
model = District
exclude = ('parent', )
urls.py
urlpatterns = [
path('districts/', get_provinces),
path('districts/<int:distid>/', get_cities), #获取单个对象id
]
CBV
ListAPIview 获取对象列表
RetrieveAPIView 获取单个对象
RetrieveUpdateAPIView 获取和更新单个对象
CreateAPIView 创建新对象
ListCreateAPIView 创建新对象和查看列表
获取经理人列表-CBV-ListAPIview
APIView --> GenericAPIView --> ListAPIView
views.py
class AgentView(ListAPIView): #ListAPIView返回的是一个列表
queryset = Agent.objects.all().only('name', 'tel', 'servstar')
serializer_class = AgentSimpleSerializer
# 修改ListAPIView的响应,定制响应格式为json
# def get(self, request, *args, **kwargs):
# resp = super().get(self, request, *args, *kwargs)
# return Response({
# 'code': 10000,
# 'message': '获取经理人列表',
# 'results': resp.data
# })
serializers.py
class AgentSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Agent
fields = ('agentid', 'name', 'tel', 'servstar')
urls.py
urlpatterns = [
path('agents/', AgentView.as_view())
]
获取单个经理人-CBV-RetrieveAPIView
views.py
class AgentView(RetrieveAPIView): #返回单个对象
queryset = Agent.objects.all().only('name', 'tel', 'servstar')
serializer_class = AgentSimpleSerializer
urls.py
urlpatterns = [
path('agents/<int:pk>', AgentView.as_view())
]
创建并获取经理人列表、获取单个和修改经理人-CBV
views.py
class AgentView(ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Agent.objects.all().only('name', 'tel', 'servstar')
def get_serializer_class(self):
return AgentCreateSerializer if self.request.method == 'POST' else AgentSimpleSerializer # 创建更新经理人时要设置详细的信息
def get(self, request, *args, **kwargs):
cls = RetrieveUpdateAPIView if 'pk' in kwargs else ListCreateAPIView
return cls.get(self, request, *args, **kwargs)
urls.py
urlpatterns = [
path('agents/', AgentView.as_view())
path('agents/<int:pk>', AgentView.as_view())
]
serializers.py
class AgentSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Agent
fields = ('agentid', 'name', 'tel', 'servstar')
class AgentCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Agent
exclude = ('estates', )
最终章:只可意会忘记言传
views.py
class AgentView(ListCreateAPIView, RetrieveUpdateAPIView):
def get_queryset(self):
queryset = Agent.objects.all()
if 'pk' not in self.kwargs:
queryset = Agent.objects.all().only('name', 'tel', 'servstar')
return queryset
def get_serializer_class(self):
return AgentCreateSerializer if self.request.method == 'POST' \
else AgentSimpleSerializer if 'pk' not in self.kwargs else AgentDetailSerializer
def get(self, request, *args, **kwargs):
cls = RetrieveUpdateAPIView if 'pk' in kwargs else ListCreateAPIView
return cls.get(self, request, *args, **kwargs)
# def get(self, request, *args, **kwargs):
# resp = super().get(self, request, *args, *kwargs)
# return Response({
# 'code': 10000,
# 'message': '获取经理人列表',
# 'results': resp.data
# })
serializers.py
class AgentSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Agent
fields = ('agentid', 'name', 'tel', 'servstar')
class AgentCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Agent
exclude = ('estates',)
class AgentDetailSerializer(serializers.ModelSerializer):
estates = serializers.SerializerMethodField()
def get_estates(self, agent):
queryset = agent.estates.all().only('name')
return EstateSimpleListAPIView(queryset, many=True).data
class Meta:
model = Agent
fields = '__all__'
class EstateSimpleListAPIView(serializers.ModelSerializer):
class Meta:
model = Estate
fields = ('estateid', 'name')
urls.py
urlpatterns = [
path('agents/', AgentView.as_view()),
path('agents/<int:pk>', AgentView.as_view()),
]
接口设计第三种方式-CBV-ModelViewSet
views.py
class HouseTypeViewSet(ModelViewSet):
queryset = HouseType.objects.all()
serializer_class = HouseTypeSerializer
serializers.py
class HouseTypeSerializer(serializers.ModelSerializer):
"""户型序列化器"""
class Meta:
model = HouseType
fields = '__all__'
urls.py
router = SimpleRouter()
router.register('housetype', HouseTypeViewSet)
urlpatterns += router.urls
Django-ORM问题
Django的ORM框架在遇到关联查询时可能产生的1+n查询问题,严重影响性能
对于多对一和一对一:select_related(关联对象)
ed:Emp.objects.filter(dept_no=20).select_related('dept') 拿到关联对象
对于多对多: prefetch_related(关联对象)
Agent.objects.all().prefetch_related('estate') 预抓取关联对象
在Django下如何使用原生sql查询
1.Agent.objects.raw('sql语句')
2.django.db.connections['default'] --> cursor() --> execute('sql语句')
--> fetchall() / fetchone() / fetchmany(n)
~ ORM框架
解决Python程序对象模型和关系型数据库关系模型不匹配问题,实现对象模型和关系模型的双向转换
District.objects.filter(parent__isnull=True).only('name')
only和defer方法可以指定需要查询的属性或者排除不需要查询的属性,对select语句做投影处理
Django的ORM框架在遇到关联查询时可能产生1+N查询问题,严重影响性能
对于多对一和一对一关系:select_related(关联对象)
Emp.objects.filter(dept__no=20).select_related('dept')
对于多对多关系:prefetch_related(关联对象)
Agent.objects.all().prefetch_related('estates')
可以使用Prefetch对象来定制多对多关系的预抓取方案
Prefetch('estates', queryset=Estates.objects.all().only('name').order_by('-hot'))