How to add an object attribute to another object

Hello,

sorry I’m a newbie in coding trying to learn with Python and Django, so I’ll maybe ask some trivial or not relevant questions.

I tried the Django Howto and now try with another app : a quote app.

Here is my problem(s) : I have an internal model with 3 objects : a quote, a source (of the quote), an author (of the source).

The object “author” is linked to the object “source” with a ForeignKey. Now, I would like, the name of the author, to appear directly in the quote.

I think there is two ways to do it : whether in the interface, or in the model. I think it’s semantically correct to say that a quote has (by inference) an author, so I would like to do it in the model.

I tried with the DB Function : ForeignKey.to_field but I’m not sure it’s the good way to do it…

Any help ? Thank you :slight_smile:

Whenever anyone is looking to get started, I always point them to the official Django Tutorial and the Django Girls Tutorial. Both are really good and if you work(*) through them, you’ll have worked with all the key concepts of what Django has to offer.

In this particular case, working through the tutorial will provide you with the information you need to answer these questions - and probably many others as well.

(* Footnote: “work” in this context means to actually type the code as part of the exercises, not to just copy/paste from the text to your editor window. Making yourself type the code forces you to really look at the code being written, and will enhance your understanding of what’s going on. Also, the typo mistakes you will make along the way will help develop your eye for seeing similar mistakes you may make in the future.)

Ken

1 Like

Hello,

Thank you for your answer. This is actually what I did.

I now try to make something on my own, but I don’t see the answer of my question in the tutorial

Rather than talking in the abstract, it would be helpful for you to post your models here so we can talk about your specific code.

(When posting code here, enclose it between lines consisting of three backticks (`). So you’ll have a line that is only ```, your code, and then another line that is only ```.) Make sure you’re using the backtick and not the apostrophe (’).

Then, please clarify what exactly it is you’re trying to accomplish. Are you just trying to display the associated fields? Or are you looking to build forms allowing you to enter related data? Or are you looking to update data based on relationships?

For any of these cases, please post the most recent code you’ve tried - it’s going to be easier to make recommendations that way. (And include all relevant code. For example, if you’re just displaying data, you should post both the view and the template.)

Ken

Ok.

So, I have an app I called “Citatio”, to save quotes from some diverse authors and sources.

Here is my model :

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    surname = models.CharField(max_length=200)
    bio = models.URLField(max_length=400)

    def __str__(self):
        return "%s %s" % (self.surname, self.name)

class Source(models.Model):
    name = models.CharField(max_length=350)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publication_date = models.DateField(auto_now=False)

class Quote(models.Model):
    content = models.TextField()
    source = models.ForeignKey(Source, on_delete=models.CASCADE)

I want to get a list of all the quotes I have in my db. So I create I view to request this list and a template to show it :

The view :

from django.shortcuts import render
from django.http import HttpResponse
from .models import Quote

# Create your views here.

def index(request):
    latest_Quote_list = Quote.objects.values().order_by('id')
    context = {'latest_Quote_list' : latest_Quote_list}
    return render(request, 'Citatio/index.html', context)

And the template :

    {% if latest_Quote_list %}
        <ul>
        {% for Quote in latest_Quote_list %}
            <li><a href="/Citatio/{{ Quote.id }}/">{{ Quote.content }}</a></li>
                <ul><li>{{ Quote.source__name }}, {{ Quote.source__author__surname }} {{ Quote.source__author__name }}</li></ul>
        {%  endfor %}
        </ul>
    {% else %}
        <p>No Quote</p>
    {% endif %}
</head

The problem is I want to show some fields from the Author object (like the “source name”, “author name” or “author surname” in the list I show in the template.

I can do it by indicating for example “source__author__surname” in “values”. But I can only request I’ll have indicated in values.
If I let “values” blank, I can request every field from the object, but not the linked fileds (like “source__author__name”.

Is there a way to get every linked field, without to indicate it in “values” ?

Thank you by advance :slight_smile:

Since the template rendering engine can work with querysets directly, you’re doing more work than necessary by specifying the values clause.

Start by replacing this:
latest_Quote_list = Quote.objects.values().order_by('id')
with:
latest_Quote_list = Quote.objects.order_by('id')

Then, if you want to optimize the processing of this to reduce the number of queries involved, you can use the select_related clause:
latest_Quote_list = Quote.objects.order_by('id').select_related('source__author')

Ken

Thank you for the help !

It’s clearer now. I had to figure how to use in the template, but it’s ok now :wink: