Django Rest中的字符串相关字段

问题描述 投票:2回答:4

我已经实现了外键来在DRF中使用StringRelatedField获取电影的类型列表。但这在POST时不起作用。我得到StringRelatedField.to_internal_value()必须实现为错误。谁能帮我?

models.朋友

class Movies(models.Model):
    movie_id = models.AutoField(primary_key=True)
    movie_name = models.CharField(max_length =200)
    director = models.CharField(max_length = 100)
    popularity = models.FloatField(max_length = 3)
    imdb_score = models.FloatField(max_length = 10)
    def __unicode__(self):               
        return '%s%s%d%d' % (self.movie_name,self.director,self.popularity,self.imdb_score)

class Genre(models.Model):
    genre_id = models.AutoField(primary_key=True)
    movie_name =models.ForeignKey(Movies, blank=True, null=True, on_delete=models.SET_NULL,related_name='genres')
    genre = models.CharField(max_length =40)

    def __unicode__(self):
        return '%s%s' % (self.genre,self.movie_name)

views.朋友

    class MovieList(viewsets.ViewSet):
                def list(self,request):
                try:
                    movie_list = Movies.objects.all()
                    serializer = MovieSerializer(movie_list, many=True)
                    username = request.session['username']
                    user_role = request.session['role']
                    context = {'username': username, 'user_role': user_role,     'movie_list': serializer.data}
                    return render(request, 'imdb/movie-list.html', context)
                except KeyError:
                    pass
                    return  HttpResponseRedirect(reverse('imdb:login'))


    class AddMovie(APIView):

        def post(self, request, format='json'):
            data = request.data

            serializer = MovieSerializer(data =request.data)
            #print serializer
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

URLs.朋友

urlpatterns = patterns('',
        url(r'^$', views.login, name='login'),
         url(r'^home/$', views.home, name='home'), 
         url(r'^logout/$', views.logout, name='logout'),
         url(r'^movie-list/$', views.MovieList.as_view({'get':'list'}),name ='movie-list'),
         url(r'^add-movie/$', views.AddMovie.as_view(),name ='add-movie') )

serialize人.朋友

    class MovieSerializer(serializers.ModelSerializer):
        genres = serializers.StringRelatedField(many=True)
        class Meta:
            model = Movies
            fields = ('movie_name','director','popularity','imdb_score','genres')
python django post django-rest-framework
4个回答
5
投票

StringRelatedField是只读的。我不得不使用嵌套的serilaizers。


3
投票
class GenreSerializer(serializers.ModelSerializer):
    class Meta:
        model = Genre
        fields =('genre',) 

class MovieSerializerList(serializers.ModelSerializer):

    genres = GenreSerializer(many=True)
    class Meta:
         model = Movies
         fields = ('movie_name','director','popularity','imdb_score','genres')

1
投票
class WordListingField(serializers.StringRelatedField):
    def to_internal_value(self, value):
        return value

另一种方法是实施to_internal_value()。但是我同意作者的意见。我只是因为我们项目中存在技术债务而不情愿地实施了这一点。


0
投票

这就是我所做的,但我认为这取决于具体情况。

class SectorClass(models.Model):
    name = models.CharField(max_length=250, unique=True)
    description = models.TextField(null=True, blank=True)
    author = models.ForeignKey(Account, null=True, related_name='sector_class', on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('common:sector_detail', args=[self.pk])


class Sector(models.Model):
    sector_class = models.ManyToManyField(SectorClass, related_name='sector')
    name = models.CharField(max_length=250)
    author = models.ForeignKey(Account, null=True, related_name='sector', on_delete=models.CASCADE)
    description = models.TextField(null=True, blank=True)
    status = models.CharField(max_length=10, choices=LEVELS, default='draft')
    nis = models.BooleanField(default=False)
    constituent = models.BooleanField(default=False)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('common:sector_detail', args=[self.pk])

序列化器看起来像这样:

class SectorClassField(serializers.StringRelatedField):

def to_internal_value(self, value):
    sector_class = models.SectorClass.objects.filter(name=value)
    if sector_class and (len(sector_class)) == 1:
        return sector_class.get().id
    else:
        raise serializers.ValidationError("Sector with name: %s not found" % value)

class SectorSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(
                view_name="common:sector-detail",
                )

    sector_class = SectorClassField(many=True)
    class Meta:
        model = models.Sector
        fields = ('__all__')
© www.soinside.com 2019 - 2024. All rights reserved.