首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django DRF外键

问Django DRF外键
EN

Stack Overflow用户
提问于 2018-10-11 15:58:38
回答 1查看 400关注 0票数 0

这个问题或许多类似的问题已经被问了很多次,但由于某种原因,我找不到答案。

我确实在一定程度上做到了这一点,如果你进入api页面,它可以毫无问题地渲染、创建和更新。问题是显示嵌套对象中的字段(标题),而不仅仅是前端的主键。

在进入代码之前,先了解一些背景知识:

Race1是一个有限的列表(例如Race1,Race2,Race3),前端没有能力添加更多。

卡片不是有限的,但每张卡片必须链接到一个现有的种族(这目前是通过主键来做到的)。

前端应显示链接种族的card_text和种族标题。它也有能力添加一个新的卡,但这工作得很好。

我已经使用了读取和创建/更新的单独序列化程序,其中读取有一个'depth = 1‘来遍历整个对象,但创建/更新没有,然后解析对象并返回主键(我在序列化程序中找不到这样做的方法,这可能吗?)。

所以基本上我的问题是,你是打算传递整个对象并在POST方法上解析它,还是传递主键并拉入链接的对象(比赛)并使用主键作为索引(例如Racescard_race)。另外,为什么“linked_race”没有出现在前端?

我意识到我几乎已经回答了我自己的问题,但由于我是Django的新手,我正在寻找正确的约定,谁知道呢,这可能会节省其他人在搜索相同答案时的时间。

urls.py

代码语言:javascript
复制
from .api import CardViewSet, RaceViewSet
from rest_framework.routers import DefaultRouter
from django.conf.urls import url, include
from .views import landing

router = DefaultRouter()
router.register(r'cards', CardViewSet)
router.register(r'races', RaceViewSet)

urlpatterns = [
    url(r'^$', landing),
    url(r'^api/', include(router.urls)),
]

api.py

代码语言:javascript
复制
from rest_framework.viewsets import ModelViewSet
from .serializers import CardSerializer, RaceSerializer
from .models import Card, Race


class CardViewSet(ModelViewSet):
    queryset = Card.objects.filter(active=True)

    def get_serializer_class(self):
        return CardSerializer

    def perform_create(self, serializer):
        serializer.save(creator=self.request.user)


class RaceViewSet(ModelViewSet):
    queryset = Race.objects.filter(active=True)
    serializer_class = RaceSerializer

models.py

代码语言:javascript
复制
from django.db import models
from django.conf import settings

User = settings.AUTH_USER_MODEL

class Race(models.Model):
    id = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=30, blank=False)
    active = models.BooleanField(default=True)

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

    def __unicode__(self):
        return self.title


class Card(models.Model):
    card_text = models.CharField(max_length=100, blank=False)
    card_description = models.CharField(max_length=100, blank=True)
    card_race = models.ForeignKey(Race, related_name='linked_race', on_delete=models.CASCADE)
    creator = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.card_text

    class Meta:
        ordering = ('created',)

serializers.py

代码语言:javascript
复制
from rest_framework import serializers
from .models import Card, Race


class RaceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Race
        fields = '__all__'


class CardSerializer(serializers.ModelSerializer):
    linked_race = RaceSerializer(read_only=True, many=True)

    class Meta:
        model = Card
        fields = 'id', 'card_text', 'card_description', 'card_race', 'linked_race',

Javascript提取(AngularJS)

代码语言:javascript
复制
$http.get('/api/races/').then(function (response) {
  $scope.races = response.data;
  $scope.selectedOption = $scope.races[0];
});
$scope.cards = [];
$http.get('/api/cards/').then(function (response) {
  $scope.cards = orderBy(response.data, 'created', true);
});

超文本标记语言摘要(AngularJS)

代码语言:javascript
复制
<div class="races--row" ng-repeat="c in cards | filter : card_filter |
orderBy : sortVal : sortDir" ng-class-odd="'odd'" ng-click="openModal(c)"> 

<div class="races--cell race">{{ c.card_race.title }}</div> 
<div class="races--cell card-text">{{ c.card_text }}</div> 

</div>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-12 08:31:06

您的第一个“问题”是Card模型(我之所以说“问题”,是因为我不认为您有意这样做)。您正在为card_race字段定义related_name='linked_race'。此是您用来指代a race中的卡的名称。

我建议你省略它,使用Django已经提供给我们的默认值(也就是本例中的my_race.card_set.all() )。因此将Card模型中字段更改为:

代码语言:javascript
复制
class Card(models.Model):
    ...
    card_race = models.ForeignKey(Race, on_delete=models.CASCADE)
    ...

让我们将卡片序列化程序更改为:

代码语言:javascript
复制
class CardSerializer(serializers.ModelSerializer):
    # no more linked_race
    class Meta:
        model = Card
        fields = ('id', 'card_text', 'card_description', 'card_race')

好了,这是一个不同的基本模型序列化程序,你还看不到比赛的细节。现在让我们来看看你的主要问题,那就是你想:

  • 查看卡的相关竞争的详细信息
  • 使用相同的序列化程序

执行创建/获取/更新/删除操作

为此,让我们进一步更改CardSerializer以包含另一个名为race_detail的字段

代码语言:javascript
复制
class CardSerializer(serializers.ModelSerializer):
    race_detail = RaceSerializer(source='card_race', read_only=True)

    class Meta:
        model = Card
        fields = ('id', 'card_text', 'card_description', 'card_race', 'race_detail')

我们为相同的模型字段定义了两个序列化字段。注意source和read_only属性。这使得这个字段在你得到卡片时可用(这是我们想要的),而不是当你执行POST或but时(这避免了发送整个比赛对象和解析等问题)。您只需发送card_race字段的比赛id,它就会起作用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52755050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档