drf序列化群增、群改、群刪
阿新 • • 發佈:2021-06-26
class MyUser(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
phone = models.CharField(max_length=32)
email = models.EmailField()
路由
path('login2/', views.MyLoginView.as_view()),
檢視
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER from rest_framework_jwt.views import obtain_jwt_token class MyLoginView(APIView): def post(self, request, *args, **kwargs): username = request.data.get('username') password = request.data.get('password') # 如果是手機號 if re.match('^1[3-9]\d{9}$', username): # 以手機號登入 user = MyUser.objects.filter(phone=username).first() elif re.match('^.+@.+$', username): # 以郵箱登入 user = MyUser.objects.filter(email=username).first() else: # 以使用者名稱登入 user = MyUser.objects.filter(username=username).first() # 如果user有值並且密碼正確 if user and user.password == password: # 登入成功,生成token # drf-jwt中有通過user物件生成token的方法 payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return APIResponse(token=token, username=user.username) else: return APIResponse(code=101, msg='使用者名稱或密碼錯誤')
# 注意:以後所有的資料刪除,儘量用軟刪除,使用一個欄位標誌是否刪除,而不是真正的從資料庫中刪除 -好處:1 這樣刪除資料不會影響索引,不會導致索引失效 2 之前存的使用者資料還在,以備以後使用 # 表模型如下 # 抽象出一個基表(不再資料庫生成,abstract=True),只用來繼承 class BaseModel(models.Model): is_delete = models.BooleanField(default=False) create_time = models.DateTimeField(auto_now_add=True) class Meta: # 基表必須設定abstract,基表就是給普通Model類繼承使用的,設定了abstract就不會完成資料庫遷移完成建表 abstract = True class Book(BaseModel): name = models.CharField(max_length=16) price = models.DecimalField(max_digits=5, decimal_places=2) publish = models.ForeignKey(to='Publish', db_constraint=False, on_delete=models.DO_NOTHING) # 重點:多對多外來鍵實際在關係表中,ORM預設關係表中兩個外來鍵都是級聯 # ManyToManyField欄位不提供設定on_delete,如果想設定關係表級聯,只能手動定義關係表 authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False) @property def publish_name(self): return self.publish.name @property def author_list(self): # ll=[] # for author in self.authors.all(): # ll.append({'name':author.name,'sex':author.get_sex_display()}) return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()] class Publish(BaseModel): name = models.CharField(max_length=16) address = models.CharField(max_length=64) class Author(BaseModel): name = models.CharField(max_length=16) sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0) class AuthorDetail(BaseModel): mobile = models.CharField(max_length=11) # 有作者可以沒有詳情,刪除作者,詳情一定會被級聯刪除 # 外來鍵欄位為正向查詢欄位,related_name是反向查詢欄位 author = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE)
class BookView(APIView): def post(self, request, *args, **kwargs): if isinstance(request.data, dict): # 增一條 ser = serializer.BookSerializer(data=request.data) ser.is_valid(raise_exception=True) ser.save() return APIResponse(data=ser.data) elif isinstance(request.data, list): # 增多條 ser = serializer.BookSerializer(data=request.data, many=True) # 內部如何實現的? # many=True,ser不是BookSerializer物件,而是ListSerializer物件,套了一個個的BookSerializer print(type(ser)) ser.is_valid(raise_exception=True) # from rest_framework.serializers import ListSerializer ser.save() # ListSerializer的save return APIResponse(msg='增加%s條成功' % len(request.data))
class BookView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk', None)
if pk:
# 單查
# 方式一
# book=models.Book.objects.filter(id=pk).filter(is_delete=False).first()
# if not book:
# raise Exception('要查詢的不存在')
# 方式二
book = models.Book.objects.get(id=pk, is_delete=False)
ser = serializer.BookSerializer(instance=book)
else:
# 查所有
book_list = models.Book.objects.all().filter(is_delete=False)
ser = serializer.BookSerializer(instance=book_list, many=True)
return APIResponse(data=ser.data)
class BookView(APIView):
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk', None)
if pk:
# 單條修改
book = models.Book.objects.get(id=pk, is_delete=False)
ser = serializer.BookSerializer(instance=book, data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
return APIResponse(msg='修改成功')
else:
# 分析:ListSerializer的update方法沒有寫,需要我們自己寫
from rest_framework.serializers import ListSerializer
# pks=[item['id'] for item in request.data]
# 如果不重寫ListSerializer的update方法,這是存不進去的
pks = []
for item in request.data:
pks.append(item['id'])
item.pop('id')
print(request.data)
book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
ser = serializer.BookSerializer(instance=book_list, data=request.data, many=True)
print(type(ser))
ser.is_valid(raise_exception=True)
ser.save()
return APIResponse(msg='修改%s條成功')
# 你們能想到的方法
# pks = []
# for item in request.data:
# pks.append(item['id'])
# item.pop('id')
# book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
#
# for i,book in enumerate(book_list):
# ser = serializer.BookSerializer(instance=book, data=request.data[i])
# ser.is_valid(raise_exception=True)
# ser.save()
# return APIResponse(msg='修改%s條成功'%len(book_list))
class BookView(APIView):
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk', None)
pks = []
if pk:
# 單條刪除
# res=models.Book.objects.filter(id=pk).update(is_delete=True)
# print(res)
# return APIResponse(msg='刪除成功')
pks.append(pk)
else:
pks = request.data
res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
if res >= 1:
return APIResponse(msg='刪除%s條成功' % res)
else:
# raise Exception('沒有要刪除的資料')
return APIResponse(code=999, msg='沒有要刪除的資料')
from app01 import models
class ListBookSerializer(serializers.ListSerializer):
# def create(self, validated_data):
# print('=======',validated_data)
# return '1'
def update(self, instance, validated_data):
print(instance) # book_list:是一堆圖書物件
print(validated_data) # 列表套字典,是要修改的資料
return [self.child.update(book, validated_data[i]) for i, book in enumerate(instance)]
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
list_serializer_class=ListBookSerializer # 指定many=True的時候,生成的ListBookSerializer的物件了
fields = ['name', 'price', 'publish', 'authors', 'publish_name', 'author_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True},
'publish_name': {'read_only': True},
'author_list': {'read_only': True},
}
# def create(self, validated_data):
# print(validated_data)
路由
path('books/', views.BookView.as_view()), re_path('books/(?P<pk>\d+)', views.BookView.as_view()),
1 自定義token的簽發和認證:https://www.cnblogs.com/liuqingzheng/articles/9766397.html