使用JavaScript(TMD.js)将流派ID与流派名称匹配 [英] Matching genre ids with genre names in TMDb with JavaScript (Ember.js)
问题描述
我敢肯定,你们中的很多人已经使用了TMDb(电影数据库)API来拍摄电影。但是我在显示每部电影的流派名称时遇到问题。我试图将电影 API中的 genre_ids
中的每个数字替换为相应的名称
来自流派 api,因为向用户显示数字并不能说太多!但是我没有得到理想的结果。我不确定正确的方法是什么...
I'm sure a lot of you have used the TMDb (The Movie Database) api for movies. But I'm having issues with showing the genre names for each movie displayed. I'm trying to replace each number in genre_ids
, from movies api, with their corresponding name
from genres api, as showing numbers to users doesn't say much! But I don't get the desired result. I'm not sure what the correct way is...
电影适配器
import DS from 'ember-data';
const apiKey = 'SOME_API_KEY_HERE';
export default DS.RESTAdapter.extend({
host: `https://api.themoviedb.org/`,
namespace: '3',
pathForType() {
return `discover/movie?sort_by=popularity.desc&api_key=${apiKey}`;
},
});
类型适配器
import DS from 'ember-data';
const apiKey = 'SOME_API_KEY_HERE';
export default DS.RESTAdapter.extend({
host: `https://api.themoviedb.org/`,
namespace: '3',
pathForType() {
return `genre/movie/list?api_key=${apiKey}`;
},
});
电影序列化器
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
payload = { movies: payload.results };
return this._super(store, primaryModelClass, payload, id, requestType);
}
});
类型序列化器
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
payload = { genres: payload.genres };
return this._super(...arguments);
}
});
电影模型
import DS from 'ember-data';
const { attr, hasMany } = DS;
export default DS.Model.extend({
vote_count: attr('number'),
video: attr('boolean'),
vote_average: attr('number'),
title: attr('string'),
popularity: attr('number'),
poster_path: attr('string'),
original_language: attr('string'),
original_title: attr('string'),
genre_ids: attr(),
backdrop_path: attr('string'),
adult: attr('boolean'),
overview: attr('string'),
release_date: attr('date'),
});
类型模型
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
});
路线
import Route from '@ember/routing/route';
import RSVP from 'rsvp'
export default Route.extend({
model() {
return RSVP.hash({
movies: this.store.findAll('movie'),
genres: this.store.findAll('genre'),
});
},
});
电影列表组件
import Component from '@ember/component';
import { computed } from '@ember/object';
export default Component.extend({
movieGenreIds: computed('movies.@each.genre_ids', function() {
return this.movies.map(movie => movie.genre_ids).reduce((a, b) => [...a, ...b]);
}),
genresNames: computed('movieGenreIds', 'genres', 'movies', function() {
let names = [];
this.genres.map((genre) => {
this.movieGenreIds.forEach(movieGenreId => {
if (parseInt(genre.id) === movieGenreId) {
names.push(genre.name);
}
})
})
return names;
}),
});
Movies API (每个电影的结果
数组具有以下结构):
Movies API (each movie from the results
array has this structure):
{
"vote_count": 1092,
"id":335983,
"video": false,
"vote_average": 6.7,
"title": "Venom",
"popularity": 505.173,
"poster_path": "\/2uNW4WbgBXL25BAbXGLnLqX71Sw.jpg",
"original_language": "en",
"original_title": "Venom",
"genre_ids": [27,878,28,53,35], // <-- I'm interested in this property
"backdrop_path": "\/VuukZLgaCrho2Ar8Scl9HtV3yD.jpg",
"adult": false,
"overview": "When Eddie Brock acquires the powers of a symbiote, he will have to release his alter-ego "Venom" to save his life.",
"release_date": "2018-10-03"
}
流派API
"genres":[
{"id":28,"name":"Action"},
{"id":12,"name":"Adventure"},
{"id":16,"name":"Animation"},
{"id":35,"name":"Comedy"},
...
]
Hbs模板(预期结果)
<ul class="movie">
{{#each movies as |movie|}}
<li>
<h2 class="movie__title">{{movie.title}}</h2>
<p class="movie__genre">
genres:
{{#each genresNames as |genre|}}
{{genre}} <!-- a list of genre names for this particular movie -->
{{/each}}
</p>
<img src="https://image.tmdb.org/t/p/w500/{{movie.poster_path}}" alt="" class="movie__image">
</li>
{{/each}}
推荐答案
我认为您的主要问题是您试图修复组件层上的某些问题,而这些问题最好在模型层上进行处理。
当您可以做到这一点时,您真正想要的是从电影
模型到类型的关系
模型:
I think your primary problem is that you're trying to fix something on the component layer that is better handled on the model layer.
While you can do that, what you actually want is a relationship from the movie
model to the genre
model:
genres: hasMany('genre'),
我不确定您的API提供了1:1的内容,因为您尚未粘贴 exact 响应。在某些时候,您提到了 results
数组,并且流派似乎包裹在流派
数组中。因此,如果那不是100%正确,那么您可能需要稍微调整一下此解决方案。
I'm not sure what your API provides 1:1 because you've not pasted the exact response. At some point you've mentioned a results
array, and the genres seems to be wrapped inside a genres
array. So if thats not 100% correct you maybe need to tweak this solution a bit.
首先,我会推荐较新的 JSONSerializer
而不是 RESTSerializer
。
For the start I would recommend the newer JSONSerializer
instead of the RESTSerializer
.
现在您需要告诉余烬了类型
关系,则应使用 genre_ids
数组中提供的ID。这可以通过 keyForRelationship
:
Now you need to tell ember that for the genres
relationship it should use the ids provided in the genre_ids
array. This can be done by keyForRelationship
:
import DS from 'ember-data';
import {singularize} from 'ember-inflector';
export default DS.JSONSerializer.extend({
...
keyForRelationship(key, typeClass, method) {
return `${singularize(key)}_ids`;
},
});
在这里我使用 ember-inflector
获得关系名称的单数形式(因此 genres->体裁
),然后只需添加 _ids
。这足以使余烬识别id,然后使用它们提供正确的模型实例。
Here I use the ember-inflector
to get the singular of the relationship name (so genres -> genre
) and then just add _ids
. This is enough for ember to recognize the ids and then use them to provide the right model instances.
接下来,您基本上可以循环遍历流派
在您的电影
型号上:
Next you can basically just loop over genres
on your movie
model:
{{#each movie.genres as |genre|}}
{{genre.name}}
{{/each}}
现在,您甚至不需要将所有类型的列表传递给控制器/模板。但是,您仍然需要加载,以便 ember-data
可以使用它们。否则 ember-data
会在您使用它们时尝试分别获取它们。
Now you don't even need to pass the list of all genres to the controller/template. However you still need to load them so ember-data
can use them. Otherwise ember-data
would try to fetch them individually when you use them.
所以您的 model
钩子可能看起来像这样:
So your model
hook could look like this:
model() {
return RSVP.hash({
genres: this.store.findAll('genre'),
movies: this.store.findAll('movie'),
}).then(x => x.movies);
}
这是实现此目的的一种麻烦方式。但是,由于我不想实时获取数据,因此我创建了返回静态数据的虚拟适配器。
Here is a twiddle implementing this. However because I don't wanted to live-fetch the data I've created dummy adapters that return static data.
这篇关于使用JavaScript(TMD.js)将流派ID与流派名称匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!