我还是python / django的新手,目前我正尝试使用django rest框架添加REST API。这是我目前拥有的:
urls.py
actions_url = {'actions': {'get': 'list', 'post': 'create'}}
actions_obj = {'actions': {'get': 'retrieve', 'delete': 'destroy', 'put': 'update'}}
urlpatterns = [
path('book', BookViewSet.as_view(**actions_url)),
path('book/<str:isbn>', BookViewSet.as_view(**actions_obj))
]
models.py(该模型没有PK)
class Book(models.Model):
BNAME = models.CharField(
db_column='BNAME',
max_length=30,
default='')
BISBN = models.CharField(
db_column='BISBN',
max_length=10,
default='')
views.py
class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN")
class Meta:
model = models.Book
fields = ('name', 'isbn')
class BookViewSet(viewsets.ModelViewSet)
queryset = Book.objects.all()
serializer_class = BookSerializer
def list(self, request):
return queryset
def create(self, request):
pass
def retrieve(self, request, *args, **kwargs):
pass
def update(self, request, *args, **kwargs):
pass
def destroy(self, request, *args, **kwargs):
pass
所以我的问题是:
def create(self, request)
包括在BookViewSet
中,那么我假设当我制作POST /book
时它什么都不做?create
,retrieve
,update
,destroy
中的内容。例如,如果我使用参数PUT /book/123
制作了{ isbn: '123', name: 'test'}
,那么我需要在def update
中做什么才能从请求中检索这些数据,然后将数据更新到数据库?isbn
并确保它唯一/不重复,然后再将记录保存/更新到数据库,该怎么办?我尝试阅读有关Validator的文章:https://www.django-rest-framework.org/api-guide/validators/,看起来我需要更新序列化程序:class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN", validators=[<UniqueValidator(queryset=Book.objects.all())>])
class Meta:
model = models.Book
fields = ('name', 'isbn')
这正确吗?
isbn
和name
两者都是唯一的,我认为这是我需要做的:class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN")
class Meta:
model = models.Book
fields = ('name', 'isbn')
validators = [
UniqueTogetherValidator(
queryset=Book.objects.all(),
fields=('name', 'isbn')
)
]
这正确吗?
谢谢
答案 0 :(得分:0)
您实现的create(self, request, *args, **kwargs)
不会执行任何操作,因为该函数为空,甚至不会返回响应。
您不必在create
,list
,retrieve
,update
,partial_update
和{{1} },因为您使用的是destroy
类。 ModelViewSet
为所有它们提供默认的实现。如果您确实想保留替代信息,则可以改用以下实现:
ModelViewSet
我们使用def create(self, request, *args, **kwargs):
"""You could add some documentation here"""
return super().create(request, *args, **kwargs)
是因为它正在调用super()
的父实现。
create
而不是将验证器添加到序列化器中。 Rest Framework非常聪明,序列化程序将检查模型字段并自动神奇地添加唯一的验证。如果您想避免在数据库上使用唯一索引,那么我认为unique=True
的使用是正确的。 UniqueValidator
请记住,如果没有数据库上的唯一索引,您可能会遇到竞争状况。我的意思是,如果这些操作同时发生,则可以创建/更新两本书以具有相同的isbn。
BISBN = models.CharField(db_column='BISBN', max_length=10, default=None, unique=True)
属性对模型上的多个字段进行验证,即Meta.unique_together
但是,如果您不想为此在数据库上使用唯一索引,那么您使用class Book(models.Model):
# fields...
class Meta:
unique_together = ("BNAME", "BISBN")
是正确的。
我认为还有另外一个花絮:
您查看的网址应该包含UniqueTogetherValidator
和lookup_url_kwarg
才能与网址定义中的isbn一起使用。
lookup_field
如果要处理多个url kwarg,则需要自定义class BookViewSet(ModelViewSet):
lookup_url_kwarg = "isbn" # Use the 'isbn' from your url definition
lookup_field = "BISBN" # Use the `BISBN` field on your database/model to perform the lookups
# ...
方法。在下面的代码中,我使用get_queryset()
来过滤查询集,然后让视图按名称查找书。
isbn