0

I am trying to accomplish something very similar to: How to join 3 tables in query with Django

Essentially, I have 3 tables. In the Django REST we are showing table 3. As you see below (models.py), table 3 has company_name which is a foreign key of table 2 and table 2 is a foreign key of table 1. Both table 2 and 3 are linked by the table 1 ID. Table 1 contains the actual text, which we want to display in the API output, not the ID number.

Table 1: Manufacturer of Car -- Table 2: What the Car is -- Table 3: list of all cars

Models.py

Table 1:
class ManufacturerName(models.Model):
    name_id = models.AutoField(primary_key=True)
    company_name = models.CharField(unique=True, max_length=50)

    class Meta:
        managed = False
        db_table = 'manufacturer_name'

Table 2:
    class CarBuild(models.Model):
        car_id = models.AutoField(primary_key=True)
        car_icon = models.CharField(max_length=150, blank=True, null=True)
        company_name = models.ForeignKey('ManufacturerName', models.DO_NOTHING, db_column='ManufacturerName') 

        class Meta:
              managed = False
              db_table = 'car_build'

Table 3:
class CarList(models.Model):
    list_id = models.AutoField(primary_key=True)
    company_name = models.ForeignKey('CarBuild', models.DO_NOTHING, db_column='CarBuild')
    title = models.CharField(unique=True, max_length=100)
    description = models.TextField()


    class Meta:
        managed = False
        db_table = 'cars'

Within my views: This is what I am trying, based on the foreign key relationships:

queryset = CarList.objects.all().select_related('company_name__company_name')

I get no errors when I save and run this, however, the ID is still being returned, and not the text associated with the foreign key relationships:

[
    {
        "list_id": 1,
        "company_name": "http://127.0.0.1:8000/api/1/",
        "title": "Really fast car you're driving, and this is dummy text",

Again, I would like to achieve getting the text associated with the company_name foreign key relationships from table 1 to show in the JSON.

serializer and viewset

class manufacturer_name(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = manufacturer_name
        fields = ('name_id', 'company_name')

class manufacturer_name(viewsets.ModelViewSet):

    queryset = manufacturer_namee.objects.all()
    serializer_class = manufacturer_name


class CarBuildViewSet(viewsets.ModelViewSet):

    queryset = CarBuild.objects.all()
    serializer_class = CarBuildSerialiser

class CarBuildSerialiser(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = CarBuild
        fields = ('car_id', 'car_icon', 'company_name')


class CarListSerialiser(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = News
        fields = ('list_id', 'company_name', 'title')


class CarListViewSet(viewsets.ModelViewSet):
    serializer_class = CarList
    def get_queryset(self):
        queryset = News.objects.all().select_related('company_name__company_name')
    return queryset
dataviews
  • 2,466
  • 7
  • 31
  • 64

1 Answers1

1

Based on detailed conversation to clear few details. Here is the answer.

You need to make small changes to your models as it was quite confusing to understand what you want to achieve.

Models:

class ManufacturerName(models.Model):
    name_id = models.AutoField(primary_key=True)
    company_name = models.CharField(unique=True, max_length=50)

    class Meta:
        managed = False
        db_table = 'manufacturer_name'


class CarBuild(models.Model):
    car_id = models.AutoField(primary_key=True)
    car_icon = models.CharField(max_length=150, blank=True, null=True)
    manufacturer = models.ForeignKey(ManufacturerName,on_delete=models.SET_NULL) 

    class Meta:
          managed = False
          db_table = 'car_build'


class CarList(models.Model):
    list_id = models.AutoField(primary_key=True)
    car = models.ForeignKey(CarBuild, on_delete=models.DO_NOTHING)
    title = models.CharField(unique=True, max_length=100)
    description = models.TextField()

    class Meta:
       managed = False
       db_table = 'cars'

And then You need to adjust your serializers.

class CarListSerialiser(serializers.HyperlinkedModelSerializer):

    company_name= serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CarList
        fields =  ('list_id', 'company_name', 'title')

    def get_company_name(self, obj):
        return obj.car.manufacturer.company_name

And you use it in your view:

class CarListViewSet(viewsets.ModelViewSet):
    queryset = CarList.object.all()
    serializer_class = CarListSerialiser
Enthusiast Martin
  • 3,041
  • 2
  • 12
  • 20
  • where is the second option? – dataviews Jul 13 '18 at 19:35
  • you have both there , one is company_name_1 and second one is company_name_2 – Enthusiast Martin Jul 13 '18 at 19:58
  • Just to confirm, I am trying to show the text being stored in the primary key table in company_name. The SQL equivalent would be an inner join – dataviews Jul 13 '18 at 20:01
  • you just want to display the ID ? i think that you want to see the company_name from ManufacturerName model, no ? – Enthusiast Martin Jul 13 '18 at 20:02
  • That's exactly what I'm trying to do. I want to see the company_name text being stored in table 1 (manufacturer_name)...Table 2 (carbuild) and Table 3 (carlist) are related to table 1 by the ID. I want to show the text instead of the ID within the API framework. So in otherwords, the user is seeing the actual company name, not the ID – dataviews Jul 13 '18 at 20:05
  • The actual text? That is being stored in the view: manufacturer_name --- the data that is always being displayed / rendered through the API is CarListViewSet – dataviews Jul 13 '18 at 20:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174966/discussion-between-enthusiast-martin-and-dataviews). – Enthusiast Martin Jul 13 '18 at 20:11