Sorry in advance if there is an obvious answer to this, I'm still learning the ropes with Django.
I'm creating a website which has 6 pre determined subjects (not stored in DB)
english, civics, literature, language, history, bible
each subject is going to be associated with a unique color.
I've got a template for a subject.html page and a view that loads from the url appname/subject/subjectname
what I need to do is apply particular css to style the page according to the subject accessed. for example if the user goes to appname/subject/english I want the page to be "themed" to english.
I hope I've made myself clear, also I would like to know if there is a way I can add actual css code to the stylesheet and not have to change attributes one by one from the back-end.
thanks very much!
In templates you can use conditionals for add css, like this:
<div class="{% if subject=='civics' %}civic-class{% endif %}"></div>
For this, subject value should come from view.
Now, for themed page, you could use the extends tag. Let's supose:
def your_view(request):
subject # Here you get the url subject, 'how' is up to you
if subject == 'english'
template_base = '/some/html/tenplate.html'
elif subject == 'civis':
template_base = '/some/other/template.html'
... # then you return 'template_base' variable to template
Then in template:
{% extends template_base %} # at the top
Hope this helps, is the same logic if you use Class-Based views.
Django's views are not responsible for the presentation, it's the template (and css etc of course)'s reponsability. Now assuming you have the same view serving different subjects, the view obviously need to know which is the current subject (I assume from a captured part of the url passed as argument to the view), so it can easily pass this information to the template, which in turn can use it to add a subject-specific class to the body tag. Then you only have to write your css accordingly.
As an example:
# urls.py
patterns = urlpatterns('',
#...
url(r'whatever/(P?<subject>[a-z-]+>)/$', 'myviews.index', ...),
)
# myviews.py
def index(request, subject):
# do whatever
context = {
# whatever else
'subject':subject
}
return render(request, "whatever/index.html", context)
# whatever/index.html
<html>
# headers etc
<body class="something {{ subject }} etc">
# whatever here
</body>
</html>
You can do this is many ways.
In general you need to return some variable from your view to the html and depending on this variable select a style sheet, if your variable name will match you style sheet's name you can do "{{variable}}.css", if not you can use JQuery.
Related
I'm trying NOT to write same code twice on different templates. Real hassle when changing something.
So when I go to a section of the webpage, I want to display a side menu. This side-menu is suppose to be on several templates. Like index.html, detail.html, manage.html and so on.
But the section is only a part of the webpage, so I can't have it in base.html.
I was thinking about using include. But since the side menu is dependent of DB queries to be generated, I then have to do queries for each view. Which also makes redundant code.
What is best practice for this feature?
Cheers!
You could write custom inclusion_tag, that's more feasible for the scenario:
my_app/templatetags/my_app_tags.py
from django import template
register = template.Library()
#register.inclusion_tag('side_menu.html')
def side_menu(*args, **kwargs):
# prepare context here for `side_menu.html`
ctx = {}
return ctx
Then in any template you want to include side menu do this:
{% load side_menu from my_app_tags %}
{% side_menu %}
I am working on a Wagtail project consisting of a few semi-static pages (homepage, about, etc.) and a blog. In the homepage, I wanted to list the latest blog entries, which I could do adding the following code to the HomePage model:
def blog_posts(self):
# Get list of live blog pages that are descendants of this page
posts = BlogPost.objects.live().order_by('-date_published')[:4]
return posts
def get_context(self, request):
context = super(HomePage, self).get_context(request)
context['posts'] = self.blog_posts()
return context
However, I would also like to add the last 3 entries in the footer, which is a common element of all the pages in the site. I'm not sure of what is the best way to do this — surely I could add similar code to all the models, but maybe there's a way to extend the Page class as a whole or somehow add "global" context? What is the best approach to do this?
This sounds like a good case for a custom template tag.
A good place for this would be in blog/templatetags/blog_tags.py:
import datetime
from django import template
from blog.models import BlogPost
register = template.Library()
#register.inclusion_tag('blog/includes/blog_posts.html', takes_context=True)
def latest_blog_posts(context):
""" Get list of live blog pages that are descendants of this page """
page = context['page']
posts = BlogPost.objects.descendant_of(page).live().public().order_by('-date_published')[:4]
return {'posts': posts}
You will need to add a partial template for this, at blog/templates/blog/includes/blog_posts.html. And then in each page template that must include this, include at the top:
{% load blog_tags %}
and in the desired location:
{% latest_blog_posts %}
I note that your code comment indicates you want descendants of the given page, but your code doesn't do that. I have included this in my example. Also, I have used an inclusion tag, so that you do not have to repeat the HTML for the blog listing on each page template that uses this custom template tag.
i like to use the url template tag in my model's content.
example:
models content:
Car.description = 'this is a link to our main page: home'
in template.html:
<div>{{ Car.description }}</div>
result
<div>this is a link to our main page: home
is it possible, or do i have to write my own template tag?
thanks in advance
Roman
Assuming you have this:
car.description = 'this is a link to our main page: home'
You can do:
from django.template import Context, Template
from django.core.urlresolvers import reverse
class Car(models.Model):
def description_with_url(self):
return Template(self.description).render({'url': reverse('home')})
or use the same logic in custom template tag instead of method..
I can't figure out why you would need to do that. Assuming that I fully-understood your question, you are attempting to store something within a model's field that then behaves "dynamically" when rendered.
A model field's content that stores a URL should contain a URL and only a URL by utilizing the URLField.
Else, if you're dynamically building the URL from somewhere else, simply use template markup, i.e. the url template tag as it is meant to be used; it can also take parameters depending on the specific URL pattern. I.e. the url tag is meant to be used in the template's context.
Let me know if you update the question to describe what you are trying to achieve. But storing "behaviour" at data level is something to simply stay away from.
I am brand new to web development, Django, python, html, etc. I have a basic Django app that displays a list of publication titles that have been entered into the database. This works fine.
I now want to make it so that each publication title is a link that - when clicked on - renders another template with the details of the publication that was clicked. So far, I know how to get the publication link to render a template, but I am trying to figure out how to pass in the publication title to the hyperlink so that the data that is rendered in the details template will be specific to the title that was chosen.
Here is what I have in my publication template which displays all the publications (it is incorrect, but hopefully it clarifies what I am trying to do):
<html>
<head><title>Publications</title></head>
<body>
<h1>Publications</h1>
<ul>
{% for publication in publication_list %}
<li><strong>{{ publication.title}}</strong></li>
{% endfor %}
</ul>
</body>
</html>
For the sake of context, the url pattern that handles this is:
url(r'^(?P<detail_type>\w+)/(?P<link_item>\w+)/detail$', get_details)
And the view function is:
// note: I may have some of the logic/syntax wrong here, but this is the basic idea
def get_details(request, detail_type=None, link_item=None):
if detail_type == "publications":
publication = Publication.objects.filter(title__iexact=link_item)
return render(request, 'publication_detail.html', {'detail_type' : detail_type, 'publication' : publication})
elif ....
Like I said, I am very much a beginner so if I am approaching this in wrong way, any suggestions or resources are appreciated. Thanks.
If you use named url patterns you can easily do this with the url template tag.
urls.py
url(r'^(?P<detail_type>\w+)/(?P<link_item>\w+)/detail$', get_details, name='details')
template
{% url 'details' 'publications' publication.title %}
I hope you know about SlugField too, it is much better for urls than a normal CharField.
An alternative:
urls.py
url(r'^(?P<detail_type>\w+)/(?P<pk>\w+)/detail$', get_details, name='details')
template
{% url 'details' 'publications' publication.pk %}
views.py
def get_details(request, detail_type=None, pk=None):
if detail_type == "publications":
publication = Publication.objects.get(pk=pk)
return render(request, 'publication_detail.html', {'detail_type' : detail_type, 'publication' : publication})
elif ....
This uses the primary key of the entry instead of the title. If you want to have a url with the title in it you will want to add and use a SlugField on your model.
This looks pretty good to me, although you may want to use get as opposed to filter in your view function if all the publication titles are unique and you want to pass an instance of Publication rather than a queryset (containing one item) into the detail template. This would throw an error of there were 0 or >1 matches, but it sounds like that's probably the behavior you'd want
However, I'm not sure what it is that you're missing here. What does publication_detail.html look like? You should have essentially everything you need in the above code to render the details, assuming they're all contained in the relevant Publication instance.
I'm writing a twitter-like note-taking web app.
In a page the latest 20 notes of the user will be listed,
and when the user scroll to the bottom of the browser window more items will be loaded and rendered.
The initial 20 notes are part of the generated html of my django template, but the other dynamically loaded items are in json format.
I want to know how do I do the tag-and-username converting consistently.
Thanks in advance.
There's a couple of pieces to consider here. On the server side, you have to be able to maintain what "chunk" of the notes list the user is on. The easiest way to do this is probably the Django paginator. It works basically by taking a QuerySet, setting a count for the number of items, then giving it the "page" number (or "chunk" number) and it returns those items.
You could do it with JSON, but it would be just as easy to do it with HTML as well. When we look at the client side part of this you'll see why.
So we can have a view "api" to handle a note "chunk" (note all my code samples here are abbreviated just for demonstration. You'd want to have error handling and all that)...
def get_notes_chunk(request, *args, **kwargs):
# Get our notes, however...
all_notes = Notes.objects.all()
# Paginate them based on the page we're on...
chunk_number = request.GET.get('c')
paginator = Paginator(all_notes, 20) # (show 20 at a time)
current_chunk = paginator.page(chunk_number)
# Render to template all that jazz
render_to_template( ... , { 'paginator':paginator, 'current_chunk':current_chunk }, ...)
Our template renders <li> tags which we'll stick into a <ul> on the client...
{% for note in current_chunk.object_list %}
<li>{{ note }}</li>
{% endfor %}
Now on the client, we need to write some javascript to handle this. It's up to you to determine on what event to fire the update, but as for how, we can use a little jQuery to handle this...
<script type="text/javascript">
var chunk_count = 1;
var notes_list_id = 'notes-list'
function load_next_chunk() {
chunk_count += 1;
$.get('{% url get_notes_chunk %}?c=' + chunk_count, function(html) {
$('#'+notes_list_id).append(html);
});
}
</script>
<body>
...
<ul id="notes-list">
<!-- Render chunk #1 here -->
</ul>
...
</body>
Some things that would probably make sense...
Refactor the rendering of the notes list into a template tag so that you can re-use it for your API and the main rendering of your page
Refactor the querying/paginating of the Notes (or whatever) model so that you can re-use it in both views
Figure out on what event the next chunk will be loaded and implement that.
The question isn't that clear... but for generating the HTML out of a Tweet take a look at twp(based on the official twitter-text-java lib):
http://github.com/BonsaiDen/twp
I'm not sure exactly what you're asking, but what's wrong with something like {{ user.get_absolute_url }}? For the tag detail URLs, it really depends on what you're looking for, but you would have to construct the url and view for that yourself.