英文:
How to resolve django rest_framework error "Method \"POST\" not allowed."?
问题
抱歉,您的代码中有一些错误,导致无法正常处理POST请求。以下是修复后的代码片段:
from rest_framework import serializers, viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
from django.contrib.auth.models import User
from .models import HDWallet
# ...
class HDWalletSerializer(serializers.ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
class HDWalletCreateView(viewsets.ModelViewSet):
queryset = HDWallet.objects.all()
serializer_class = HDWalletSerializer
@action(detail=False, methods=['post'])
def create_hdwallet(self, request):
username = request.data.get('username')
user = User.objects.get(username=username)
if user:
name = f"{user.username}_{user.id}"
wallet = Wallet.create(name)
hdwallet = HDWallet.objects.create(
name=name,
private_key=wallet.get_key(),
address=wallet.get_key().address,
user=user,
)
return Response(
{
"status": 201,
"message": "Wallet has been successfully created!",
"data": HDWalletSerializer(hdwallet).data,
}
)
else:
return Response({"status": 400, "message": "User does not exist."})
请确保您的视图类继承自viewsets.ModelViewSet
,并且使用了@action
装饰器来处理创建HD钱包的POST请求。另外,确保您在POST请求中发送了有效的username
参数以关联到用户。这些更改应该能够修复问题,让您能够成功创建HD钱包。
英文:
Sorry I'm still a beginner on django I would like to create an endpoint with django rest_framework allowing me to create an HD wallet and backup in database, but I have an error:
> "Method "POST" not allowed ."
So I created this model that represented hdwallet:
from typing import Any
from django.db import models, transaction
from django.contrib.auth.models import User
class HDWallet(models.Model):
"""HDWallet class"""
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
name: str = models.CharField(max_length=255, unique=True)
private_key: str = models.CharField(max_length=100, unique=True)
address: str = models.CharField(max_length=100, unique=True)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="wallet",
)
active = models.BooleanField(default=True)
def __str__(self) -> str:
return self.name
@transaction.atomic
def disable(self) -> Any:
if self.active is False:
# Ne faisons rien si la wallet est déjà désactivée
return
self.active = False
self.save()
self.currencies.update(active=False)
also I created my serializers class:
class HDWalletSerializer(ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
def post(self, request: Request) -> Any:
user = User.objects.get(username=request["username"])
name = f"{user.username}_{user.id}"
wallet = Wallet.create(name)
if user is not None:
hdwallet = HDWallet.objects.create(
{
"name": name,
"private_key": wallet.get_key(),
"address": wallet.get_key().address,
"user": user.id,
}
)
else:
raise Exception("use do not exist")
return Response(
{
"status": 201,
"message": "wallet have been successfully created!",
"data": hdwallet,
}
)
and my view in views.py:
class HDWalletCreateView(ModelViewSet):
serializer_class = HDWalletSerializer
permission_classes = [IsUser, IsUserAuthenticated, IsAdminAuthenticated]
and the this is the URL:
# we create your router
router = routers.SimpleRouter()
# we register all url
router.register("wallet/create", HDWalletCreateView, basename="wallet-create"),
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include(router.urls)),
]
but when I run the endpoint to postman I have this error:
>"detail": "Method "POST" not allowed."
I don't know where is the problem
答案1
得分: 1
I think if you want to create a CRUD like that, the good think is to use the ModelViewSets, Rather than creating our URLs and redefining our methods one by one, DRF offers inheritable classes for our views, which are the ModelViewsets. They allow the rapid implementation of all CRUD actions for a given model. Using a ModelViewset requires using another way of defining our URLs. This is done through a router. You can Juste declared your Serializer
class HDWalletSerializer(ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
Your views will look like this
class HDWalletCRUDViewset(ModelViewSet):
serializer_class = HDWalletSerializer
def get_queryset(self) -> Any:
return HDWallet.objects.filter(active=True)
at the end, to access to the endpoint, you can get this code:
from django.urls import path, include
from rest_framework import routers
from wallet.views import (
HDWalletCRUDViewset,
)
router = routers.SimpleRouter()
# we register all url
router.register("wallets", HDWalletCRUDViewset, basename="wallets")
urlpatterns = [
path("api/", include(router.urls)),
]
Notice that the router use the viewset to do all action
英文:
I think if you want to create a CRUD like that, the good think is to use the ModelViewSets, Rather than creating our URLs and redefining our methods one by one, DRF offers inheritable classes for our views, which are the ModelViewsets.
They allow the rapid implementation of all CRUD actions for a given model.
Using a ModelViewset requires using another way of defining our URLs. This is done through a router. You can Juste declared your Serializer
class HDWalletSerializer(ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
Your views will look like this
class HDWalletCRUDViewset(ModelViewSet):
serializer_class = HDWalletSerializer
def get_queryset(self) -> Any:
return HDWallet.objects.filter(active=True)
at the end, to access to the endpoint, you can get this code:
from django.urls import path, include
from rest_framework import routers
from wallet.views import (
HDWalletCRUDViewset,
)
router = routers.SimpleRouter()
# we register all url
router.register("wallets", HDWalletCRUDViewset, basename="wallets")
urlpatterns = [
path("api/", include(router.urls)),
]
Notice that the router use the viewset to do all action
答案2
得分: 0
最终,我解决了这个问题,我在网络文档上找到了帮助我理解如何使用DRF执行CRUD操作的文档。所以这就是解决方案,我将在最后放上网络教程的链接。
我的钱包类模型没有改变:
class HDWallet(models.Model):
"""HDWallet class"""
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
name: str = models.CharField(max_length=255, unique=True)
private_key: str = models.CharField(max_length=100, unique=True)
address: str = models.CharField(max_length=100)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="wallet",
)
active = models.BooleanField(default=True)
def __str__(self) -> str:
return self.name
这是我的序列化器类:
class HDWalletSerializer(ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
这是我的视图文件:
@api_view(["GET", "POST", "DELETE"])
def wallet_list(request):
if request.method == "GET":
wallets = HDWallet.objects.all()
name = request.query_params.get("name", None)
if name is not None:
wallets = wallets.filter(name=name)
tutorials_serializer = HDWalletSerializer(wallets, many=True)
return JsonResponse(tutorials_serializer.data, safe=False)
elif request.method == "POST":
wallet_data = request.data
wallet_serializer = HDWalletSerializer(data=wallet_data)
if wallet_serializer.is_valid():
wallet_serializer.save()
return JsonResponse(wallet_serializer.data, status=status.HTTP_201_CREATED)
return JsonResponse(
wallet_serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
elif request.method == "DELETE":
count = HDWalletSerializer.objects.all().delete()
return JsonResponse(
{"message": "{} Tutorials were deleted successfully!".format(count[0])},
status=status.HTTP_204_NO_CONTENT,
)
@api_view(["GET", "PUT", "DELETE"])
def wallet_detail(request, pk):
try:
wallet = HDWallet.objects.get(pk=pk)
except HDWallet.DoesNotExist:
return JsonResponse(
{"message": "The wallet does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
if request.method == "GET":
wallet_serializer = HDWalletSerializer(wallet)
return JsonResponse(wallet_serializer.data)
elif request.method == "PUT":
wallet_data = JSONParser().parse(request)
wallet_serializer = HDWalletSerializer(wallet, data=wallet_data)
if wallet_serializer.is_valid():
wallet_serializer.save()
return JsonResponse(wallet_serializer.data)
return JsonResponse(
wallet_serializer.errors,
status=status.HTTP_400_BAD_REQUEST,
)
elif request.method == "DELETE":
wallet.delete()
return JsonResponse(
{"message": "Wallet was deleted successfully!"},
status=status.HTTP_204_NO_CONTENT,
)
@api_view(["GET"])
def wallet_list_published(request):
wallets = HDWallet.objects.filter(published=True)
if request.method == "GET":
wallets_serializer = HDWalletSerializer(wallets, many=True)
return JsonResponse(wallets_serializer.data, safe=False)
最后是URL配置文件:
from django.urls import path
from wallet.views import (
wallet_detail,
wallet_list,
)
urlpatterns = [
path("api/wallets/", wallet_list),
path("api/wallets/<pk>/", wallet_detail),
]
所以这是图像上的结果:
[![在此输入图片描述][1]][1]
[![在此输入图片描述][1]][1]
我们有一些配置要做,我在这里放了教程链接,供需要更多解释的人参考:
[在此输入链接描述][1]
链接:https://www.bezkoder.com/django-rest-api/
英文:
finally I resolved the problem, I falled on the web documents who help me to have a good understand of how to perform crud using DRF. So that is the solution and I will put the link to the web tutorial at the end.
the model of my wallet class didn't change:
class HDWallet(models.Model):
"""HDWallet class"""
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
name: str = models.CharField(max_length=255, unique=True)
private_key: str = models.CharField(max_length=100, unique=True)
address: str = models.CharField(max_length=100)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="wallet",
)
active = models.BooleanField(default=True)
def __str__(self) -> str:
return self.name
that is my serializer class:
class HDWalletSerializer(ModelSerializer):
class Meta:
model = HDWallet
fields = "__all__"
that is my views file:
@api_view(["GET", "POST", "DELETE"])
def wallet_list(request):
if request.method == "GET":
wallets = HDWallet.objects.all()
name = request.query_params.get("name", None)
if name is not None:
wallets = wallets.filter(name=name)
tutorials_serializer = HDWalletSerializer(wallets, many=True)
return JsonResponse(tutorials_serializer.data, safe=False)
elif request.method == "POST":
wallet_data = request.data
wallet_serializer = HDWalletSerializer(data=wallet_data)
if wallet_serializer.is_valid():
wallet_serializer.save()
return JsonResponse(wallet_serializer.data, status=status.HTTP_201_CREATED)
return JsonResponse(
wallet_serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
elif request.method == "DELETE":
count = HDWalletSerializer.objects.all().delete()
return JsonResponse(
{"message": "{} Tutorials were deleted successfully!".format(count[0])},
status=status.HTTP_204_NO_CONTENT,
)
@api_view(["GET", "PUT", "DELETE"])
def wallet_detail(request, pk):
try:
wallet = HDWallet.objects.get(pk=pk)
except HDWallet.DoesNotExist:
return JsonResponse(
{"message": "The wallet does not exist"},
status=status.HTTP_404_NOT_FOUND,
)
if request.method == "GET":
wallet_serializer = HDWalletSerializer(wallet)
return JsonResponse(wallet_serializer.data)
elif request.method == "PUT":
wallet_data = JSONParser().parse(request)
wallet_serializer = HDWalletSerializer(wallet, data=wallet_data)
if wallet_serializer.is_valid():
wallet_serializer.save()
return JsonResponse(wallet_serializer.data)
return JsonResponse(
wallet_serializer.errors,
status=status.HTTP_400_BAD_REQUEST,
)
elif request.method == "DELETE":
wallet.delete()
return JsonResponse(
{"message": "Wallet was deleted successfully!"},
status=status.HTTP_204_NO_CONTENT,
)
@api_view(["GET"])
def wallet_list_published(request):
wallets = HDWallet.objects.filter(published=True)
if request.method == "GET":
wallets_serializer = HDWalletSerializer(wallets, many=True)
return JsonResponse(wallets_serializer.data, safe=False)
and finally the urls file:
from django.urls import path
from wallet.views import (
wallet_detail,
wallet_list,
)
urlpatterns = [
path("api/wallets/", wallet_list),
path("api/wallets/<pk>/", wallet_detail),
]
so that's the result here on image
[![enter image description here][1]][1]
[![enter image description here][1]][1]
We have certains configurations to do, I put the tutorial link for who want to have more explanation:
[enter link description here][1]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论