Para que o `related_name` é usado no Django?

391

Qual é o related_nameargumento útil para on ManyToManyFielde ForeignKeyfields? Por exemplo, dado o código a seguir, qual é o efeito related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
fonte
12
@DanielRoseman De alguma forma, é bom para o desempenho ou as boas práticas usar related_name = '+' quando a relação inversa não é necessária?
Lajarre 25/10/12
10
Gostaria de saber a resposta para a pergunta de @ lajarre.
3cheesewheel
11
@ lajarre - Presumo que não mude o desempenho. Eu tive que usá-lo uma vez com os tipos de conteúdo FeinCMS. Pessoalmente, acho que é uma boa prática especificar sempre o related_namemodo. Se você sabe que não vai usá-lo, acho que é uma coisa boa. Essa é uma opinião pessoal, é claro.
François Constant
@ 3cheesewheel é nos docs agora: docs.djangoproject.com/en/2.0/ref/models/fields/... + meios não criam relação inversa
P. Myer Nore

Respostas:

531

O related_nameatributo especifica o nome da relação reversa do Usermodelo para o seu modelo.

Se você não especificar a related_name, o Django criará automaticamente uma usando o nome do seu modelo com o sufixo _set, por exemplo User.map_set.all().

Se você não especificar, por exemplo, related_name=mapsno Usermodelo, User.map_setcontinuará a funcionar, mas a User.maps.sintaxe é, obviamente, um pouco mais limpo e menos desajeitado; por exemplo, se você tiver um objeto de usuário current_user, poderá usar current_user.maps.all()para obter todas as instâncias do seu Mapmodelo que tenham uma relação current_user.

A documentação do Django tem mais detalhes.

Wogan
fonte
11
Ok, eu sei que este é um post antigo. Mas estou apenas tentando descobrir isso - qual é o truque + no final do nome relacionado? Por exemplo, o que acontece se eu fiz related_name='maps+'no exemplo acima?
Sidd
10
se você adicionar o +, o django desabilitará o mapeamento
josephmisiti
5
para o OneToOneField, o padrão related_name será o nome da classe de maiúsculas e minúsculas. Por exemplo, no exemplo dado, se os membros forem OneToOnefield, o "User.map" funcionará.
Ancho
se você especificar related_name, _setainda funciona em django1.11 >??
Esir Kings
9
Eu uso o Django 2.1.3 e posso notar que eles são exclusivos. Uma vez related_nameespecificado, _setnão funciona mais.
stockersky
84

Para adicionar um nome relacionado à resposta existente, é necessário que haja 2 FKs no modelo que apontam para a mesma tabela. Por exemplo, no caso de lista técnica

@with_author 
class BOM(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tomaterial =  models.ForeignKey(Material, related_name = 'tomaterial')
    frommaterial =  models.ForeignKey(Material, related_name = 'frommaterial')
    creation_time = models.DateTimeField(auto_now_add=True, blank=True)
    quantity = models.DecimalField(max_digits=19, decimal_places=10)

Então, quando você precisar acessar esses dados, poderá usar apenas nomes relacionados

 bom = material.tomaterial.all().order_by('-creation_time')

Não está funcionando de outra forma (pelo menos não pude usar o nome relacionado no caso de 2 FKs na mesma tabela.)

Ilya Bibik
fonte
2
Você precisa escolher um nome relacionado pelo menos para um deles. O outro não exige necessariamente.
Csaba Toth
32
related_namedeve ser plural. Porque as relações ForeignKey retornam vários objetos.
Mesut Tasci
11

O related_nameargumento também é útil se você tiver nomes de classes relacionados mais complexos. Por exemplo, se você tiver um relacionamento de chave estrangeira:

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User) 

Para acessar UserMapDataFrameobjetos do relacionado User, a chamada padrão seria User.usermapdataframe_set.all(), o que é bastante difícil de ler.

O uso de related_namepermite especificar um nome mais simples ou legível para obter a relação inversa. Nesse caso, se você especificar user = models.ForeignKey(User, related_name='map_data'), a chamada será então User.map_data.all().

Daniel Holmes
fonte
3

O parâmetro de nome relacionado é realmente uma opção. Se não o definirmos, o Django criará automaticamente o outro lado da relação para nós. No caso do modelo Map, o Django teria criado um map_setatributo, permitindo o acesso m.map_setno seu exemplo (estou sendo sua instância de classe). A fórmula que o Django usa é o nome do modelo seguido pela string _set. O parâmetro name relacionado simplesmente substitui o padrão do Django em vez de fornecer um novo comportamento.

Abrar
fonte
0

prefetch_relateduse para pré-buscar dados para Muitos para muitos e muitos para um dado de relacionamento. select_relatedé selecionar dados de um único relacionamento de valor. Ambos são usados ​​para buscar dados de seus relacionamentos de um modelo. Por exemplo, você constrói um modelo e um modelo que tem um relacionamento com outros modelos. Quando uma solicitação chega, você também consulta seus dados de relacionamento e o Django possui mecanismos muito bons. Para acessar dados do relacionamento, como book.author.namequando você itera uma lista de modelos para buscar seus dados de relacionamento, o Django cria cada solicitação para todos os dados de relacionamento. Para superar isso, temos prefetchd_relatedeselected_related

Jamil Noyda
fonte