The Django model combines the relationships of one and many for display in a template

Not sure the best way to describe the problem. I have 2 contacts and a table attribute. The contact table has 1 entry per person, and the attribute table has 0, 1, or many entries per person. They are currently connected to a β€œfake” foreign key, which is not really a foreign key. If I need to add a foreign key, I will not deal with old data, and initially there was no foreign key. Thus, the tables are laid out as follows:

contact:

class contact(models.Model):
    contactId = models.AutoField(primary_key=True, db_column='contactId')
    firstName = models.CharField(max_length=255, null=True, db_column='firstName')
    middleName = models.CharField(max_length=255, null=True, db_column='middleName')
    lastName = models.CharField(max_length=255, null=True, db_column='lastName')

attribute:

class attribute(models.Model):
    attributeId = models.AutoField(primary_key=True, db_column='attributeId')
    contactId = models.IntegerField(db_index=True, null=True, db_column='contactId')
    attributeValue = models.TextField(null=True, db_column='attributeValue')

, Django . , , - , XML- :

<contacts>
    <contact>
        <contactId></contactId>
        <firstName></firstName>
        <lastName></lastName>
        <attributes>
            <attribute>
                <attributeId></attributeId>
                <attributeValue></attributeValue>
            </attribute>
        </attributes>
    </contact>
</contacts>

, , .

, . , , . , , , django/python, .

, , .

+3
3

, django , , .

contacts = Contact.objects.all()

for contact in contacts:
    contact.attributes = Attribute.objects.filter(contactId=contact.pk) 


return render_to_response("mytemplate.html", {'contacts': contacts })

;

attributes_map = dict( 
    [(attribute.contactId, attribute) for attribute in \
        Attribute.objects.filter(contactId__in=[contact.pk for contact in contacts])]
    )

for contact in contacts:
    contact.attributes = attributes_map.get(contact.pk)

return render_to_response("mytemplate.html", {'contacts': contacts })

<contacts>
{% for contact in contacts %}
    <contact>
        <contactId>{{ contact.pk }}</contactId>
        <firstName>{{ contact.firstName }}</firstName>
        <lastName>{{ contact.lastName }}</lastName>

        {% if contact.attributes %}
            <attributes>
            {% for attribute in contact.attributes %}
                <attribute>
                    <attributeId>{{ attribute.pk }}</attributeId>
                    <attributeValue>{{ attribute.attributeValue }}</attributeValue>
                </attribute>
            {% endfor %}
            </attributes>
        {% endif %}

    </contact>
{% endfor %}
</contacts>
+7

, .

, , , django, ForeignKey, , .

, , - ...

def attributes(self):
    return Attribute.objects.filter(contactId=self.contactId)

.

<attributes>
    {% for attribute in contact.attributes.all %}
        <attribute>
            ...
        </attribute>
    {% endfor %}
</attribute>

, contact.attributes.all ( ). - .

+1

Yuji Nick Johnson prefetch_refprops App Engine: http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine

:

attributes_map = dict( 
    [(attribute.contactId, attribute) for attribute in \
        Attribute.objects.filter(contactId__in=[contact.pk for contact in contacts])]
    )

:

attributes_map = dict(Attribute.objects
    .filter(contactId__in=set([contact.pk for contact in contacts]))
    .values_list('contactId', 'attribute'))

:

  • ()
  • , dict().

, .values_list() , dict(), , (.. "contactId" ) .

, , . :

for contact in contacts:
    contact.attributes = attributes_map.get(contact.pk)

. ,

attributes_map = dict(Attribute.objects
    .filter(contactId__in=set([contact.pk for contact in contacts]))
    .values_list('contactId', 'attribute'))
names_map = dict(Name.objects
    .filter(nameId__in=set([contact.nameId for contact in contacts]))
    .values_list('nameId', 'name'))

for contact in contacts:
    contact.attributes = attributes_map.get(contact.pk)
    contact.name = names_map.get(contact.nameId)

If you have ever had a template, generate a lot of additional SQL queries for each row of the result set (to view each value of the foreign key), this approach will have huge savings by preloading all the data before sending it to the template.

0
source

Source: https://habr.com/ru/post/1794583/


All Articles