0

Hello guys I am currently working on django views and templates and met some problems. I have a model named 'metabolites', which contains: id, name, compartment, charge and formula 5 components. I have another model named 'Reactionsmeta', which contains: id(reactions), name, metabolie1, metabolite2, .... metabolite6. The table of this model is not filled complete, because sometimes one id corresponds to 5 metabolites, but sometimes even 20.

I write a template which can displays all the reaction, when I click on the reaction and enter the detail page, I also want to display the metabolites that involve in this reactions. My views.py and templates are written as below:

reactions_detail.html

{% extends 'Recon/Base.html' %}
{% load static %}
{% block title %}Reaction Details{% endblock %}
{% block body %}
<h1>{{ reactionsmeta.id }}</h1>
<h2>{{ reactionsmeta.name}}</h2>
<!-- Left Album Info -->
<div class="col-sm-4 col-md-3">
    <div class="panel panel-default">
        <div class="panel-body">
            <a href="{% url 'detail_reaction' reactionsmeta.id %}">
                {% if reactionsmeta.id %}
                    <img src="{% static "Recon/images/Logo-Technische-Universiteit-Eindhoven.jpg" %}" class="img-responsive">
                {% else %}
                    <h3>No image to display</h3>
                {% endif %}
            </a>
            <h1>{{ reactionsmeta.id }} <small>{{ reactionsmeta.name }}</small></h1>
        </div>
    </div>
</div>

index.html

views.py
from django.views import generic
from .models import Reactionsmeta,Metabolites,Reactions
from django.shortcuts import render


class IndexView(generic.ListView):
template_name = 'Recon/index.html'
context_object_name = 'Reactions_object'

def get_queryset(self):
    return Reactionsmeta.objects.all()


class DetailsView(generic.DetailView):
model = Reactionsmeta
template_name = 'Recon/reactions_detail.html'

def get_context_data(self, **kwargs):
    context = super(DetailsView, self).get_context_data(**kwargs)
    context['metabolite'] = Metabolites.objects.all()
    context['reactions'] = Reactions.objects.all()

    # And so on for more models
    return context

How can I write the loop in reaction_detail.html???

EDIT:

class Metabolites(models.Model):
id = models.CharField(primary_key=True, max_length=255)
name = models.CharField(max_length=255, blank=True, null=True)
compartment = models.CharField(max_length=255, blank=True, null=True)
charge = models.CharField(max_length=255, blank=True, null=True)
formula = models.CharField(max_length=255, blank=True, null=True)
notes = models.CharField(max_length=255, blank=True, null=True)

class Meta:
    managed = False
    db_table = 'Metabolites'

class Reactionsmeta(models.Model):
id = models.CharField(primary_key=True, max_length=255)
name = models.CharField(max_length=255, blank=True, null=True)
metabolite1 = models.ForeignKey('Metabolites', db_column='metabolite1', 
blank=True, null=True, on_delete=models.CASCADE)
stoichiometry1 = models.IntegerField(blank=True, null=True)
metabolite2 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry2 = models.IntegerField(blank=True, null=True)
metabolite3 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry3 = models.CharField(max_length=255, blank=True, null=True)
......
stoichiometry55 = models.CharField(max_length=255, blank=True, null=True)
metabolite56 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry56 = models.CharField(max_length=255, blank=True, null=True)
metabolite57 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry57 = models.CharField(max_length=255, blank=True, null=True)
metabolite58 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry58 = models.CharField(max_length=255, blank=True, null=True)
metabolite59 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry59 = models.CharField(max_length=255, blank=True, null=True)
metabolite60 = models.CharField(max_length=255, blank=True, null=True)
stoichiometry60 = models.CharField(max_length=255, blank=True, null=True)

class Meta:
    managed = False
    db_table = 'ReactionsMeta'
HAOYANG MI
  • 151
  • 11
  • Can we see your Reaction Model, Reactionsmeta Model and Metabolite Model? We can access the relationship between metabolite, reactionmeta and reaction but we'd need to see what those fields are called and whether they have related_name set. – Harry MW Apr 02 '18 at 21:26
  • Hi, thank you for your concerning. And I edited the question and put the Reactionsmeta Model and Metabolites model on it. – HAOYANG MI Apr 02 '18 at 21:56
  • Happy to help. Any particular reason your `metabolite1` field is a foreign key and the rest are CharFields? Is it reasonable to assume that metabolite2-60 are in fact foreign keys? – Harry MW Apr 02 '18 at 22:08
  • Yes, they are all foreign keys – HAOYANG MI Apr 02 '18 at 22:28
  • The reason is that in adminsite you can click on the metabolite and check the information of this metabolite while viewing information of Reactionmeta – HAOYANG MI Apr 02 '18 at 22:29
  • It's definitely the right thing to do to make it a foreign key but by not designating it a Foreign Key field we lose the ability to easily check what the Foreign Key is referencing. – Harry MW Apr 02 '18 at 22:44

1 Answers1

0

I don't see a great way to do this since each metabolite has its own field and isn't necessarily a foreign key. It'd be easier if the metabolite were in a ManyToMany field with through defining the stoichiometry.

Django's ManyToMany Relationship with Additional Fields

https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_many/

That said, in the template you can display a Reactionsmeta metabolite1 and stoichiometry one by :

{% if reactionsmeta.metabolite1 %}
    Metabolite: {% reactionsmeta.metabolite1 %}
    Stoichiometry: {% reactionsmeta.stoichiometry1 %}
{% endif %}
{% if reactionsmeta.metabolite2 %}
    Metabolite: {% reactionsmeta.metabolite2 %}
    Stoichiometry: {% reactionsmeta.stoichiometry2 %}
{% endif %}
...
{% if reactionsmeta.metabolite60 %}
    Metabolite: {% reactionsmeta.metabolite60 %}
    Stoichiometry: {% reactionsmeta.stoichiometry60 %}
{% endif %}

Problems with the above:

  1. It's terrably repetative
  2. If the fields are in fact Foreign Keys their raw values wont't mean anything to the user.

EDIT: Response to comment that CharFields are in fact FKs.

So I think you need to query db for the information about the metabolites in the view and return that to the template. I think, by design, templates are not supposed to be able to access the db.

EDIT: I'm afraid you're going to have to learn how to write custom views. It's really not bad but it's hard to do some of the things you're attempting just using the generics.

https://docs.djangoproject.com/en/2.0/topics/http/views/

Harry MW
  • 134
  • 1
  • 10
  • Thank you for your great patience! But is it possible if I access the data in Metabolite model? is it possible if I write a loop for something like this: {% if reactions.metabolite1 != '' %} {{ metabolite.metabolite1.id }} – HAOYANG MI Apr 02 '18 at 22:44
  • I mean, how can I access to multiple models' data in one template? As you can see in my views.py, the model of class DetailsView is only Reactionsmeta, how can I also include Metabolites to this class? – HAOYANG MI Apr 02 '18 at 22:50
  • You can definitely do that HAOYANG but where is `metabolite` coming from and how is `metabolite.metabolite1` related to `reactions.metabolite1` also, in python an empty string will evaluate to False. – Harry MW Apr 02 '18 at 23:06
  • Hi, ReactionMeta is a model that contains metabolite1 - metabolite60. The data in these columns are ids (for examples, 10FDHTMl), and the information in Metabolites Model, contains id, name, compartment and formula, and the ids here are exactly the same with the data in metabolite1-60. So the relationship is derived – HAOYANG MI Apr 03 '18 at 09:52