简体   繁体   中英

Django - How to display parent model property in template

This is a pretty generic issue I'm having and I have so far not been able to debug this any further after reading the Django documentation nor any of the other somewhat related responses on this site.

My issue is this, and I'll post the code so people can see what I'm trying to accomplish as well.

I have the following models

class Tournament(models.Model):
    name = models.CharField(max_length=128, null=True)
    description = models.CharField(max_length=2000, null=True)
    number_players = models.IntegerField(default=-1)
    teams_per_game = models.IntegerField(default=-1)
    template = models.IntegerField(default=-1)
    created_by = models.ForeignKey('Player')
    created_date = models.DateTimeField(auto_now=True)
    number_rounds = models.IntegerField(default=-1)
    is_finished = models.BooleanField(default=False)
    has_started = models.BooleanField(default=False)
    players_per_team = models.IntegerField(default=1)
    private = models.BooleanField(default=False,db_index=True)
    start_option_when_full = models.BooleanField(default=True)
    host_sets_tourney = models.BooleanField(default=False)
    max_players = models.IntegerField(default=-1)
    template_settings = models.TextField()

@property
def time_since_created(self):
    print("Here!")
    fmt = '%H:%M:%S'
    td = datetime.strptime(datetime.now(), fmt) - datetime.strptime(self.created_date, fmt)
    vars(td)

    print ("Hours: {}".format(td.hours))
    print ("Minutes: {}".format(td.minutes))
    print ("Seconds: {}".format(td.seconds))

    if td.hours > 0:
        return td.hours + " hours ago"
    if td.minutes > 0:
        return td.minutes + " minutes ago"
    if td.seconds > 0:
        return td.seconds + " seconds ago"



def __str__(self):
    return "Tournament: " + self.name


class SwissTournament(Tournament):

    type = models.CharField(max_length=255, default="Swiss")
    max_rating = models.IntegerField(default=0)
    min_rating = models.IntegerField(default=0)
    best_record = models.CharField(max_length=10, null=True)
    max_teams = 128
    min_teams = 16

When I do this in my view:

def index(request):
    context = {}
    try:
        swiss_tournaments = SwissTournament.objects.filter(private=False).values()[:20]
        if swiss_tournaments.count() > 0:
            context.update({'swiss_tournaments': swiss_tournaments})

            #for t in swiss_tournaments:
                # calling time_since_created set's time_since in our objects

        return render(request, 'index.html', context)
    except ObjectDoesNotExist:
        log("No open tournaments", LogLevel.informational)

        return render(request, 'index.html', context)

I get my swiss tournament objects back with zero issue, and I can display all the properties besides time_since_created… I don't even see the print statements in my standard output on my dev box like I do everywhere else in my code.

Template code:

            {% for swiss_t in swiss_tournaments %}
            <div class="card-body">
                <a class="card-link" href="#">
                    <span class="card-title h5"> {{ swiss_t.name }} </span><span class="text-muted h7 mb-2"> <i class="fa fa-clock-o"></i>{{ swiss_t.time_since_created }}</span></span>
                </a>

                <p class="card-text">
                    {{ swiss_t.description }}
                </p>
                <div>
                    <span class="badge badge-primary">{{ swiss_t.created_by.name }}</span>
                    <a href="https://warzone.com/MultiPlayer?TemplateID={{ swiss_t.template }}" target="_blank"><span class="badge badge-primary">Template {{ swiss_t.template }}</span></a>
                    <span class="badge badge-primary">Max Players: {{ swiss_t.max_players }}</span>
                    <span class="badge badge-primary">Node.js</span>
                    <span class="badge badge-primary">Ruby</span>
                    <span class="badge badge-primary">Paython</span>
                </div>
            </div>
            {% endfor %}

I've even tried making a child class @property and referencing the parent one (or just calculating it there)...no luck, the method is never called.

Does anyone know what I can do to debug this further or have any ideas how I can reference a @property like this in a view once the objects are loaded?

You've used the values() method in your query, which means that instead of sending a queryset of model instances to the template, you're sending a list of dicts. So the individual objects don't have any of the methods defined on the models.

You should avoid values unless you have a good reason, which you don't here. Use an actual queryset:

swiss_tournaments = SwissTournament.objects.filter(private=False)[:20]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM