Django Rest Framework - ไม่สามารถแก้ไข URL สำหรับความสัมพันธ์ที่เชื่อมโยงหลายมิติโดยใช้ชื่อมุมมอง“ user-detail”


108

ฉันกำลังสร้างโครงการใน Django Rest Framework ซึ่งผู้ใช้สามารถเข้าสู่ระบบเพื่อดูห้องเก็บไวน์ของพวกเขาได้ ModelViewSets ของฉันทำงานได้ดีและทันใดนั้นฉันก็ได้รับข้อผิดพลาดที่น่าผิดหวังนี้:

ไม่สามารถแก้ไข URL สำหรับความสัมพันธ์แบบไฮเปอร์ลิงก์โดยใช้ชื่อมุมมอง "user-detail" คุณอาจไม่สามารถรวมโมเดลที่เกี่ยวข้องใน API ของคุณหรือกำหนดค่าlookup_fieldแอตทริบิวต์ในฟิลด์นี้ไม่ถูกต้อง

การย้อนกลับแสดง:

    [12/Dec/2013 18:35:29] "GET /bottles/ HTTP/1.1" 500 76677
Internal Server Error: /bottles/
Traceback (most recent call last):
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/viewsets.py", line 78, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 399, in dispatch
    response = self.handle_exception(exc)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 396, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/mixins.py", line 96, in list
    return Response(serializer.data)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 535, in data
    self._data = [self.to_native(item) for item in obj]
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 325, in to_native
    value = field.field_to_native(obj, field_name)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 153, in field_to_native
    return self.to_native(value)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 452, in to_native
    raise Exception(msg % view_name)
Exception: Could not resolve URL for hyperlinked relationship using view 
name "user-detail". You may have failed to include the related model in 
your API, or incorrectly configured the `lookup_field` attribute on this 
field.

ฉันมีรูปแบบผู้ใช้อีเมลที่กำหนดเองและรุ่นขวดใน models.py คือ:

class Bottle(models.Model):    
      wine = models.ForeignKey(Wine, null=False)
      user = models.ForeignKey(User, null=False, related_name='bottles')

Serializers ของฉัน:

class BottleSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Bottle
        fields = ('url', 'wine', 'user')

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'password', 'is_superuser')

มุมมองของฉัน:

class BottleViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows bottles to be viewed or edited.
    """
    queryset = Bottle.objects.all()
    serializer_class = BottleSerializer

class UserViewSet(ListCreateAPIView):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

และสุดท้าย url:

router = routers.DefaultRouter()
router.register(r'bottles', views.BottleViewSet, base_name='bottles')

urlpatterns = patterns('',
    url(r'^', include(router.urls)),
    # ...

ฉันไม่มีมุมมองรายละเอียดผู้ใช้และไม่เห็นว่าปัญหานี้มาจากไหน ความคิดใด ๆ ?

ขอบคุณ

คำตอบ:


96

เนื่องจากเป็นHyperlinkedModelSerializerserializer ของคุณกำลังพยายามแก้ไข URL สำหรับสิ่งที่เกี่ยวข้องUserในBottleไฟล์.
เนื่องจากคุณไม่มีมุมมองรายละเอียดผู้ใช้จึงไม่สามารถทำได้ ดังนั้นข้อยกเว้น

  1. จะไม่เพียงแค่ลงทะเบียนUserViewSetกับเราเตอร์เพื่อแก้ปัญหาของคุณ?
  2. คุณสามารถกำหนดฟิลด์ผู้ใช้บนของคุณBottleSerializerเพื่อใช้อย่างชัดเจนUserSerializerแทนที่จะพยายามแก้ไข URL ดูเอกสาร serializer เกี่ยวกับการจัดการกับวัตถุที่ซ้อนกันสำหรับสิ่งนั้น

1
ขอบคุณมากฉันได้แสดงความคิดเห็นเกี่ยวกับ UserViewSet ในเราเตอร์ของฉันซึ่งแก้ไขได้!
bpipat

5
นั่นคือจุดที่ ---- ทำอย่างชัดเจน --- การใช้เวทมนตร์มากคือการเสียเวลาไปมาก
andilabs

คุณช่วยชี้ให้เห็นสิ่งที่กำหนดค่าไม่ถูกต้องในโครงการของฉันได้หรือไม่?
JJD

@ GrijeshChauhan— ขอบคุณ! แก้ไขแล้ว
Carlton Gibson

สาเหตุที่ใช้งานไม่ได้เนื่องจาก django ต้องการแสดงข้อมูลที่เกี่ยวข้องจาก User ในมุมมองปัจจุบันของคุณสำหรับพารามิเตอร์ User โดยปกติแล้วจะหยิบรายการค่าที่มีอยู่ เนื่องจากไม่ได้กำหนด UserViewSet จึงไม่สามารถดึงรายละเอียดเพื่อแสดงหน้าเว็บได้ การเพิ่ม UserViewSet และการตั้งค่าใหม่ภายใต้เราเตอร์เริ่มต้นทำให้การแสดงผลคอมโพเนนต์ทั้งหมดสมบูรณ์
Doogle

66

ฉันเจอข้อผิดพลาดนี้ด้วยและแก้ไขได้ดังนี้:

เหตุผลก็คือฉันลืมให้ "** - detail" (view_name เช่น: user-detail) เนมสเปซ ดังนั้น Django Rest Framework จึงไม่พบมุมมองนั้น

มีอยู่คนหนึ่งแอปในโครงการของฉันสมมติว่าชื่อโครงการของฉันคือเป็นmyprojectและชื่อ app myappเป็น

มีไฟล์ urls.py สองเป็นหนึ่งmyproject/urls.pyและอื่น ๆ myapp/urls.pyคือ ฉันให้เนมสเปซแก่แอปmyproject/urls.pyเช่นเดียวกับ:

url(r'', include(myapp.urls, namespace="myapp")),

ฉันลงทะเบียนเราเตอร์เฟรมเวิร์กที่เหลือmyapp/urls.pyแล้วได้รับข้อผิดพลาดนี้

วิธีแก้ปัญหาของฉันคือระบุ url พร้อมเนมสเปซอย่างชัดเจน:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")

    class Meta:
        model = User
        fields = ('url', 'username')

และมันช่วยแก้ปัญหาของฉันได้


@boveson งานนี้เหมือนมีเสน่ห์! ขอบคุณที่แก้ไขความยุ่งยากหลายชั่วโมงที่อยู่เคียงข้างฉัน
lmiguelvargasf

สิ่งนี้ทำให้ฉันได้ผลเช่นกัน จุดสำคัญอย่างหนึ่งในฝั่งของฉันคือการสะกด base_name ที่ถูกต้องในเส้นทาง!
maggie

1
คีย์ในที่นี้คือคำนำหน้าเนมสเปซป้องกันการย้อนกลับไม่ให้ทำงาน .....
boatcoder

ฉันมีปัญหาเช่นนี้และคำตอบนี้ช่วยแก้ปัญหาของฉันได้หลังจากค้นหา 3 ชั่วโมง! @bovenson
Whale 52Hz

หรือคุณสามารถใช้ extra_kwargs ตามที่ drf แนะนำ:extra_kwargs = {'url': {'view_name': 'myapp:user-detail'}}
ChrisRob

19

อาจมีใครบางคนสามารถดูสิ่งนี้: http://www.django-rest-framework.org/api-guide/routers/

หากใช้เนมสเปซกับซีเรียลไลเซอร์ไฮเปอร์ลิงก์คุณจะต้องตรวจสอบให้แน่ใจว่าพารามิเตอร์ view_name ใด ๆ บนซีเรียลไลเซอร์แสดงเนมสเปซอย่างถูกต้อง ตัวอย่างเช่น:

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include(router.urls, namespace='api')),
]

คุณจะต้องรวมพารามิเตอร์เช่นview_name='api:user-detail'สำหรับฟิลด์ serializer ที่เชื่อมโยงกับมุมมองรายละเอียดผู้ใช้

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="api:user-detail")

class Meta:
    model = User
    fields = ('url', 'username')

1
สรุปแล้วการให้เนมสเปซ api ของคุณทำให้เกิดข้อผิดพลาดในชื่อคุณอาจไม่ต้องการทำเว้นแต่คุณต้องการเปลี่ยนในหลาย ๆ ที่
มาร์ค

ทำงานให้ฉัน! ของฉันurls.pyซ้อนอยู่ในnewsiteโครงการของฉัน: (1) newsite/urls.py(สร้างโดย django) (2) polls/urls.py(3) polls/api/v1/urls.py ............ ฉันต้องพูดถึงชื่อที่ซ้อนกันโดยใช้url = serializers.HyperlinkedIdentityField(view_name="polls:polls_api:user-detail")
Grijesh Chauhan

13

ข้อผิดพลาดที่น่ารังเกียจอีกประการหนึ่งที่ทำให้เกิดข้อผิดพลาดนี้คือการกำหนด base_name โดยไม่จำเป็นใน urls.py ของคุณ ตัวอย่างเช่น:

router.register(r'{pathname}', views.{ViewName}ViewSet, base_name='pathname')

ซึ่งจะทำให้เกิดข้อผิดพลาดที่ระบุไว้ข้างต้น รับ base_name outta ที่นั่นและกลับไปที่ API ที่ใช้งานได้ โค้ดด้านล่างจะแก้ไขข้อผิดพลาด ไชโย!

router.register(r'{pathname}', views.{ViewName}ViewSet)

อย่างไรก็ตามคุณอาจไม่ได้เพิ่ม base_name โดยพลการ แต่คุณอาจทำไปแล้วเนื่องจากคุณกำหนด get_queryset () def ที่กำหนดเองสำหรับ View ดังนั้น Django จึงสั่งให้คุณเพิ่ม base_name ในกรณีนี้คุณจะต้องกำหนด 'url' อย่างชัดเจนเป็น HyperlinkedIdentityField สำหรับ serializer ที่เป็นปัญหา สังเกตว่าเรากำลังกำหนด HyperlinkedIdentityField นี้บน SERIALIZER ของมุมมองที่ทำให้เกิดข้อผิดพลาด หากข้อผิดพลาดของฉันคือ "ไม่สามารถแก้ไข URL สำหรับความสัมพันธ์ที่เชื่อมโยงหลายมิติโดยใช้ชื่อข้อมูลพร็อพเพอร์ตี้" study-detail "คุณอาจไม่สามารถรวมโมเดลที่เกี่ยวข้องใน API ของคุณหรือกำหนดค่าlookup_fieldแอตทริบิวต์ในช่องนี้ไม่ถูกต้อง" ฉันสามารถแก้ไขได้ด้วยรหัสต่อไปนี้

My ModelViewSet (get_queryset ที่กำหนดเองคือสาเหตุที่ฉันต้องเพิ่ม base_name ไปยัง router.register () ตั้งแต่แรก):

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

    '''custom get_queryset'''
    def get_queryset(self):
        queryset = Study.objects.all()
        return queryset

การลงทะเบียนเราเตอร์ของฉันสำหรับ ModelViewSet นี้ใน urls.py:

router.register(r'studies', views.StudyViewSet, base_name='studies')

และนี่คือที่ที่เงินอยู่! จากนั้นฉันสามารถแก้ปัญหาได้ดังนี้:

class StudySerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="studies-detail")
    class Meta:
        model = Study
        fields = ('url', 'name', 'active', 'created',
              'time_zone', 'user', 'surveys')

ใช่. คุณต้องกำหนด HyperlinkedIdentityField นี้อย่างชัดเจนเพื่อให้ใช้งานได้ และคุณต้องตรวจสอบให้แน่ใจว่าค่าที่view_nameกำหนดบน HyperlinkedIdentityField นั้นเหมือนกับที่คุณกำหนดไว้base_nameใน urls.py โดยมี '-detail' ที่เพิ่มไว้ข้างหลัง


2
สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่ฉันต้องวางเส้นทาง<app_name>:studies-detailทั้งหมด ตัวอย่างเช่น my if my app is called tanks, then the full path will be HyperlinkedIdentityField(view_name="tanks:studies-detail"). เพื่อให้เข้าใจว่าฉันใช้คำสั่งdjango-exensions show_urlsเพื่อดูเส้นทางแบบเต็มและป้ายกำกับที่เราเตอร์สร้างขึ้นโดยอัตโนมัติ
dtasev

10

รหัสนี้ควรใช้งานได้เช่นกัน

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

  class Meta:
    model = Bottle
    fields = ('url', 'wine', 'user')

3
เป็นที่น่าสังเกตว่าUserSerializerจะต้องดำเนินการ (ยังไม่พร้อมที่จะนำเข้า) ดังแสดงในdjango-rest-framework.org/api-guide/serializers
Caumons

สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่เพื่อให้ใช้งานได้ฉันต้องเปลี่ยน router.register (r'bottles ', views.BottleViewSet, base_name =' bottles ') เป็น router.register (r'bottles', views.BottleViewSet) ฉันไม่รู้ว่าทำไมจึงต้องมีการเปลี่ยนแปลงนี้
manpikin

4

ฉันพบข้อผิดพลาดนี้หลังจากเพิ่มเนมสเปซใน URL ของฉัน

 url('api/v2/', include('api.urls', namespace='v2')),

และเพิ่ม app_name ใน urls.py ของฉัน

ฉันแก้ไขสิ่งนี้โดยระบุ NamespaceVersioning สำหรับ API กรอบงานที่เหลือของฉันใน settings.py ของโครงการของฉัน

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.NamespaceVersioning'}

4

วันนี้ฉันได้รับข้อผิดพลาดเดียวกันและการเปลี่ยนแปลงด้านล่างช่วยฉันได้

เปลี่ยน

class BottleSerializer(serializers.HyperlinkedModelSerializer):

ถึง:

 class BottleSerializer(serializers.ModelSerializer):

2

ข้อผิดพลาดเดียวกัน แต่เหตุผลต่างกัน:

ฉันกำหนดรูปแบบผู้ใช้ที่กำหนดเองไม่มีฟิลด์ใหม่:

from django.contrib.auth.models import (AbstractUser)
class CustomUser(AbstractUser):
    """
    custom user, reference below example
    https://github.com/jonathanchu/django-custom-user-example/blob/master/customuser/accounts/models.py

    # original User class has all I need
    # Just add __str__, not rewrite other field
    - id
    - username
    - password
    - email
    - is_active
    - date_joined
    - method, email_user
    """

    def __str__(self):
        return self.username

นี่คือฟังก์ชั่นมุมมองของฉัน:

from rest_framework import permissions
from rest_framework import viewsets
from .models import (CustomUser)
class UserViewSet(viewsets.ModelViewSet):
    permission_classes = (permissions.AllowAny,)
    serializer_class = UserSerializer

    def get_queryset(self):
        queryset = CustomUser.objects.filter(id=self.request.user.id)
        if self.request.user.is_superuser:
            queryset = CustomUser.objects.all()
        return queryset

เนื่องจากฉันไม่ได้ให้querysetโดยตรงUserViewSetฉันจึงต้องตั้งค่าbase_nameเมื่อฉันลงทะเบียน viewset นี้ นี่คือที่ข้อความแสดงข้อผิดพลาดของฉันที่เกิดจากurls.pyไฟล์:

from myapp.views import (UserViewSet)
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, base_name='customuser')  # <--base_name needs to be 'customuser' instead of 'user'

คุณจำเป็นต้องมีbase_nameชื่อเดียวกับชื่อรุ่นของคุณ customuser-


โพสต์เก่า แต่ความคิดเห็นของคุณ "# <- base_name ต้องเป็น" customuser "แทน" user "" คือสิ่งที่ช่วยชีวิตฉัน ขอบคุณ!
Hannon César

1

หากคุณกำลังขยายคลาสGenericViewSetและListModelMixinและมีข้อผิดพลาดเดียวกันเมื่อเพิ่มฟิลด์urlในมุมมองรายการนั่นเป็นเพราะคุณไม่ได้กำหนดมุมมองรายละเอียด ต้องแน่ใจว่าคุณกำลังขยายมิกซ์อินRetrieveModelMixin :

class UserViewSet (mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   viewsets.GenericViewSet):

1

ปรากฏว่าไม่เห็นด้วยกับการมีเส้นทางHyperlinkedModelSerializer namespaceในใบสมัครของฉันฉันได้ทำการเปลี่ยนแปลงสองครั้ง

# rootapp/urls.py
urlpatterns = [
    # path('api/', include('izzi.api.urls', namespace='api'))
    path('api/', include('izzi.api.urls')) # removed namespace
]

ในไฟล์ urls ที่นำเข้า

# app/urls.py
app_name = 'api' // removed the app_name

หวังว่านี่จะช่วยได้


0

ฉันพบข้อผิดพลาดเดียวกันในขณะที่ฉันทำตามคู่มือ DRF ฉบับย่อ http://www.django-rest-framework.org/tutorial/quickstart/จากนั้นพยายามเรียกดู / users ฉันได้ทำการตั้งค่านี้หลายครั้งก่อนหน้านี้โดยไม่มีปัญหา

โซลูชันของฉันไม่ได้อยู่ในรหัส แต่อยู่ในการแทนที่ฐานข้อมูล

ความแตกต่างระหว่างการติดตั้งนี้กับการติดตั้งอื่น ๆ ก่อนหน้านี้คือเมื่อฉันสร้างฐานข้อมูลภายในเครื่อง

คราวนี้ฉันวิ่ง

./manage.py migrate
./manage.py createsuperuser

ทันทีหลังจากวิ่ง

virtualenv venv
. venv/bin/activate
pip install django
pip install djangorestframework

แทนที่จะเป็นลำดับที่แน่นอนที่ระบุไว้ในคำแนะนำ

ฉันสงสัยว่ามีบางอย่างไม่ได้สร้างขึ้นอย่างถูกต้องในฐานข้อมูล ฉันไม่สนใจ dev db ของฉันดังนั้นฉันจึงลบมันและเรียกใช้./manage.py migrateคำสั่งอีกครั้งสร้างผู้ใช้ขั้นสูงเรียกดู / ผู้ใช้และข้อผิดพลาดก็หายไป

มีบางอย่างเป็นปัญหากับลำดับการดำเนินการที่ฉันกำหนดค่า DRF และฐานข้อมูล

หากคุณใช้ sqlite และสามารถทดสอบการเปลี่ยนเป็น DB ใหม่ได้ก็คุ้มค่าที่จะลองก่อนที่คุณจะแยกรหัสทั้งหมดของคุณ


0

ขวด = serializers.PrimaryKeyRelatedField (read_only = True)

read_only ช่วยให้คุณสามารถแสดงฟิลด์ได้โดยไม่ต้องเชื่อมโยงกับมุมมองอื่นของโมเดล


0

ฉันได้รับข้อผิดพลาดนั้นใน DRF 3.7.7 เมื่อค่ากระสุนว่างเปล่า (เท่ากับ '') ในฐานข้อมูล


0

ฉันพบปัญหาเดียวกันนี้และแก้ไขได้โดยการเพิ่มgenerics.RetrieveAPIViewเป็นคลาสพื้นฐานในมุมมองของฉัน


0

ฉันติดอยู่ในข้อผิดพลาดนี้เกือบ 2 ชั่วโมง:

กำหนดค่าไม่ถูกต้องที่ / api_users / users / 1 / ไม่สามารถแก้ไข URL สำหรับความสัมพันธ์ที่เชื่อมโยงหลายมิติโดยใช้ชื่อมุมมอง "users-detail" คุณอาจไม่สามารถรวมโมเดลที่เกี่ยวข้องใน API ของคุณหรือกำหนดค่าlookup_fieldแอตทริบิวต์ในฟิลด์นี้ไม่ถูกต้อง

ในที่สุดเมื่อฉันได้วิธีแก้ปัญหา แต่ฉันไม่เข้าใจว่าทำไมรหัสของฉันคือ:

#models.py
class Users(models.Model):
    id          = models.AutoField(primary_key=True)
    name        = models.CharField(max_length=50, blank=False, null=False)
    email       = models.EmailField(null=False, blank=False) 
    class Meta:
        verbose_name = "Usuario"
        verbose_name_plural = "Usuarios"

    def __str__(self):
        return str(self.name)


#serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Users
        fields = (
            'id',
            'url',
            'name',        
            'email',       
            'description', 
            'active',      
            'age',         
            'some_date',   
            'timestamp',
            )
#views.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = Users.objects.all()
    serializer_class = UserSerializer

#urls_api.py
router = routers.DefaultRouter()
router.register(r'users',UserViewSet, base_name='users')

urlpatterns = [ 
        url(r'^', include(router.urls)),
]

แต่ใน URL หลักของฉันมันคือ:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls', namespace='api')),

]

ในที่สุดฉันก็แก้ปัญหาการลบเนมสเปซ:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls')),

]

และในที่สุดฉันก็แก้ไขปัญหาของฉันได้ดังนั้นใครก็ได้สามารถแจ้งให้เราทราบว่าทำไมดีที่สุด


0

หากคุณละช่อง "id" และ "url" จาก serializer ของคุณคุณจะไม่มีปัญหาใด ๆ คุณสามารถเข้าถึงโพสต์ได้โดยใช้ id ที่ส่งคืนในอ็อบเจ็กต์ json แต่อย่างใดซึ่งทำให้การใช้งานส่วนหน้าของคุณง่ายขึ้น


0

ฉันมีปัญหาเดียวกันฉันคิดว่าคุณควรตรวจสอบไฟล์

get_absolute_url

ค่าอินพุตเมธอดของโมเดลอ็อบเจ็กต์ (** kwargs) title และใช้ชื่อฟิลด์ที่แน่นอนใน lookup_field

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.