Reputation: 126
I installed a third party app which has basically 5 fields: id, name, state, geocode, geometry.
I created a new app which I need to import only the values from the 'name' field from the other model.
So I basically did this:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.gis.geos import Point
from brasil_municipios.models import Municipio #which is the third party app
class Escritorio(models.Model):
nomeescritiorio = models.CharField(max_length=255)
cidade = models.OneToOneField(Municipio.objects.values_list('name').order_by('name')[0:10], on_delete=models.PROTECT, null=True)
And got this error:
AssertionError: OneToOneField(<QuerySet [('ABADIA DE GOIÁS',), ('ABADIA DOS DOURADOS',), ('ABADIÂNIA',), ('ABAETETUBA',), ('ABAETÉ',), ('ABAIARA',), ('ABARÉ',), ('ABATIÁ',), ('ABAÍRA',), ('ABDON BATISTA',)]>) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'
I already tried others ways to solve the issue, using filter(), get() and etc, but all get the same error in all of them.
Upvotes: 1
Views: 1514
Reputation: 77902
I created a new app which I need to import only the values from the 'name' field from the other model.
You don't "import the values from another model" - that's not how it works. What you do is link models together so that the underlying "escritorio" table records know the primary key of the "municipio" table record they are related to (that's what the OneToOneField
is doing actually). Then, from the foreign key stored in "escritorio", you can read the related "municipio" record's "name" value.
IOW, you just pass the related model's name to the OneToOne
field, and then you can get the related Municipio name from an Escritorio
instance just following the relationship, ie escrotorio.cidade.name
.
If you most often need to use this value when working with Escritorio
models, you can optimize for readability by adding a read-only property to Escritorio
:
class Escritorio(models.Model):
nomeescritiorio = models.CharField(max_length=255)
cidade = models.OneToOneField(Municipio, on_delete=models.PROTECT)
@property
def name(self):
return self.cidade.name
which allows you to just write escritorio.name
(simple shortcut, really)
AND you certainly want to optimize for performances by forcing the ORM to always load the related municipio
values when loading escritorio
so you have everything in a single db query instead of needing one query to get the escritorio
and a second for the related municipio
. You do this by using select_related()
, either directly when you know you'll need the names, or systematically by providing a custom manager and queryset class for your Escritorio
model.
NB: you will of course have to create escritorio instances for each of the municipio record you're interested in - neither django nor your rdmbs will automagically do this for you.
Upvotes: 1