練習

使用DRF django rest framework來寫一個簡單的購物車api,前端的部分就斟酌斟酌的寫了~主要著重在DRF這個超集,一直沒有好好的用他來寫一個東東出來,新的一年就來試著寫寫吧!

首先當然是建立環境,虛擬環境很多種大家就挑自己喜歡的建吧~
然後pip的部分如下

asgiref==3.7.2
Django==5.0.1
django-filter==23.5
djangorestframework==3.14.0
djangorestframework-simplejwt==5.3.1
Markdown==3.5.2
PyJWT==2.8.0
pytz==2023.3.post1
setuptools==68.2.2
sqlparse==0.4.4
tzdata==2023.4
wheel==0.41.2

python的版本則是用3.12.0

資料夾

目前規劃如下,有account, cart, order, shop, product

登入

首當其衝的就是登入了,目前考慮使用simplejwt和內建的api-auth兩個並行,api-auth是測試的時候比較方便,之後還要考慮轉換成simplejwt後一些request驗證怎麼執行~

# settings.py

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'rest_framework_simplejwt',
    # ...
]

REST_FRAMEWORK = {
    # ...
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    # ...
}
# project下的urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
    TokenVerifyView,
)


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]

之後跑

  • python manage.py migrate
  • python manage.py runserver

接著去 http://127.0.0.1:8000/api/token

帳號密碼呢,我們先用 python manage.py createsuperuser建立一個admin帳號來測試會拿到什麼token~建立好輸入帳號密碼應該會像下面這樣拿到token~

HTTP 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcwOTczNTE0MywiaWF0IjoxNzA1NDE1MTQzLCJqdGkiOiJkMWI0MzRkZjc5YTM0MjE1OWFlOGY3ODViOWZiZWFiNiIsInVzZXJfaWQiOjF9.eCAuJ9LMUUbAYDmtB9h9VBbjCthz-SucJlcTTNztJk4",
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzA1NDI1OTQzLCJpYXQiOjE3MDU0MTUxNDMsImp0aSI6ImY3MjViYmU4ZWVjZTQ5ZWJiYjk4MzZiMDk5NmM5MTVkIiwidXNlcl9pZCI6MX0.tAlpCVanj942qMjgBdxcTwqpLmdFCmPsSOJqkgw2XmY"
}

這邊只是測試能否運行,實際要使用到JWT應該滿後期了~

Account

一開始就從Account開始著手吧!首先要起一個account的app

  • python manage.py startapp account

DRF會有三個不同負責的區域

  • models
  • serializers
  • views

models

我們會需要動用到django內建的User,所以我們的model會去繼承

from django.db import models
from django.contrib.auth.models import AbstractUser


class Account(AbstractUser):
    
    class Sex(models.IntegerChoices):
        FEMALE = 0, "Female"
        MALE = 1, "Male"
        OTHER = 2, "Other"
    
    sex = models.PositiveSmallIntegerField(
        verbose_name="sex",
        choices=Sex,
        default=Sex.OTHER
        )
    
    phone = models.CharField(
        verbose_name="phone", 
        max_length=10
        )
    
    email = models.EmailField(
        verbose_name="email", 
        max_length=254
        )
    
    address = models.CharField(
        verbose_name="address", 
        max_length=100
        )
    
    def __str__(self):
        return self.username

這邊除了AbstractUser自帶的欄位外我自己新增了幾項~

serializers

models是主要跟資料庫連結的class,而serializers則是把models跟view接在一起的通道

class AccountSerializer(serializers.HyperlinkedModelSerializer):

    sex = serializers.SerializerMethodField()

    class Meta:
        model = Account
        fields = ["username", "sex", "email", "phone", "address", "url", "is_superuser", "is_staff"]

    def get_sex(self, obj):
        return obj.get_sex_display()

sex 性別額外拉出來是因為我想要它顯示的時候是顯示 male, female, other這樣,而不是0, 1, 2,至於這邊是怎麼對接上的有時間再來好好研究研究~

views

views當然就是要準備回傳值的地方囉~

from rest_framework import viewsets
from account.models import Account
from account.serializers import AccountSerializer


class AccountsView(viewsets.ModelViewSet):
    queryset = Account.objects.all().order_by("id")
    serializer_class = AccountSerializer

urls

最後把我們寫好的view註冊到urls裡面

from account import views
from rest_framework import routers


router = routers.DefaultRouter()
router.register(r'', views.AccountsView)

urlpatterns = [
     # ...
]

urlpatterns += router.urls

最後在

  • python manage.py makemigrations
  • python manage.py migrate
  • python manage.py runserver

就可以看到DRF預設可以操作api的頁面囉~