Search code examples
pythondjangodatabasedjango-viewsurl-pattern

Django app view - how to get an entry from the django database in the url and to obtain more information from the database for the view?


I have a django application 'test_app'. The test_app page - "domain/test_app/" has a link to another page within the app "Genes". This takes me to "domain/test_app/genes/". In this page I have a list of links which comes from my a table in my django database called "gene", which is in test_app/models.py as class Gene. This links to another table called "Variants" via attribute 'gene' as a foreign key.

This is all in test_app/models.py:

class Gene(models.Model):
    gene = models.CharField(primary_key=True, max_length=110)
    transcript = models.CharField(max_length=100)

    def __str__(self):
        return self.gene


class Variant(models.Model):
    variant = models.CharField(primary_key=True, max_length=210)
    gene = models.ForeignKey(Gene, on_delete=models.CASCADE)
    cds = models.CharField(max_length=150)

    def __str__(self):
        return self.variant

My test_app/urls.py urlpatterns look like this:

urlpatterns = [
    url(r'^$', views.test_app, name='test_app'),
    url(r'^genes/$', views.genes, name='genes'),
    url(r'^genes/(?P<gene>)', views.variant_info, name='variant_info'),
]

and test_app/views.py look like this (link to test_app/templates/test_app/ directory with my templates in):

def test_app(request):
    template = loader.get_template('test_app/index.html')
    return render(request, 'test_app/index.html')

def genes(request):
    gene_list = Gene.objects.all()
    context = {'gene_list': gene_list}
    return render(request, 'test_app/genes.html', context)

def variant_info(request, gene):
    variant_info = Variant.objects.filter(gene=gene)
    return(request, 'test_app/gene_info.html', {'variant_info': variant_info}

I have a list of genes in my gene table in my database. When obtaining these genes using 'gene_list = Gene.objects.all()' this works fine. I then render this list to a template as a series of links on my "domain/test_app/genes" page. For example, when I click on TP53 on this page, it goes to "domain/test_app/genes/TP53/". This takes me to the correct page.

However, I clearly do not have the regex for this urlpattern correct as when I type in more digits or characters such as /TP53098120918 it still goes to the same page. Even when I put r'^genes/(?P)$' this is still happening and I dont understand why?

But the main problem I am having is obtaining the information from my variant table in my database and rendering this to the specific gene page, such as domain/test_app/genes/TP53.

When I am clicking on the TP53 it does not pass through to my view function 'variant_info' as the gene argument because the line:

variant_info = Variant.objects.filter(gene=gene)

does not obtain any information from the database - i thought this would pass gene='TP53' when I click on the link, and therefore this would be:

variant_info = Variant.objects.filter(gene='TP53')

which would return the information from the variant table with the gene as TP53. I don't know how to properly access the TP53 from the genes function in views.py.


Solution

  • The problem is that your (?P<gene>) is not matching any characters, so you will always have gene='' in your view.

    Try changing your url pattern to:

    url(r'^genes/(?P<gene>\w+)/$', views.variant_info, name='variant_info'),
    

    This will accept letters A-Z, a-z, digits 0-9 and underscore for the gene argument. I've added the trailing slash for consistency with your other views, and the dollar because it's usually a good idea to do this.