I'm using Django to create an application with different types of words / terms. On one page, you may have the title "Terms" and then a list of terms. On another page, you have the exact same thing but for phrases (header, list of phrases).
Is it possible to do something like this -->
Store header and list for terms
Store header and list for phrases
Create one template that is used to show headers and lists on a
page
Call some Django function (not sure if this exists) that uses
the template to generate a page for terms
Use that same Django
function that uses the same template to generate the page for
phrases
The hope is that I can avoid having one large template folder full of pages that are basically doing the same thing. For example, right now, if I wanted to add phrases_in_spanish and phrases_in_french, I'd have to add two new templates that are basically doing the same thing --> showing the header and the list. All I want to do is store the header and list somewhere and have Django do the rest of the work to create the pages. So I could technically have 1,000 pages without having to write 1,000 different template files that are all just showing headers and lists.
Template example:
{% extends "profile/base.html" %}
{% block content %}
<div class="row">
<div class="col-sm-6">
Add a New Term
<p>Terms:</p>
<ul>
{% for term in terms %}
<li><p>{{ term.name }} : {{ term.definition }}</p></li>
Edit Term
Delete Term
{% empty %}
<li>No terms have been added yet.</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock content %}
You don't have to create an html template for each page.
You have to create a URL dispatcher on urls.py:
url(r'^(P<list_name>\w+)/$', views.your_view)
So instead of having many templates that have the same structure, you render only one with the info you want.
So your view should look like this:
def your_view(request, list_name):
list = get_object_or_404(List, pk=list_name)
context = {
'list_info':list.info
}
return render(request, 'your_app/template.html', context)
Of course in this example you need to have a table called List on your database with primary key list_name.
Maybe it would be possible to have a model called something generic like Concept (this could be Terms or Phrases or Headers or something similar) with a related model like ConceptDetail (which could be a list of terms or list of phrases, etc).
Then you have one URL config but different concepts have different PKs which appear in the URL to differenciate them (you can also use slugs in URL as kwargs to make the URLs more readable). For example:
path('concept/', ConceptListView.as_view()),
path('concept/<slug:concept_name>/', ConceptDetailView.as_view()),
As for views and templates, you have a ListView that shows you all the concepts (here you can add filtering and other search options) and then in the DetailView of each concept you could display its related ConceptDetail instances.
Does this sound like something that could help you?
Related
I have a template file for the header of a website which will be included in all pages, it takes a list as a context and renders items based on that list as follows:
{% for category in categories %}
<li><a class='text-primary' href=" {% url 'category-url' category.id%}">{{category.name | title}}</a></li>
{% endfor %}
Now my problem is that every view that renders any page in the website needs to pass the categories list in order for the header to work (the header is included in all pages). and thus almost all of my views have this code
return render(request, ..., 'categories':Category.objects.all())
so is there away to have a code that passes the categories to the header once and just rely on that for every other view?
I would like to know if anyone has any best practice recommendations for rendering a view within a view in Django, or something with a similar effect where both views can have their own context and methods.
I am currently rendering the dropdown using the built-in include tag. So the nested .html is using the same Django view as the rest of the page. And all the context is coming from the main view as shown below. I would like to give this dropdown its own Django view so that I only perform certain database queries and other calculations if the dropdown is opened.
<div class="container-fluid">
<div class="row">
<div class="col-6">
</div>
<div class="col-2 d-flex justify-content-center">
{% include nested.html %}
</div> ...
It would be nice if someone with experience in this could let me know what they think, and if it even makes sense to try and split this into 2 views.
In summary. I would like to know if I can somehow render a separate view using something similar to the include Django tag. So that I have control over where the view gets rendered.
Below I have outlined my implementation of the solution below, using custom inclusion tags as suggested in the comments to my question.
You can make a custom template tag file in project directory and then register these in the template library. e.g:
template_tags.py
from django import template
from users.models import Organisation
register = template.Library()
#register.inclusion_tag('nested.html', takes_context=True)
def nested_template(context, param=None): #param to pass variables from main view
context.update({
'data_list': get_data_list(param)
'organisation_id': param,
})
return context
def get_data_list(self,param):
data_list = ... #do all queries needed.
return data_list
In the template tag you point to your nested.html which does whatever you need it to do. For example:
nested.html
{% for data in data_list %}
<h4> {{data}} </h4>
{% endfor %}
Then to include the template, in your main view template:
{% load nested_template %} #at the top or anywhere before using it
{% nested_template param %} #where you want the template included
Hopefully clear enough and may assist someone
I was going to create my own friendship view and everything (But I couldn't figure out how to get everything working in a database) So I opted to use something called django-friendship which seems quite good, and It also came with tags to use in the HTML templates but now I am trying to list all the friend requests I can't seem to do a for statement in the tag which is:
{% friend_requests request.user %}
What I would like to be able to do is
{for friend_requests in request.user}
#show this then that#
the link to the github page for the project is this: https://github.com/revsys/django-friendship
If it comes to it I would prefer to create my own friendship implementation, but I don't know where to start.
The friend_requests tag uses a template, which already loops through and creates a list for you:
#register.inclusion_tag('friendship/templatetags/friend_requests.html')
def friend_requests(user):
"""
Inclusion tag to display friend requests
"""
return {'friend_requests': Friend.objects.requests(user)}
source
Here is the template
<ul>
{% for friend_request in friend_requests %}
<li>{{ friend_request }}</li>
{% endfor %}
</ul>
source
To customize it, create a directory friendship and inside it another one called templatetags, and then create a file called friend_requests.html in your app's template directory, and then you can customize the output there.
I know we can pass variables to content blocks but are we able to pass list?
I know we can pass variables in this way
{% include "partials/pickUp-Order-Form.html" with form="form" %}
I tried passing list like this
{% include "partials/pickUp-Order-Form.html" with form=["list", "test"] %}
this wouldn't work though. I searched up and there doesn't seem to have such thing in documentations.
You need to pass a list in a variable or object, you can do it like this:
{% include "partials/pickUp-Order-Form.html" with form="list test".split %}
or you can create the variable first and then pass it to the include tag:
{% with "list test" as list %}
{% include "partials/pickUp-Order-Form.html" with form=list.split %}
{% endwith %}
The include django template tag can be used for loading and rendering HTML templates where the context/data that was passed to the original template gets passed.
You can find documentation about this functionality in the built-ins section.
So if you would like to include a template, of which original view that renders the template has the following context dict: {'word': 'Bird', 'power_level': 9001} you can render it inside another template with: {% include "word_template.html" with word="Not a Bird" power_level="470" %}, which will in turn change the values to the desired ones.
To answer the question:
It should work
Taking into consideration you include a template which will not use the list type as something else.
I have the following code in my template:
{% for req in user.requests_made_set.all %}
{% if not req.is_published %}
{{ req }}
{% endif %}
{% empty %}
No requests
{% endfor %}
If there are some requests but none has the is_published = True then how could I output a message (like "No requests") ?? I'd only like to use Django templates and not do it in my view!
Thanks
Even if this might be possible to achieve in the template, I (and probably many other people) would advise against it. To achieve this, you basically need to find out whether there are any objects in the database matching some criteria. That is certainly not something that belongs into a template.
Templates are intended to be used to define how stuff is displayed. The task you're solving is determining what stuff to display. This definitely belongs in a view and not a template.
If you want to avoid placing it in a view just because you want the information to appear on each page, regardless of the view, consider using a context processor which would add the required information to your template context automatically, or writing a template tag that would solve this for you.