BRHSM
BRHSM

Reputation: 884

Why am I unable to access foreign key information in django templates.

I'm working on a django app that needs to create XML files to respond to requests. I've go my models setup like this:

# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey has `on_delete` set to the desired behavior.
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models


class Color(models.Model):
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', unique=True, max_length=255)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_Colors'

    def __str__(self):
        return "Color: [" + self.id.__str__() + ", " + self.name + "] "


class Company(models.Model):
    orders = models.ManyToManyField('Order', through='OrderCompany')
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', max_length=255, blank=True, null=True)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_Companies'

    def __str__(self):
        return "Company:[" + self.orders.__str__() + ", " + self.id.__str__() + ", " + self.name + "] "


class ModelColor(models.Model):
    color = models.ForeignKey(Color, models.DO_NOTHING, db_column='ColorID')
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_ModelColors'

    def __str__(self):
        return "ModelColor:[" + self.color + ", " + self.id.__str__() + "] "


class ModelData(models.Model):
    colors = models.ManyToManyField('Color', through='ModelDataColor')
    sizes = models.ManyToManyField('Size', through='ModelDataSize')
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', max_length=255)  # Field name made lowercase.
    descript = models.CharField(db_column='Descript', max_length=2047, blank=True, null=True)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_ModelData'

    def __str__(self):
        return "ModelData:[" + self.colors.__str__() + ", " + self.sizes.__str__() + ", " + self.id.__str__() + ", " + self.name + ", " + self.descript + ", " + "] "


class Modeldatacolor(models.Model):
    model_data = models.ForeignKey(ModelData, models.DO_NOTHING, db_column='ModelDataID', primary_key=True)
    color = models.ForeignKey(Color, models.DO_NOTHING, db_column='ColorID')

    class Meta:
        managed = False
        db_table = 'Data_ModelDataColors'
        unique_together = (('model_data', 'color'),)

    def __str__(self):
        return "Modeldatacolor:[" + self.model_data.__str__() + ", " + self.color.__str__() + "] "


class Modeldatasize(models.Model):
    model_data = models.ForeignKey(ModelData, models.DO_NOTHING, db_column='ModelDataID', primary_key=True)
    size = models.ForeignKey('Size', models.DO_NOTHING, db_column='SizeID')

    class Meta:
        managed = False
        db_table = 'Data_ModelDataSizes'
        unique_together = (('model_data', 'size'),)

    def __str__(self):
        return "Modeldatasize:[" + self.model_data.__str__() + ", " + self.size.__str__() + "] "

class Modelsize(models.Model):
    color = models.ForeignKey(ModelColor, models.DO_NOTHING, db_column='ColorID')
    size = models.ForeignKey('size', models.DO_NOTHING, db_column='SizeID')
    amount = models.IntegerField(db_column='Amount')  # Field name made lowercase.
    amountfinished = models.IntegerField(db_column='AmountFinished')  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_ModelSizes'

    def __str__(self):
        return "Modelsize:[" + self.color.__str__() + ", " + self.size.__str__() + ", " + self.amount+ ", " + self.amountfinished + "] "


class Model(models.Model):
    model_color = models.ForeignKey(ModelColor, models.DO_NOTHING, db_column='ModelColorID')
    order = models.ForeignKey('Order', models.DO_NOTHING, db_column='OrderID')
    model_data = models.ForeignKey(ModelData, models.DO_NOTHING, db_column='ModelDataID')
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_Models'

    def __str__(self):
        return "Model:[" + self.model_color.__str__() + ", " + self.order.__str__() + ", " + self.model_data.__str__() + ", " + self.id.__str__() + "] "


class Ordercompany(models.Model):
    order = models.ForeignKey('Order', models.DO_NOTHING, db_column='OrderID', primary_key=True)
    company = models.ForeignKey(Company, models.DO_NOTHING, db_column='CompanyID')
    stage_number = models.IntegerField(db_column='StageNumber')

    class Meta:
        managed = False
        db_table = 'Data_OrderCompanies'
        unique_together = (('order', 'company'),)

    def __str__(self):
        return "Ordercompany:[" + self.order.__str__() + ", " + self.company.__str__() + ", " + self.stage_number + "] "

