vcruvinelr
vcruvinelr

Reputation: 126

Get a list of values from another model

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

Answers (1)

bruno desthuilliers
bruno desthuilliers

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

Related Questions