我已经使用外键在DRF中使用StringRelatedField获取电影类型列表。但这在POST时不起作用。 我得 StringRelatedField.to_internal_value()必须实现作为错误。 任何人都可以帮助我吗?
models.py
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.py
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.py
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') )
serializer.py
class MovieSerializer(serializers.ModelSerializer):
genres = serializers.StringRelatedField(many=True)
class Meta:
model = Movies
fields = ('movie_name','director','popularity','imdb_score','genres')
答案 0 :(得分:5)
StringRelatedField是只读的。我不得不使用嵌套的序列化器。
答案 1 :(得分: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')
答案 2 :(得分:1)
class WordListingField(serializers.StringRelatedField):
def to_internal_value(self, value):
return value
另一种方法是实施to_internal_value()
。
但是我同意作者的意见。由于我们项目中存在技术债务,我不情愿地实施了这一点。
答案 3 :(得分: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__')