How do I input two views in a template - django

I am trying to create a template that contains a form that creates something and a list of those somethings.If I have the views
def list_of_something(request):
list1=something.objects.all()
return render(request , 'index.html' ,{'list1':list1})
def post_something(request):
form_class=SomethingForm
if request.method="POST":
form=form_class(request.POST)
if form.is_valid():
.........
........
........
return render(request, 'post_something.html', {'form': form,})
This is what I have done.
I have tried the include putting {% include "post_something.html" %} into index.html, it loads the post_something.html but when it gets to {{form.as_p}}it doesnt load it?
I have checked out Class-based view,but i dont know how to use it to do the above.
UPDATE
Thanks to the answers below.What I did was add {% include "post_something.html" %} to index.html.and pass the name of the form to the view return render(request,'index.html,{'list1':list1,'form':SomethingForm()}) .
And additionally,point your form action attribute to post_something view and it should work.

post_something.html is just the name of the template, you still need to pass in the form. I'm assuming you're trying to show the list_of_something view so you need to include the form in the context data of that view.
return render(request , 'index.html',{'list1':list1, 'form': SomethingForm()})

Assume that the contents of post_something.html will be merged to index.html when you use {% include %} tag. Now you need to pass all the variables in the merged template from your view. It should be like this:
return render(request,
'index.html',
{'list1':list1, 'form': form})
You can define the form based on your business use case.

Related

Django view return data

I have a view that returns an HTML response using render. The data returned is specific to a template.
If I want to consume that data on another page, should I write another view with the same logic, or is there a way to pass the data from view 1 to view 2
view
return render(request, 'pages/project_details.html', {"project": project,
urls
path('show_project_details/<project_id>', view=show_project_details, name="show_project_details"),
I know that a view is just a function, which takes a request and does something with it, but I don't get how I make a request to a view within a template and consume the response within an existing page.
Example here:
## filename: views.py
from django.shortcuts import render
from .models import Team
def index(request):
list_teams = Team.objects.filter(team_level__exact="U09")
context = {'youngest_teams': list_teams}
return render(request, '/best/index.html', context)
I want to return the data within this context to home.html and index.html.
Hope this makes sense?
You can use your urls.py to pass a variables through via the URL notation.
For example - Getting Team info:
template
{% for team in youngest_teams %}
Team
{% endfor %}
url.py
path('team_info/<team_id>', view=team_info, name="get_team_info")
views.py
def team_info(request, team_id=None):
team = Team.objects.get(id=team_id) #Information on team is passed.
There are multiple cases in your case. Let me explain them one by one.
Let's say you have two templates. One is template 1 and the other is template 2.
If you want to use the same logic for template 1 and template 2. You can use a variable in the views.py & url.py and use a condition there on that variable which is team_id in your case. E.g.
def index(request, team_id):
list_teams = Team.objects.filter(team_level__exact="U09")
context = {'youngest_teams': list_teams}
if team_id == 1:
return render(request, '/best/index.html', context)
elif: team_id == 2:
return render(request, '/best/template2.html', context)
And in urls.py, you can write:
path('team_info/<int:team_id>', view=team_info, name="get_team_info")
If you don't want the variable in the views and URLs. Then you can write different views with the same code in views.py. But in the case of multiple ids, it will cause code duplication.

render multiple template from a single view in django

I want to send context data to one html and want to render different html.
After login user is redirected to this dashboard view. Here I want to render two html file, the context value will be sent to one html let say temp1.html file, but user can see temp2.html file. In temp2.html and other html file, I will include temp1.html file. Is there any way to do so?
views.py
def dashboard(request):
print('in dashboard view')
object = UserSelection.objects.get(user=request.user)
if object.user_type == 'candidate':
val_cand = CandidateDetail.objects.filter(candidate_username=request.user)
if val_cand:
print('Candidate filled data') #Already filled data
data = CandidateDetail.objects.get(candidate_username=request.user)
return render(request, 'dashboard.html',{'obj':object.user_type, 'data':data})
else:
print('new user') #Registered but not filled data
return render(request, 'dashboard.html', {'obj':object.user_type})
else:
val_emp = EmployerDetail.objects.filter(name=request.user)
if val_emp:
print('Employer filled data') #Already filled data
data = EmployerDetail.objects.get(name=request.user)
return render(request, 'dashboard.html',{'obj':object.user_type, 'data':data})
else:
print('new user') #Registered but not filled data
return render(request, 'dashboard.html', {'obj':object.user_type})
You can't render two html file in single view. Please use the Django template language for the desired behaivour.
i.e) If your passing obj to dashboard.html and inside html files can also access obj.
dashboard.html
{{ obj }}
{% include 'test1.html' %}
{% include 'test2.html' %}
You can pass additional context to the template using keyword arguments:
{% include 'test1.html' with obj=obj additional_context='blah' %}
test1.html
{{ obj }}

django 2: rendering both single post and suggested posts on a template

I am using Django 2 and I would like to display in a single article blog page both the body of that article and, at the bottom, 3 recommended articles.
Unfortunately the display 3 articles part doesn't work. I receive no error it just doesn't display any part of the block from the loop more specifically:
my view
def detail (request, post_slug):
post = get_object_or_404 (Post, slug=post_slug)
suggested = Post.objects.all()[:3]
return render (request, 'detail.html', {'post':post}, {'suggested':suggested})
and the html to display the suggested
<section class="read-next">
{% for a in suggested.all %}
<a href="/{{a.slug}}" class="prev-post " style="background-image:url({{a.image}})" >
<div class="info">
<div class="tag">We recommend</div>
<h3 class="post-title">{{a.title}}</h3>
</div>
</a>
{% endfor %}
</section> <!-- .read-next -->
nothing gets rendered of this section or for wherever I add the loop.
Thanks in advance for your help!
A couple things are the issue here.
render is called wrong. The format of render is like so:
return render(request, template_name, context)
context is a single dictionary that can be used to place variable values on the html page.
You are sending two separate dictionaries to render. So context right now for you is only a dictionary with one key: "post". The dictionary that contains suggested is set to content_type instead of being sent to context.
So your view needs to become:
def detail (request, post_slug):
post = get_object_or_404 (Post, slug=post_slug)
suggested = Post.objects.all()[:3]
context = {
"post": post,
"suggested": suggested
}
return render (request, 'detail.html', context)
Because you sliced the queryset of Post objects (suggested = Post.objects.all()[:3]), it is now a queried list, not a usable queryset. So you treat it as if it's a list. Basically what this means, is that you don't use {% for a in suggested.all %} because suggested no longer has a method called all after slicing it.
So your template should use {% for a in suggested %} instead of {% for a in suggested.all %}. The reason it didn't work this correct way before is because suggested wasn't even in the context before because of issue #1.
When you call render you should return a single context dictionary:
return render(request, 'detail.html', {'post':post, 'suggested':suggested})
The fourth argument to the render shortcut is content_type, so your current code is equivalent to:
return render(request, 'detail.html', context={'post':post}, content_type={'suggested':suggested})

Django render templates from seperate app's in one template file

I need to display content of two templates (from different views) on 1 webpage (these are login and registration form side by side, sooner or later i will include other apps).
So I created index.html for displaying both templates - login.html and register.html - by usage of {% include %} templatetag. However, when it came to validation of registration form after i typed incorrect values i got redirected to template that I've imported.
How I can solve my issue of having forms from two completely seperate views in other (third) template?
How I can solve my issue of having forms from two completely seperate
views in other (third) template?
You should specify the action attribute of your form.
You can use a context variable (for example 'type') to distinguish between the two forms in same template.
In view1:
if login_form.is_valid():
# do something
return render_to_response("home.html", context_instance=RequestContext(request))
else:
return render_to_response("index.html", {"login_form": login_form, "type": "login"}, context_instance=RequestContext(request))
In view2:
if register_form.is_valid:
# do something
return render_to_response("home.html", context_instance=RequestContext(request))
else:
return render_to_response("index.html", {"register_form": register_form, "type": "register"}, context_instance=RequestContext(request))

Django: How to include modelform?

{% include 'django.contrib.auth.views.login' %}
I don't want to write everything by hand.. I hate this really, django full of automatic stuff.
Goal is to include registration/login.html into base.html, so that I could have this form in every page
If I include only template itself (registration/login.html), problem appears that "form.login", I mean "form" var is not defined because this one comes from VIEW which called when you going to login url. So how can I call that view MANUALLY with include or at least to grab django.contrib.auth.views.login variables by my self in my own view and pass then to base.html?
P.s. It's not just about login form, I think there will be more situations like this
I have found better solution in #django irc.
They called inclusion tags
I'll give you my code, because I got lot's of problem learning new stuff in django =)
file: templatetags/form_login.py
from django import template
register = template.Library()
from django.contrib.auth.forms import AuthenticationForm
#register.inclusion_tag('registration/login.html')
def form_login():
return { 'form': AuthenticationForm() }
Now you can have your form anywhere, this will prerender template and THAT'S IT! no stupid context processors which requires to modify whole project settings.py, which is really sux if you writing stand alone little application..
If you need login-form on every page
Create a context processor:
def login_form_processor(request):
return {
'login_form': LoginForm(request.POST or None)
}
Add it to settings.CONTEXT_PROCESSORS.
Include the template for login form:
{% with login_form as form %}
{% include "registration/login.html" %}
{% endwith %}
You can also make you form lazy-loading, so form will not be created until it is used for the first time.
from django.utils improt functional
def login_form_processor(request):
create_login_form = lambda: LoginForm(request.POST or None)
return {
'login_form': functional.lazy(create_login_form, LoginForm)
}
But I guess you won't want the lazy-loading feature, because login-form is cheap to initialize.
Reusing views
Concerning the "grabbing variables" part from your question: you cannot grab variable from view. Django view is method which returns response object. You can not get variables from response. However some of views accept extra_context and other attributes. Those attributes allow you to configure those views in urls, or to wrap them with your own view, for example:
def my_login_view(request):
some_extra_data = get_some_data()
extra_context = {
'some_extra_var': some_extra_data
}
return login_view(request, extra_context=extra_context, template="my_template.html")
This is not exactly grabbing the variables from views, more like augmentation of existing views.
If you expect to have more situations like this, do less data-porcessing in views. Call some methods which checks for permissions. Collect some data from context-processors. Return rendered response. Now you can reuse the data in other views.
You can specify the action on the form html to point to the URL that accesses the corresponding view.
If you want a form, say called as login_form always populated in all templates, then put it in the context_processors.
Browsing the code for django.contrib.auth.views, you will see that the variables form, site and *site_name* are passed to the template.
Either you (1) provide your custom registration form or (2) you can just import django.contrib.auth.forms.AuthenticationForm in your view if you want to use it.