表关系

  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         }

 

 

posted @ 2021-05-26 22:56  mofr  阅读(67)  评论(0)    收藏  举报