Tenha cuidado para perceber que existem algumas diferenças entre OneToOneField(SomeModel)
e ForeignKey(SomeModel, unique=True)
. Conforme declarado no Guia Definitivo do Django :
OneToOneField
Um relacionamento individual. Conceitualmente, isso é semelhante a um ForeignKey
com unique=True
, mas o lado "reverso" da relação retornará diretamente um único objeto.
Em contraste com a relação OneToOneField
"reversa", uma relação ForeignKey
"reversa" retorna a QuerySet
.
Exemplo
Por exemplo, se tivermos os dois modelos a seguir (código completo do modelo abaixo):
Car
modelo usa OneToOneField(Engine)
Car2
modelo usa ForeignKey(Engine2, unique=True)
De dentro, python manage.py shell
execute o seguinte:
OneToOneField
Exemplo
>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKey
com unique=True
exemplo
>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]
Código de modelo
from django.db import models
class Engine(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=25)
engine = models.OneToOneField(Engine)
def __unicode__(self):
return self.name
class Engine2(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car2(models.Model):
name = models.CharField(max_length=25)
engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)
def __unicode__(self):
return self.name
e.car
também funcione?ForeignKey
comunique=True
e não umOneToOneField
? Vejo em outras perguntas que o Django até adverte queOneToOneField
os interesses de quem geralmente serve melhor. O inversoQuerySet
nunca terá mais de um elemento, certo?Uma ForeignKey é para um para muitos, portanto, um objeto Car pode ter muitas Rodas, cada Roda tendo uma ForeignKey no Carro ao qual pertence. Um OneToOneField seria como um mecanismo, onde um objeto Car pode ter um e apenas um.
fonte
A melhor e a maneira mais eficaz de aprender coisas novas é ver e estudar exemplos práticos do mundo real. Suponha por um momento que você queira criar um blog no django onde os repórteres possam escrever e publicar artigos de notícias. O proprietário do jornal on-line quer permitir que cada um de seus repórteres publique quantos artigos quiser, mas não quer que repórteres diferentes trabalhem no mesmo artigo. Isso significa que, quando os leitores lerem um artigo, verão apenas um autor no artigo.
Por exemplo: Artigo de John, Artigo de Harry, Artigo de Rick. Você não pode ter o artigo de Harry & Rick porque o chefe não deseja que dois ou mais autores trabalhem no mesmo artigo.
Como podemos resolver esse 'problema' com a ajuda do django? A chave para a solução desse problema é o django
ForeignKey
.A seguir, está o código completo que pode ser usado para implementar a ideia do nosso chefe.
Execute
python manage.py syncdb
para executar o código sql e criar as tabelas para o seu aplicativo no seu banco de dados. Em seguida, usepython manage.py shell
para abrir um shell python.Crie o objeto Reporter R1.
Crie o objeto de artigo A1.
Em seguida, use o seguinte trecho de código para obter o nome do repórter.
Agora crie o objeto Reporter R2 executando o seguinte código python.
Agora tente adicionar R2 ao objeto Artigo A1.
Ele não funciona e você receberá um AttributeError dizendo que o objeto 'Reporter' não tem atributo 'add'.
Como você pode ver, um objeto Artigo não pode estar relacionado a mais de um objeto Reporter.
E o R1? Podemos anexar mais de um objeto de artigo a ele?
Este exemplo prático nos mostra que o django
ForeignKey
é usado para definir relacionamentos muitos-para-um.OneToOneField
é usado para criar relacionamentos um a um.Podemos usar
reporter = models.OneToOneField(Reporter)
o arquivo models.py acima, mas não será útil em nosso exemplo, pois um autor não poderá postar mais de um artigo.Sempre que você desejar publicar um novo artigo, será necessário criar um novo objeto Reporter. Isso consome tempo, não é?
Eu recomendo tentar o exemplo com o
OneToOneField
e perceber a diferença. Tenho certeza de que, após este exemplo, você saberá completamente a diferença entre djangoOneToOneField
e djangoForeignKey
.fonte
O OneToOneField (um para um) realiza, na orientação a objetos, a noção de composição, enquanto ForeignKey (um para muitos) se refere à agregação.
fonte
Patient
eOrgan
.Patient
pode ter muitosOrgan
s, mas umOrgan
pode pertencer a apenas umPatient
. QuandoPatient
é excluído, todos osOrgan
s também são excluídos. Eles não podem existir sem aPatient
.Também
OneToOneField
é útil para ser usado como chave primária para evitar duplicação de chave. Pode-se não ter autofield implícito / explícitomas use
OneToOneField
como chave primária (imagine oUserProfile
modelo por exemplo):fonte
Quando você acessa um OneToOneField, obtém o valor do campo consultado. Neste exemplo, o campo 'title' do modelo de livro é um OneToOneField:
Ao acessar uma ForeignKey, você obtém o objeto de modelo relacionado, com o qual você pode realizar outras consultas. Neste exemplo, o campo 'publicador' do mesmo modelo de livro é uma ForeignKey (correlacionada à definição do modelo de classe do Publisher):
Com os campos ForeignKey, as consultas também funcionam de outra maneira, mas são ligeiramente diferentes devido à natureza não simétrica do relacionamento.
Nos bastidores, book_set é apenas um QuerySet e pode ser filtrado e fatiado como qualquer outro QuerySet. O nome do atributo book_set é gerado anexando o nome do modelo em minúsculas a _set.
fonte
OneToOneField: se a segunda tabela estiver relacionada com
table2 conterá apenas um registro correspondente ao valor pk da tabela1, ou seja, table2_col1 terá um valor único igual a pk da tabela
A tabela2 pode conter mais de um registro correspondente ao valor de pk da tabela1.
fonte
ForeignKey permite que você receba subclasses. É a definição de outra classe, mas o OneToOneFields não pode fazer isso e não é acoplável a várias variáveis.
fonte