通过我的端点解决多对多关系

时间:2018-04-21 20:29:45

标签: python-3.x django-models django-rest-framework

我有一个RESTful API,我目前可以使用它来添加小部件和可选类别。我的目的是使这个小部件和类别之间的多对多关系。我想我很接近但是如果我尝试将一个小部件分配给一个类别我会收到错误;我希望能够为窗口小部件分配一个类别。这就是我到目前为止所做的:

在我的模特中:

class Widget(models.Model):
    name = models.CharField(max_length=255, blank=False, unique=True)
    inventory = models.IntegerField(default=0, null=False, blank=False)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "{}".format(self.name)

class Category(models.Model):
    name = models.CharField(max_length=255, blank=False, unique=True)
    widget = models.ManyToManyField(Widget)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "{}".format(self.name)

# TODO: add many-to-many relationship between widget and category
class WidgetCategory(models.Model):
    widget = models.ForeignKey(Widget, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "{}".format(self.id)

在我的序列化程序中:

class WidgetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Widget
        fields = '__all__'
        read_only_fields = ('id', 'date_created', 'date_modified')

class WidgetCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = WidgetCategory
        fields = '__all__'
        read_only_fields = ('id', 'widget', 'category', 'date_created', 'date_modified')

class CategorySerializer(serializers.ModelSerializer):
    widgetcategory = WidgetCategorySerializer(source="*", many=True, read_only=True)
    class Meta:
        model = Category
        fields = '__all__'
        read_only_fields = ('id', 'date_created', 'date_modified')

在我看来:

class WidgetCreateView(generics.ListCreateAPIView):
    queryset = Widget.objects.all()
    serializer_class = WidgetSerializer

    def perform_create(self, serializer):
        serializer.save()

class WidgetDetailsView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Widget.objects.all()
    serializer_class = WidgetSerializer

class CategoryCreateView(generics.ListCreateAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

    def perform_create(self, serializer):
        serializer.save()

class CategoryDetailsView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

    def perform_create(self, serializer):
        serializer.save()

在我的端点映射中:

url(r'^widgets/$', WidgetCreateView.as_view(), name="widget_create"),
url(r'^finishes/(?P<pk>[0-9]+)/widgets/$', WidgetCreateView.as_view(), name="widget_create"),
url(r'^sizes/(?P<pk>[0-9]+)/widgets/$', WidgetCreateView.as_view(), name="widget_create"),
url(r'^categories/(?P<pk>[0-9]+)/widgets/$', WidgetCreateView.as_view(), name="widget_create"),
url(r'^widgets/(?P<pk>[0-9]+)/$',
        WidgetDetailsView.as_view(), name="widget_details"),

url(r'^categories/$', CategoryCreateView.as_view(), name="category_create"),
url(r'^widgets/(?P<pk>[0-9]+)/categories/$', CategoryCreateView.as_view(), name="category_create"),
url(r'^categories/(?P<pk>[0-9]+)/$',
        CategoryDetailsView.as_view(), name="category_details"),

当我尝试添加新类别并将新窗口小部件分配给新POST时,我收到此错误:

TypeError at /categories/
'Category' object is not iterable
Request Method: POST
Request URL:    http://localhost:8000/categories/
Django Version: 2.0.4
Exception Type: TypeError
Exception Value:    
'Category' object is not iterable
Exception Location: C:\Users\joe_t\workspace\python_projects\env\lib\site-packages\rest_framework\serializers.py in to_representation, line 683
Python Executable:  C:\Users\joe_t\workspace\python_projects\env\Scripts\python.exe
Python Version: 3.6.4
Python Path:    
['C:\\Users\\joe_t\\workspace\\python_projects\\widget_challenge',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env\\Scripts\\python36.zip',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env\\DLLs',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env\\lib',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env\\Scripts',
 'c:\\program files\\python\\36\\Lib',
 'c:\\program files\\python\\36\\DLLs',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env',
 'C:\\Users\\joe_t\\workspace\\python_projects\\env\\lib\\site-packages']
Server time:    Sat, 21 Apr 2018 20:11:16 +0000

我不明白这个错误意味着什么;我仍然在网上寻找线索以获取线索。有没有人见过这个,也许有想法如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

@goterpsgo看起来正在为ListSerializer电话触发to_representation课程。 source="*"如何运作?我不知道这种用法。

您可以尝试将其更改为: widgetcategory = WidgetCategorySerializer(source="widget", many=True, read_only=True)