Sending an object with request - django

In the below code i am trying to send a object with the request,Is this correct if so how to decode it in template
def index(request):
cat = Category.objects.filter(title="ASD")
dict = {'cat' : cat}
request.update('dict' : dict)
#or
request.dict=dict;
And In the templates can we write the code as
{% for obj in request.dict%}
obj.title
{% endfor %}
EDIT:
If i am calling function like
def post_list(request, page=0, paginate_by=20, **kwargs):
logging.debug("post_list")
page_size = getattr(settings,'BLOG_PAGESIZE', paginate_by)
return list_detail.object_list(
request,
queryset=Post.objects.published(),
paginate_by=page_size,
page=page,
**kwargs
)

You could do this, but why would you want to? Django has a simple, well-defined and well-documented way of passing data into templates - through the context. Why try and find ways to work around that?
Edit after comment No. Again, Django has a perfectly good way of passing extra context into a generic view, via the extra_context parameter which again is well-documented.

You're not showing the actual function you use to render your view (render(), render_to_response(), etc.).
Let's say you are using render_to_response() :
render_to_response(template_name[, dictionary][, context_instance][, mimetype])
Renders a given template with a given
context dictionary and returns an
HttpResponse object with that rendered
text.
So if you pass in {"foo": your_object} as a dictionary you can use {{ foo }} directly in your template.
If you are using the object_list generic view you should use the extra_context:
extra_context: A dictionary of values
to add to the template context. By
default, this is an empty dictionary.
If a value in the dictionary is
callable, the generic view will call
it just before rendering the template.

Related

Django get url variables within get_context data?

Say I have a url likes this
path(
'foo/<int:foo_id>/edit/',
views.FooView.as_view(),
name='foo',
),
and a view likes this:
def get(self, request, foo_id):
I find a common idiom is getting the URL variable foo_id into the context.
The only thing context has access to be default is request. I tried checking request and request.GET and could not see anything.
Is there a better way than:
Manually adding url variables to the context_data after get_context_data()
or passing it into get_context_data from a custom call from get? (ugly because class based views expect the same get_context_data signature)
The url parameters are stored in the .kwargs of the view. You thus can access and render these with:
{{ view.kwargs.foo_id }}
There is a reference with the name view that is passed which is the View object that is constructed when handling a request. We thus access the .kwargs attribute of that View object, and in the kwargs, we look for kwargs['foo_id'].
A peculiarity in Django is that a TemplateView [Django-doc] passes all it kwargs items as context data, if your view is thus a TemplateView, then you can render this with
<!-- only a TemplateView -->
{{ foo_id }}

How can I tell if I'm doing a create or an update with django generic views (CreateView vs UpdateView) from my template?

I'm sharing the same template for my CreateView and UpdateView using django's generic views. I want the "submit" button in my template to say "Add" when I'm using the CreateView and "Update" when I'm using the UpdateView. Is there any way in my template to distinguish which view is being used (CreateView vs UpdateView)?
I know I could use a separate template using template_name_suffix and put the common stuff in a separate include or something but just wanted to see if there was a way to do it without creating a separate template.
When creating a new object, object will always be None, at the moment the template is rendered. You could check for the existence of {{ object }} in your template:
{% if object %}Update{% else %}Add{% endif %}
Override get_context_data and add a flag in your view:
def get_context_data(self, **kwargs):
context = super(YourClass, self).get_context_data(**context)
context['create_view'] = True
return context
Change YourClass to your Class View name
Then in your template you can:
{% if create_view %}

Django basics: how to render a context with a class based view

My 'Note' model has a Charfield called 'tags'. I want to take the Note.tags string and render it as a . I have a method that will give me a python list and I am sort of hoping that I can use the form method '.as_ul' in the template. But I can't seem to get the variable into the template. Here is what I am trying:
My view class:
import string
...
class NoteDetailView(generic.DetailView):
model = Note
template_name = 'note_taker/note'
def tag_string_to_list(self):
tag_string = Note.tags
tag_list = string.split(tag_string)
return render(template_name, Context({'tag_list':tag_list}, note_taker))
My template:
<ul>
{{ tag_list.as_ul }}
</ul>
even if I am wrong about how to use '.as_ul' I can't even render the list with {{ tag_list }}
I suppose I am not understanding how view methods work then.
Use the get_context_data method.
class NoteDetailView(generic.DetailView):
def get_context_data(self, **kwargs):
context = super(NoteDetailView, self).get_context_data(**kwargs)
context['tag_list'] = Note.tags.split()
return context
Within the template, you won't be able to use .as_ul, but there is a built in filter unordered_list that will probably do what you want:
<ul>
{{ tag_list|unordered_list }}
</ul>
Although you should really consider defining a standalone Tag model and using a many-to-many relationship rather than just a char field. This is one of the classic examples of many-to-many relationships. Or using one of the third-party Django tagging packages.
I always use Django's standard ContextMixin. It makes sure that the view object is available in the template as view.
So the view becomes like
class NoteDetailView(generic.ContextMixin, generic.DetailView):
model = Note
template_name = 'note_taker/note'
def tag_string_as_list(self):
return Note.tags.split()
And in the view you do:
<ul>{{ view.tag_string_as_list }}</ul>

Automatically add more items if an item exists in template

I have an app that passes "book" object to the template from my view.
I want to automatically add more items to the template context if "book" is being passed. I don't want to do it for every view that passes "book".
e.g. if "book" exists, add "other_books_user_read" in relation to "books" to the template.
I was trying to do this using middleware but I cannot figure out how to check the context if "book" exists.
You can make a template tag that does this behavior, or you could put a method on your book model that you can access in the template.
Here's the simplest one to explain:
class Book(Model):
def other_books_users_read(self):
return Book.objects.filter(...)
{{ book.other_books_users_read }}
Template tag: It's your responsibility to figure out how a custom template tag works, but essentially the code would be...
#register.assignment_tag
def get_other_books_users_read(book):
return Book.objects.filter(...) # logic here to get the books you need.
{% get_other_books_users_read book as other_books_users_read %}
{% for book in other_books_users_read %}
...
Now, if you truly want it in the context, and one line of code (and a dot) is too much work, you can set up a middleware that injects content into the context.
https://docs.djangoproject.com/en/dev/topics/http/middleware/?from=olddocs#process-template-response
class MyMiddleware(object):
def process_template_response(self, request, response):
if 'book' in response.context_data:
response.context_data['other_books'] = Book.objects.filter(...)
return response
But IMO that's a silly way to use a template context middleware since you literally have access to a book object in your template.

How to use the querylist object in Django template

Initially i had this code
(r'^list/fixed/$', list_detail.object_list, fixedList)
In template i use
{% for val in object_list %}
It worked fine as i used Generic list
But now i want to write my own view which does same
object_list = model.objects.all()
return render_to_response('lists.html', object_list)
But its not working.
how can pass the same object list to template as in Generic View
render_to_response() takes a dictionary of variables to use.
return render_to_response('lists.html', {'object_list': object_list})