如何解决django rest_framework错误”Method \”POST\” not allowed.”?

huangapple go评论130阅读模式
英文:

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):
&quot;&quot;&quot;HDWallet class&quot;&quot;&quot;
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=&quot;wallet&quot;,
)
active = models.BooleanField(default=True)
def __str__(self) -&gt; str:
return self.name

that is my serializer class:

class HDWalletSerializer(ModelSerializer):
    class Meta:
        model = HDWallet
        fields = &quot;__all__&quot;

that is my views file:

@api_view([&quot;GET&quot;, &quot;POST&quot;, &quot;DELETE&quot;])
def wallet_list(request):
if request.method == &quot;GET&quot;:
wallets = HDWallet.objects.all()
name = request.query_params.get(&quot;name&quot;, 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 == &quot;POST&quot;:
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 == &quot;DELETE&quot;:
count = HDWalletSerializer.objects.all().delete()
return JsonResponse(
{&quot;message&quot;: &quot;{} Tutorials were deleted successfully!&quot;.format(count[0])},
status=status.HTTP_204_NO_CONTENT,
)
@api_view([&quot;GET&quot;, &quot;PUT&quot;, &quot;DELETE&quot;])
def wallet_detail(request, pk):
try:
wallet = HDWallet.objects.get(pk=pk)
except HDWallet.DoesNotExist:
return JsonResponse(
{&quot;message&quot;: &quot;The wallet does not exist&quot;},
status=status.HTTP_404_NOT_FOUND,
)
if request.method == &quot;GET&quot;:
wallet_serializer = HDWalletSerializer(wallet)
return JsonResponse(wallet_serializer.data)
elif request.method == &quot;PUT&quot;:
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 == &quot;DELETE&quot;:
wallet.delete()
return JsonResponse(
{&quot;message&quot;: &quot;Wallet was deleted successfully!&quot;},
status=status.HTTP_204_NO_CONTENT,
)
@api_view([&quot;GET&quot;])
def wallet_list_published(request):
wallets = HDWallet.objects.filter(published=True)
if request.method == &quot;GET&quot;:
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(&quot;api/wallets/&quot;, wallet_list),
path(&quot;api/wallets/&lt;pk&gt;/&quot;, wallet_detail),
]
so that&#39;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]

https://www.bezkoder.com/django-rest-api/

huangapple
  • 本文由 发表于 2023年6月15日 22:04:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定