class Order(models.Model):
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.
    ordertimestamp = models.DateTimeField(db_column='OrderTimeStamp', blank=True, null=True)  # Field name made lowercase.
    finishtimestamp = models.DateTimeField(db_column='FinishTimeStamp', blank=True, null=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', max_length=255)  # Field name made lowercase.
    confirmed = models.IntegerField(db_column='Confirmed')  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_Orders'

    def __str__(self):
        self.ordertimestamp = "None"
        self.finishtimestamp = "None"
        return "Order:[" + self.id.__str__() + ", " + self.ordertimestamp + ", " + self.finishtimestamp + ", " + self.name + ", " + self.confirmed.__str__() + "] "

class Size(models.Model):
    id = models.AutoField(db_column='ID', primary_key=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', unique=True, max_length=255)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'Data_Sizes'

    def __str__(self):
        return "Size: [" + self.id.__str__() + ", " + self.name + "] "

and I call create the template like this:

def index(request):
    template = loader.get_template('orders/responseTemplate.xml')
    company = Company.objects.get(id=10)  # remember to use `get` for a single item
    order_list = company.orders.all()
    tpcontext = {'orderList': order_list}
    return HttpResponse(template.render(tpcontext, request))

the template file I'm using looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<orders>
    {% for order in orderList %}
    <order id="{{ order.id }}">
        <models>
        {% for model in order.model_set.all %}
        <model id="{{ model.id }}">
            <name>{{model.model_data.name}}</name>
            {% for color in model.model_color_set.all %}
            <color name="'{{color.color.name}}'">
                {% for size in color.modelsize_set.all %}
                <sizeAmount name="'{{size.size.name}}'">{{size.amount}}</sizeAmount>
                {% endfor%}
            </color>
            {% endfor%}
        </model>
        {% endfor %}
        </models>
    </order>
    {% endfor %}
</orders>

What I'm trying to do is to get nformation about a certain company (in this case the company with ID number 10) and obtain all of it's orders. After that for each order I want to obtain a list of models. After I have a list of models I want to show the model name on the screen and then I want to iterate through the list of colors associated with each model and add it to the model in the XML file. finally each color has a few size fields which should be added to their respective color. The output I'm getting looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<orders>

    <order id="16">
        <models>

        <model id="17">
            <name>Pants</name>

        </model>

        <model id="18">
            <name>Pants</name>

        </model>

        </models>
    </order>

</orders> 

as you can see I'm able to get a list o models and also the model's name. however the colors don't show up in the list. I've checked that there is information in the database and the information is present.

I think there is an error in this line in the template:

{% for color in model.model_color_set.all %}

however I don't know what that error can be?

Upvotes: 1

Views: 346

Answers (3)

Sam
Sam

Reputation: 2084

You have a one-to-one relationship between Model and ModelColor, so using a set doesn't make sense.

It looks like what you may be trying to access is the Colors set of the ModelData model. You could do that like so:

{% for model in order.model_set.all %}
    <model id="{{ model.id }}">
    <name>{{model.model_data.name}}</name>
    Colors:
    {% for color in model.model_data.colors_set.all %}
        {{ color.name }}
    {% endfor %}
{% endfor %}

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599490

Your model defines a ForeignKey from Model to ModelColor. That means that each model only has one modelcolor. There is no _set here, and nothing to iterate through; you can follow the foreign key to get the single color for that model. You can use the with tag to make this slightly easier to work with.

    <model id="{{ model.id }}">
        <name>{{model.model_data.name}}</name>
        {% with model.model_color as color %}
        <color name="'{{color.color.name}}'">
            {% for size in color.modelsize_set.all %}
            <sizeAmount name="'{{size.size.name}}'">{{size.amount}}</sizeAmount>
            {% endfor%}
        </color>
        {% endwith %}

Upvotes: 1

py_dude
py_dude

Reputation: 832

Have you tried model.modelcolor_set.all ? Django doesn't add an underscore when converting the CamelCase model name to lower case.

Upvotes: 1

Related Questions