getattr() hasattr() setattr() 使用Django View视图开发REST 接口

发布于:2024-12-18 ⋅ 阅读:(10) ⋅ 点赞:(0)

使用Django View视图开发REST 接口

model
from django.db import models
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.contrib.auth.models import AbstractUser


def validate_read(value):
    if value <= 0:
        raise ValidationError('阅读量必须是一个正整数。')


def validate_comment(value):
    if value <= 0:
        raise ValidationError('评论量必须是一个正整数。')


class BookInfo(models.Model):
    title = models.CharField(max_length=30, verbose_name='书籍名')
    pub_date = models.DateField(verbose_name='出版日期')
    read = models.PositiveIntegerField(verbose_name='阅读量', validators=[validate_read])
    comment = models.PositiveIntegerField(verbose_name='评论量',
                                          blank=True, null=True, validators=[validate_comment])

    class Meta:
        db_table = 'bookinfo'
urls
urlpatterns = [
    # path('admin/', admin.site.urls),
    path('books/', views.BookListView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view())
]
views
from django.shortcuts import render, HttpResponse

"""
基于 Django View 开发REST接口

GET	    /goods	    获取所有商品
POST	/goods	    增加商品
GET	    /goods/1	获取编号为1的商品
PUT	    /goods/1	修改编号为1的商品
DELETE	/goods/1	删除编号为1的商品

响应数据 JSON
"""

from django.views import View
from django.http import JsonResponse, HttpResponse
import json

from app.models import BookInfo


class BookListView(View):
    # 查询所有
    def get(self, request):
        # 1.查询所有,queryset类型
        books = BookInfo.objects.all()
        # 2.遍历查询集,将模型对象变成字典
        book_list = []
        for book in books:
            book_dict = {
                'title': book.title,
                'pub_date': book.pub_date,
                'read': book.read,
                'comment': book.comment if book.comment else ''
            }
            book_list.append(book_dict)
        # 3。响应给前端
        # 参数safe=False是必要的,因为book_list是一个非字典对象,
        # 而JsonResponse默认只接受字典对象(出于安全考虑)。
        # 将safe设置为False可以允许传递非字典对象,如列表。
        return JsonResponse(book_list, safe=False)

    # 新增
    def post(self, request):
        # 获取前端请求体(JSON)
        book_dict_bytes = request.body
        print('bytes类型:', book_dict_bytes)
        # 把 bytes 类型的 json数据,转换为 json str
        book_dict_str = book_dict_bytes.decode()
        print('str类型', book_dict_str)
        # json.loads():将一个 JSON 格式的字符串转换成 Python 的数据类型
        # (通常是字典或列表,但也可能是字符串、数字、布尔值等)。
        data_dict = json.loads(book_dict_str)
        print('JSON格式的字符串转换成 Python 的数据类型:', data_dict)
        # 新增
        book = BookInfo.objects.create(**data_dict)

        # 准备返回数据:JsonResponse 用于返回字典或列表
        response_data = {
            'title': book.title,
            'pub_date': book.pub_date,
            'read': book.read,
            'comment': book.comment if book.comment else ''
        }

        return JsonResponse(response_data, status=201)


class BookDetailView(View):
    # 查询指定
    def get(self, request, pk):
        try:
            book = BookInfo.objects.get(pk=pk)
            book_dict = {
                'title': book.title,
                'pub_date': book.pub_date,
                'read': book.read,
                'comment': book.comment if book.comment else ''
            }
        except Exception as e:
            return JsonResponse({'message': '没有此图书'}, status=404)

        return JsonResponse(book_dict)

    # 修改指定
    def put(self, request, pk):
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '没有此图书'}, status=404)
        # 获取前端请求体(JSON)
        book_dict_bytes = request.body
        # 把 bytes 类型的 json数据,转换为 json str
        book_dict_str = book_dict_bytes.decode()
        # json.loads():将一个 JSON 格式的字符串转换成 Python 的数据类型
        # (通常是字典或列表,但也可能是字符串、数字、布尔值等)。
        data_dict = json.loads(book_dict_str)
        print('data_dict', data_dict)

        # 更新对象的属性(只更新允许的字段)
        allowed_fields = {'title', 'pub_date', 'read', 'comment'}
        # 从接收到的data_dict里处理需要修改的数据
        # 对一个字典调用 items() 方法时,它会返回一个可迭代的视图对象,
        # 该对象包含了字典中的键值对(key-value pairs)。
        # 每个键值对都以一个元组(tuple)的形式表示,
        # 元组中第一个元素是键,第二个元素是与该键相关联的值。
        for field, value in data_dict.items():
            # hasattr(book, field): 这个函数检查 book 对象是否有名为 field 的属性, 返回布尔值
            if field in allowed_fields and hasattr(book, field):
                # setattr(book, field, value):这个函数用于动态地设置对象的属性。
                # 在这里,它将 book 对象的 field 属性设置为 value。
                setattr(book, field, value)
        book.save()

        # 准备返回数据:JsonResponse 用于返回字典或列表
        response_data = {
            'title': book.title,
            'pub_date': book.pub_date,
            'read': book.read,
            'comment': book.comment if book.comment else ''
        }

        return JsonResponse(response_data, status=200)

    # 删除指定
    def delete(self, request, pk):
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return JsonResponse({'message': '没有此图书'}, status=404)
        book.delete()
        return JsonResponse({'message': '删除成功'}, status=200)

getattr()

getattr() 是 Python 中的一个内置函数,它用于获取对象的属性值。如果指定的属性存在,getattr() 会返回其值;如果不存在,则可以返回一个默认值(如果提供了的话),或者抛出一个 AttributeError 异常(如果没有提供默认值)。

getattr() 函数的基本语法如下:

getattr(object, name[, default])
  • object:要获取属性的对象。

  • name:要获取的属性的名称(作为字符串)。

  • default:(可选)如果属性不存在,则返回的值。如果不提供此参数,并且属性不存在,则会抛出 AttributeError

hasattr()

hasattr() 是 Python 中的一个内置函数,用于检查对象是否具有指定的属性。它接受两个参数:一个是要检查的对象,另一个是属性名的字符串。如果对象具有该属性,hasattr() 返回 True;如果不具有,则返回 False

hasattr(object, name)
  • object:要获取属性的对象。

  • name:要获取的属性的名称(作为字符串)。

setattr()

setattr() 是 Python 的内置函数之一,其用途是设置对象的属性值。该函数接受三个参数:对象本身、属性名(需为字符串形式)以及要设置的新属性值。若指定的属性在对象中已存在,setattr() 会更新其值;若不存在,则会创建该属性并赋值。

以下是 setattr() 的基本语法:

setattr(object, name, value)
  • object:代表要设置属性的对象。
  • name:表示要设置的属性名,需以字符串形式提供。
  • value:指定属性的新值。