1 # model.py
2 from django.db import models
3
4 '''
5 # 二、表断关联
6 # 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
7 # 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
8 # 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制
9 # 4、断关联
10 # 5、级联关系
11 # 作者没了,详情也没:on_delete=models.CASCADE
12 # 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
13 # 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
14 # 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
15 '''
16
17
18 class BaseModel(models.Model):
19 creat_time = models.DateTimeField(auto_now_add=True)
20 last_time = models.DateTimeField(auto_now=True)
21 is_delete = models.BooleanField(default=False)
22
23 class Meta:
24 # 单个字段,有索引,有唯一
25 # 多个字段,有联合索引,联合唯一
26 abstract = True # 抽象表,不再数据库建立出表
27
28
29 # 书表--出版社(一对多)
30 class Book(BaseModel):
31 name = models.CharField(max_length=64)
32 price = models.DecimalField(max_digits=5, decimal_places=2)
33 publish = models.ForeignKey(to='Publish', on_delete=models.DO_NOTHING, db_constraint=False)
34 # 一对多的关系一旦确立,关联字段写在多的一方
35 # to_field 默认不写,关联到Publish主键
36 # db_constraint=False 逻辑上的关联,实质上没有外键练习,增删不会受外键影响,但是orm查询不影响
37 # 什么时候用自动,什么时候用手动?第三张表只有关联字段,用自动 第三张表有扩展字段,需要手动写
38 # 不能写on_delete(就没有这个属性)
39 author = models.ManyToManyField(to='Author', db_constraint=False)
40
41 # admin 显示中文表名
42 class Meta:
43 verbose_name_plural = '书名'
44
45 # # admin 显示中文字段
46 def __str__(self):
47 return self.name
48
49 # 序列化的时候 显示完整数据
50 @property
51 def publish_name(self):
52 return self.publish.name
53
54 @property
55 def author_list(self):
56 author_list = self.author.all()
57 # li = []
58 # for author in author_list:
59 # li.append({'name': author.name, 'sex': author.get_sex_display()})
60 # return li
61 return [{'name': author.name, 'sex': author.get_sex_display()} for author in author_list]
62
63
64 # 出版社
65 class Publish(BaseModel):
66 name = models.CharField(max_length=64)
67 add = models.CharField(max_length=64)
68
69 class Meta:
70 verbose_name_plural = '出版社'
71
72 def __str__(self):
73 return self.name
74
75
76 # 作者
77 class Author(BaseModel):
78 name = models.CharField(max_length=64)
79 sex = models.IntegerField(choices=((1, '男'), (2, '女')))
80 author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE, db_constraint=False)
81
82 class Meta:
83 verbose_name_plural = '作者'
84
85 def __str__(self):
86 return self.name
87
88
89 # 作者详情
90 class AuthorDetail(BaseModel):
91 telephone = models.CharField(max_length=11)
92
93 class Meta:
94 verbose_name_plural = '作者详情'
95
96 # view.py
97 from django.shortcuts import render
98 from rest_framework.views import APIView
99 from rest_framework.response import Response
100 from rest_framework.generics import GenericAPIView
101 from rest_framework.viewsets import GenericViewSet
102 from rest_framework.mixins import ListModelMixin
103 from . import models, serializer
104
105
106 class BookGenericAPIView(APIView):
107 # 获取所有 单个(配路由)
108 def get(self, request, *args, **kwargs):
109 if kwargs.get('pk'):
110 book = models.Book.objects.filter(is_delete=False, pk=kwargs.get('pk')).first()
111 book_serializer = serializer.BookModelSerializer(book)
112 return Response(data=book_serializer.data)
113 book = models.Book.objects.all().filter(is_delete=False)
114 book_serializer = serializer.BookModelSerializer(book, many=True)
115 return Response(data=book_serializer.data)
116
117 # 单增 # 群增
118 def post(self, request, *args, **kwargs):
119 # 如果request.data--dic
120 if isinstance(request.data, dict):
121 book_serializer = serializer.BookModelSerializer(data=request.data)
122 if book_serializer.is_valid():
123 book_serializer.save()
124 return Response(data=book_serializer.data)
125 else:
126 return Response(data=book_serializer.errors)
127
128 elif isinstance(request.data, list):
129 book_serializer = serializer.BookModelSerializer(data=request.data, many=True)
130 if book_serializer.is_valid(raise_exception=True):
131 book_serializer.save() # 作者重写了create,直接用
132 return Response(data=book_serializer.data)
133 else:
134 return Response(data=book_serializer.errors)
135
136 # 单改(配pk路由) 群改(pk从post传过来,手动处理)
137 def put(self, request, *args, **kwargs):
138 if kwargs.get('pk', None):
139 book = models.Book.objects.filter(pk=kwargs.get('pk')).first()
140 # partial=True -- 部分修改 不需要全部传 传需要修改的 requied --Ture
141 book_serializer = serializer.BookModelSerializer(instance=book, data=request.data, partial=True)
142 if book_serializer.is_valid():
143 book_serializer.save()
144 return Response(book_serializer.data)
145 else:
146 return Response(book_serializer.errors)
147 else:
148 # 第一种方案,for循环一个一个修改
149 # book_list = []
150 # data_list = []
151 # for item in request.data:
152 # pk = item.pop('id')
153 # book = models.Book.objects.filter(pk=pk).first()
154 # # 想要修改的对象
155 # book_list.append(book)
156 # # 修改的数据
157 # data_list.append(item)
158 # for i,si_data in enumerate(modify_data):
159 # book_ser = BookModelSerializer(instance=book_list[i], data=si_data)
160 # book_ser.is_valid(raise_exception=True)
161 # book_ser.save()
162 # return Response(data='成功')
163
164 # 传过来的数据 [{id:1,name:xxx},{id:2,name:xxx}]
165 # 处理过后的数据 [{name:xxx},{name:xxx}]
166 book_list = []
167 data_list = []
168 for item in request.data:
169 pk = item.pop('id')
170 book = models.Book.objects.filter(pk=pk).first()
171 # 想要修改的对象
172 book_list.append(book)
173 # 修改的数据
174 data_list.append(item)
175 book_serializer = serializer.BookModelSerializer(instance=book_list, data=data_list, many=True)
176 if book_serializer.is_valid(raise_exception=True):
177 book_serializer.save() # ListSerializer的update方法,自己写的update方法
178 return Response(book_serializer.data)
179 else:
180 return Response(book_serializer.errors)
181
182 # 单删 群删
183 def delete(self, request, *args, **kwargs):
184 # 不管单条删除还是多条删除,都用多条删除
185 # 多条删除
186 # {'pks':[1,2,3]}
187 # 单条 1
188 pk = kwargs.get('pk')
189 pks = []
190 if pk:
191 pks.append(pk)
192 else:
193 pks = request.data.get('pk')
194 # ret -- int (更新的数据量 ) 1---2
195 ret = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=True)
196 print(ret)
197 if ret:
198 return Response(f'删除{ret}条成功')
199 else:
200 return Response('删除失败')
201
202
203 # 内置三种分页方式
204 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
205
206
207 class BookGenericViewSet(GenericViewSet, ListModelMixin):
208 queryset = models.Book.objects.all().filter(is_delete=False)
209 serializer_class = serializer.BookModelSerializer
210 pagination_class = PageNumberPagination
211
212 # urls.py
213 from django.urls import path, re_path
214 from app01 import views
215 from rest_framework.routers import SimpleRouter
216
217 router = SimpleRouter()
218 router.register('get_all', views.BookGenericViewSet, 'get_all')
219 urlpatterns = [
220 path('book/', views.BookGenericAPIView.as_view()),
221 re_path(r'^book/(?P<pk>\d+)/$', views.BookGenericAPIView.as_view()),
222
223 ]
224 urlpatterns += router.urls
1 # serializer.py
2
3 from rest_framework import serializers
4 from . import models
5
6
7 class BookListSerializer(serializers.ListSerializer):
8 def update(self, instance, validated_data):
9 # instance--book_list validated_data--清洗后(校验后)的数据
10 # enumerate(0,xxx)
11 # self.child --- BookModelSerializer
12
13 # instance[i]---- [{name: 臭屁李}, {name: 17}]
14 # attrs---- [{name: 李大头}, {name: 18}]
15
16 # li = []
17 # for i, attrs in enumerate(validated_data):
18 # ret = self.child.update(instance[i], attrs)
19 # li.append(ret)
20 # return li
21
22 return [
23 self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
24 ]
25
26
27 class BookModelSerializer(serializers.ModelSerializer):
28 # 第一种(反序列化的时候有问题---反序列化的时候传id or 名字)
29 # 解决办法--重写一个publish_name(read_only)只序列化,publish反序列化(write_only)
30 # publish = serializers.CharField(source='publish.name')
31 # publish_name = serializers.CharField(source='publish.name')
32 # author_list-- Null 只能用model 里面写方法
33 # author_list = serializers.CharField(source='author.name')
34
35 # 第二种 models --写函数或方法
36 class Meta:
37 list_serializer_class = BookListSerializer
38 model = models.Book
39 fields = ['id', 'name', 'price', 'publish', 'publish_name', 'author', 'author_list']
40 # 进行连表展示 depth=1
41 # depth = 0
42 extra_kwargs = {
43 'publish': {'write_only': True},
44 'publish_name': {'read_only': True},
45
46 'author': {'write_only': True},
47 'author_list': {'read_only': True},
48 'id': {'read_only': True}
49 }