Modelserializer使用kwargs获取FK对象

时间:2016-05-18 08:01:45

标签: django django-rest-framework

我创建了一个Django(1.8)webapp,可以保存赛车游戏和记分牌。使用使用Django Rest Framework构建的API填充数据库。这是我第一次尝试使用rest框架构建一个合适的api。

模型的快速概述:

  • 活动,赛车活动/周末
  • 会话,单一种族/练习/质量 - FK活动
  • 汽车,参加会议的汽车 - FK会议
  • 圈数,特定车型的小费 - FK Car

事件是手动创建的,但其余部分应该是"动态" (获取或创建)

现在我正在尝试使用我的API创建一款新车,但我被卡住了。为了获得汽车活动和会议,我试图使用网址; / API /结果/ skrotbilsracet-29042016 / R1 /汽车/

我们的想法是将数据发布到此网址,并获取或创建"一个新的汽车对象。 为了获得新车会话FK的正确会话对象,我需要使用一个自定义函数来获取kwargs并尝试查找会话。

我越了解如何解决这个问题,我就越感到困惑。

有人能把我推向正确的方向吗?

这是我最近尝试解决这个问题,这只是给了我" {"会话":["此字段是必需的。"]}"

models.py

class Session(models.Model):
    session_types = (
        ('p', 'Practice'),
        ('q', 'Qualification'),
        ('r', 'Race')
    )
    event_id = models.ForeignKey(Event, related_name='sessions')
    name = models.CharField(max_length=2, blank=True)
    current_session = models.BooleanField(default=True)
    session_type = models.CharField(max_length=2,
                                    choices=session_types)
    started = models.DateTimeField(auto_now_add=True)
    ended = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['started']

    def save(self):
        if not self.name:
            # Get number of sessions
            session_count = Session.objects.filter(event_id=self.event_id)\
                            .filter(session_type=self.session_type)\
                            .count()
            session_count += 1
            self.name = self.session_type + str(session_count)

        super(Session, self).save()

    def __unicode__(self):
        string = self.started.strftime("%d-%m-%Y %H:%M") + ' - '
        string += self.name.upper()
        return(string)


class Car(models.Model):
    session = models.ForeignKey(Session, related_name='cars')
    number = models.IntegerField()
    full_name = models.CharField(max_length=256, blank=True)
    short_name = models.CharField(max_length=256, blank=True)
    race_class = models.CharField(max_length=50, blank=True)
    best_lap = models.IntegerField(blank=True, null=True)
    best_lap_time = models.CharField(max_length=20, blank=True)
    best_sector1 = models.CharField(max_length=20, blank=True)
    best_sector2 = models.CharField(max_length=20, blank=True)
    best_sector3 = models.CharField(max_length=20, blank=True)
    best_speed = models.IntegerField(blank=True, null=True)
    pitstops = models.IntegerField(blank=True, null=True)
    total_time = models.CharField(max_length=20, blank=True)
    transponder = models.CharField(max_length=50, blank=True)

apiUrls.py

urlpatterns = [
  url(r'^raceslug/$', raceSlugView.as_view(), name='race-slug'),
  url(r'^events/$', eventsView.as_view(), name='event-list'),
  url(r'^session/$', getSessionView.as_view(), name='session-pk'),
  url(r'^(?P<event_id>[a-z0-9\-]+)/$', eventView.as_view(), name='event-detail'),
  url(r'^(?P<event_id>[a-z0-9\-]+)/(?P<name>[a-z0-9\-]+)/$', sessionView.as_view(), name='session-detail'),
  url(r'^(?P<event_id>[a-z0-9\-]+)/(?P<name>[a-z0-9\-]+)/cars/$', carsView.as_view(), name='car-list'),
  url(r'^(?P<event_id>[a-z0-9\-]+)/(?P<name>[a-z0-9\-]+)/(?P<number>[0-9]+)/$', carView.as_view(), name='car-detail'),
]

urlpatterns = format_suffix_patterns(urlpatterns)

api.py

class carsView(generics.ListCreateAPIView):
    serializer_class = carSerializer

    def get_session(self, event_id, name):
        print('Getting session')
        # Get event object
        try:
            event = Event.objects.get(event_id=event_id)
            print('Found event')
        except ObjectDoesNotExist:
            print('Did not find event')
            return

        # Get session object
        try:
            session = event.sessions.get(name=name)
            print('Found session: ', session)
            return session
        except ObjectDoesNotExist:
            print('Did not find session')
            return


    def get_queryset(self):
        print('Getting queryset')
        print('event_id: ' + self.kwargs['event_id'])
        print('name: ' + self.kwargs['name'])
        session = self.get_session(self.kwargs['event_id'], self.kwargs['name'])
        return(Car.objects.filter(session=session.pk))


    def perform_create(self, serializer):
        print('Creating new car')
        session = self.get_session(self.kwargs['event_id'], self.kwargs['name'])
        serializer.save(session=session)

serializers.py

class carSerializer(serializers.ModelSerializer):

  laps = lapSerializer(many=True, read_only=True)

  class Meta:
    model = Car
    fields = (
        'session',
        'number',
        'full_name',
        'short_name',
        'race_class',
        'best_lap',
        'best_lap_time',
        'best_sector1',
        'best_sector2',
        'best_sector3',
        'best_speed',
        'pitstops',
        'total_time',
        'transponder',
        'laps')

解决方案:
这就是我实际改变它以使其正常工作。

api.py

from rest_framework.serializers import ValidationError

class carsView(generics.ListCreateAPIView):
...
    def perform_create(self, serializer):
        print('Creating new car')
        session = self.get_session(self.kwargs['event_id'], self.kwargs['name'])
        number = self.request.POST.get('number')
        car = session.cars.filter(number=number)
        if car.exists():
            raise ValidationError('Car already exists')
        serializer.save(session=session)

serializers.py

class carSerializer(serializers.ModelSerializer):

    laps = lapSerializer(many=True, read_only=True)
    session = serializers.StringRelatedField(required=False)
    ...

1 个答案:

答案 0 :(得分:0)

我看到你在那里创建会话ID:

def get_queryset(self):
       ...
        session = self.get_session(self.kwargs['event_id'], self.kwargs['name'])
        return(Car.objects.filter(session=session.pk))

然后,您不需要在序列化程序中,仅在模型中。因此,您可以将其设置为序列化程序中所需的鼻涕,但在模型中仍然需要它。

我想这个答案可以帮到你:Django REST Framework serializer field required=false