Django Loading data independantly in a partial - django

I have some partial templates which I load in on various pages and sometimes the inclusion of these partials is dynamic, these have their own related models.
At present I am passing models via views to the main page, but is there not a way to load data for these partials independant of the parent page and view?
Just seems like I am duplicating code in the views which cant be right!
Can I not create a custom tag or something which would allow me to load data into the partial irrespective of the data passed in the parent page and its view?
A good example of this is a partial for "latest posts" which exists in a sidebar partial and loads on many different parent templates
Cheers
Kevin

A custom template tag can do this for you. You could write an inclusion tag, which will output the rendered template directly:
# yourapp/templatetags/appname_tags.py
def latest_posts(num_posts):
posts = Post.objects.all()[:num_posts]
return {'posts': posts}
register.inclusion_tag('yourapp/partials/latest_posts.html')(latest_posts)

Related

Add own functions in views.py wagtail

I have setup a wagtail website. It works great for postings like a blog and simply add new pages.
But what if I want to add some extra functions to a page. Like showing values from my own database in a table.
Normally i use a models.py, views.py and template.py. But now I don’t see any views.py to add functions or a urls.py to redirect to an url?
Don’t know where to start!
Or is this not the meaning of a wagtail site, to customize it that way?
Thnx in advanced.
You can certainly add additional data to pages. One option is to add the additional information to the context of a page type by overriding its get_context method. For example, this page is just a place to display a bunch of links. The links and the collections they belong to are plain old Django models (managed as snippets). And then there is a page model that queries the database like this:
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
collection_tuples = []
site = Site.find_for_request(request)
for collection in Collection.objects.filter(links__audiences=self.audience, site=site).distinct():
links = Link.objects.filter(audiences=self.audience, collections=collection, site=site)
collection_tuples.append((collection.name, links.order_by('text')))
# sort collection tuples by the collection name before sending to the template
context['collection_tuples'] = sorted(collection_tuples, key=lambda x: x[0], reverse=False)
return context
Another option is to do basically the same thing - but in a StructBlock. Then you can include the StructBlock in a StreamField on your page. Most of the Caltech site is written using blocks that can be included in one large StreamField on a page. Some of those blocks manage their own content, e.g. rich text blocks or image blocks, but others query data and render it in a block template.
To add to #cnk's excellent answer - you can absolutely use views.py and urls.py just as you would in an ordinary Django project. However, any views you define in that way will be available at a fixed URL, which means they'll be distinct from the Wagtail page system (where the URL for a page is determined by the page slug that the editor chooses within the Wagtail admin).
If you're defining URLs this way, make sure they appear above the include(wagtail_urls) route in your project's top-level urls.py.

django generic view send context to multiple templates at the same time

I am trying to send the listview context (book_list) in this case to more than one template at the same time.
I have tried to edit templates_names by doing this:
class BookListView(ListView):
model = Book
def get_template_names(self):
template_name=["catalog/index.html","catalog/book_list.html"]
return template_name
but book_list is still only known to catalog/book_list.html not to catalog/index.html(so the function I have added did NOT do anything).
any suggestions please?
Best regards
You just cannot :) Each view is responsible for one url and one template in will render. Actually I cannot even find and example when one would need to do what you're trying to do.
I think you have to read about template inheritance
render multiple template from a single view in django
I had same problem. If you send arguments to parents html and if your htmls are children. They can access to arguments. check the link.

Django: rendering more than one view in a template

I am newbie in Django and didn't know how to render more than one view in a template. This is my case, I have a template (main.html) and I have 2 sections: a home page and one at the top where the user data (messages, log off, etc ...) will be displayed.
My question is this, can I make 2 partial views (_index.html and _userdata.html) and render them separately and display them in the template. In the same way that the "include" php or ASP.NET MVC partial views. Or spend the model or models to the template with all the information.
As I haven't explained well, an example of real life would be, Amazon or any online book store. Where you can see the books or products on the right side and have your shopping cart with your products shown. How would that Django? Have an HTML template and view the 2 models you send or you can do 2 separate views and are rendered in the same HTML template?
Those things are bound to the user, so you could get them in your parent templates.
Example:
parent.html
{{ request.user.get_something }}
define get_something(self) in the user model (your items in the cart, etc).
You can also do something like:
{% include 'elements/my_something.html' %}

Add a form to admin side

I need to create a form to admin-side with two fields
Number of code: integer
Value of code: float
How can I do that. This form is not related to any model.
You can implement your modelless form as explained in #levi's answer.
Then, you can place it in the admin site in a number of different ways, depending your needs:
Make instances of the form available to all templates via a context processor, and override the admin templates to have it rendered wherever you want. You can create a view for only processing the form.
Create a view for both rendering and processing the form in a unique place, and hook it up to the admin as explained in the old Django Book, you'll need to make sure the template for that view extends one of the admin's templates (admin/change_form.html may be a good choice).
from django import forms
class Your_Form(forms.Form):
number_code = forms.IntegerField()
value_code = forms.FloatField()

Django, custom tag... how?

I would like to make a django custom tag to display 10 entry titles from the category where the user is reading an article. How can I do this? I need to pass the category from the actual entry.
The best way to do this would be with an inclusion tag. This is a tag that renders a template fragment which renders the 10 related articles.
You just pass in the current article into the tag, and return the context for the template fragment - ie the related articles.
#register.inclusion_tag('related_articles.html')
def related_articles(article, count):
category = article.category
articles = category.article_set.exclude(id=article.id)[:count]
return {'articles': articles}
You'll need a related_articles.html file in your templates directory which outputs the articles. Then, to call it from your main template, you would just do
{% related_articles article 10 %}
where article is the name of the article object.
Why a custom tag? It's probably better, cleaner, to add a method to the article model, and call that from the template. Depending on your model, the method would be practically trivial.
Check here for making custom tags:
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#howto-custom-template-tags
You would need to pass the relevant category object to the template context.