django. Passing id from one template to second template - python

I need to pass id from one template to another template. In template i am iterating over one model
{% for project in all_projects %}
<h3>{{ project.name }}</h3>
{% endfor %}
This going to one template where my url looks like
url(r'^$', views.ProjectsListView.as_view(), name='index'),
url(r'^platforms/$', views.PlatformsIndexView.as_view(), name='platforms'),
url(r'^platforms/nodes/$', views.PlatformsNodesListView.as_view(), name='platforms_list'),
Browser url that i have is http://127.0.0.1:8000/platforms/?project=1
that's ok good. But from second template i need to send third template another parametrs and filters. So how do i can get id of project?
I can not send now project id to third template because i am not iterating over it. How to remember id of project?
views.py
class ProjectsListView(ListView):
template_name = 'project/projects.html'
model = Project
context_object_name = 'all_projects'
class PlatformsIndexView(TemplateView):
template_name = 'project/platforms.html'
class PlatformsNodesListView(ListView):
template_name = 'project/general.html'
model = Platform
context_object_name = 'all_platforms'
def get_queryset(self):
queryset = super().get_queryset()
type_filter = self.request.GET.get('type')
project_filter = self.request.GET.get('project')
if type_filter in [Platform.BACKEND, Platform.ANDROID, Platform.IOS, Platform.FRONTEND]:
queryset = queryset.filter(type=type_filter)
if project_filter:
queryset = queryset.filter(project__id__exact=project_filter)
else:
raise Http404
return queryset
Please explain me.
Thank you in advance

Related

How to query automatically in Django?

I can retrieve data by explicitly giving the 'Id' but I want to retrieve it automatically the top 3 'Id' data. How can I do that. please check my code below and help me out
this is models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.title
this is admin.py
class PostAdmin(admin.ModelAdmin):
list_display = ('id','title')
admin.site.register(Post, PostAdmin)
this is views.py
def index(request):
post3 = get_object_or_404(Post, id=3)
post2 = get_object_or_404(Post, id=2)
post1 = get_object_or_404(Post, id=1)
context = {
"post3": post3,
"post2": post2,
"post1": post1,
}
return render(request, 'contents/index.html', context)
as you can see in the above am giving the id number and it works fine but I want it to retrieve the top id automatically
this is my remplate
<h3>{{post3.title}}</h3>
<h3>{{post2.title}}</h3>
<h3>{{post1.title}}</h3>
You can just use slice on queryset (it will automatically add LIMIT to the SQL query) or take objects specified by index:
posts = Post.objects.all()[:3] # 3 first objects
posts = Post.objects.order_by("-id")[:3] # 3 last objects
post = Post.objects.last() # last object
post = Post.objects.order_by("-id")[0] # also last object, but it's better to use `last` in such case
post = Post.objects.order_by("-id")[1] # pre-last object
Pass it to the context:
context = {"posts": posts}
And then you can process this queryset in template:
{% for post in posts %}
<h3>{{ post.title }}</h3>
{% endfor %}
you should query in views for instance posts = Post.objects.all()[0:3] and then in template use for loop
{% for post in posts %}
{{ post.title }}
If you want to create DetailView you can pass post.id via template and add it as parameter in view, then Post = get_object_or_404(id=post_id)

Django 2.1 recalling old slug url variables

I am having some issues directing a url pattern through the following type of path: Listview --> Listview2 --> DetailView. I am running into trouble with my url patterns. Here is what I am working with:
app_name = 'ism'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<slug:client_slug>/', views.CostCenterListView.as_view(), name='cost_center_list'),
path('<slug:client_slug>/<slug:cost_center_slug>/', views.cost_center_detail, name='cost_center_detail'),
]
The home page of this app is a list of all clients. Clicking on a client will populate a new page showing a list of that client's sub-clients (cost_center).
Here is part of my template {% url %} call to my final path listed above (/slug/slug/):
{% for cost_center in cost_centers %}
<ul>
<li>{{ cost_center }}</li>
</ul>
{% endfor %}
Adding this along with its accompanying view causes an error:
NoReverseMatch at /ism/cleint_slug/
Can you confirm that my issue has to deal with my {% url %} in my template not remembering the first slug in my url path? My error message seems to indicate that it's trying to find:
.../cost_center_slug
instead of:
.../client_slug/cost_center_slug/
My assumption is that django would magically remember the first part of my url pattern (ie client_slug), but that does not appear to be happening. Do I need to bring in more context variables in my view to allow for the calling of two url variables (also is url variable the right terminology? It doesn't sound right) in my template above?
Here is my full error message ('cffd' is a slug representing a cost-center):
Reverse for 'cost_center_detail' with arguments '('cffd',)' not found.
1 pattern(s) tried:
['ism/(?P<client_slug>[-a-zA-Z0-9_]+)/(?P<cost_center_slug>[-a-zA-Z0-9_]+)/$']
Here is my views.py. I was initially trying to work with a DetailView and its get_object method, but I couldn't get that to work in addition to the function based view I shown
class IndexView(generic.ListView):
template_name = 'ism/index.html'
context_object_name = 'client_list'
def get_queryset(self):
queryset = Client.objects.all()
return queryset
class CostCenterListView(generic.ListView):
template_name = 'ism/costcenter_list.html'
context_object_name = 'cost_centers'
def get_queryset(self):
slug = self.kwargs.get('client_slug')
client = Client.objects.get(slug=slug)
queryset = client.costcenter_set.all()
return queryset
def cost_center_detail(request, client_slug, cost_center_slug):
cost_center = get_object_or_404(CostCenter, slug=cost_center_slug)
context = {'cost_center': cost_center}
return render(request, 'ism/costcenter_detail.html', context)
I think you've got a wrong url. It should be either
{% url 'ism:cost_center_list' client_slug %}
or (you don't provide enough argument to construct cost_center_detail url)
{% url 'ism:cost_center_detail' client_slug cost_center.slug %}

Error using DjangoFramework in template

new try of dev here.
Im trying to make a project and I alredy having some issues that i dont know why dont work... I put my code and explain it...
url.py
app_name = 'opotest'
urlpatterns = [
url(r'^$', views.indexView, name='index'),
url(r'^inicio/$', views.ListaView.as_view(), name='inicio'),
url(r'^test/(?P<tipo>.+)/$', views.TestList.as_view(), name='test'),
url(r'^test/(?P<tipo>.+)/run/$',
views.TestDetail.as_view(), name='run'), # this one
View.py
class TestDetail(generic.DetailView):
model = Pregunta
context_object_name = 'lista'
def get_queryset(self):
return Pregunta.objects.all()
HTML template
{% for test in lista %}
<br/>
<p>Pregunta: {{ pregunta.textopregunta }}</p>
{% endfor %}
Models.py
class Pregunta(models.Model):
id = models.AutoField(primary_key=True)
textopregunta = models.CharField('Texto pregunta', max_length=1000)
test = models.ForeignKey(Test, on_delete=models.CASCADE)
def __str__(self):
return self.textopregunta
This code should bring me some 'pregunta' that i have alredy created but it doesnt work... can you please tell me what im doing wrong? the for bring me Pregunta: the textopregunta do not appears...
Thanks everyone
D...
Should be
{% for test in lista %}
<br/>
<p>Pregunta: {{ test.textopregunta }}</p>
{% endfor %}
will work,
but anyway, if you want to use Pregunta.objects.all() , you must use ListView, not DetailView. Like this
class TestList(generic.ListView):
model = Pregunta
context_object_name = 'lista'
{% for test in lista %}
<br/>
<p>Pregunta: {{ test.textopregunta }}</p>
{% endfor %}
UPDATE
If you want to list all your model objects, please use ListView.
1. Change your view to ListView
class TestList(generic.ListView):
model = Pregunta
context_object_name = 'lista'
Then you can use objects and lista both in tempalte.
2. Change your url
You don't need tipo in url, if it's listview.
urlpatterns = [
url(r'^$', views.indexView, name='index'),
url(r'^inicio/$', views.ListaView.as_view(), name='inicio'),
url(r'^test/(?P<tipo>.+)/$', views.TestList.as_view(), name='test'),
url(r'^test/run/$',
views.TestList.as_view(), name='run'), # this one
3. use objects or lista in templates.
Because you define lista in context_object_name : it means your objects list will be used with lista in template. (you can use objects cause django ListView automatically make context for you)
{% for test in lista %}
<br/>
<p>Pregunta: {{ test.textopregunta }}</p>
{% endfor %}
UPDATE for DetailView
1. Change urls with pk
Above all, you have to understand about View - Template and urls.
In your urls - you should pass params what you want to use to grep your one specific object. It should be unique, so just use pk(id). (Or you can make your own unique slug)
url(r'^test/run/$',
views.TestList.as_view(), name='run'), # this one
# this is DetailView
url(r'^test/(?P<pk>\d+)/$',
views.TestDetail.as_view(), name='run'), # this one
Then your url will be.. test/1/ , test/2/.
2. change views
Actually, django CBV supports many functions (method) so you don't have to handle more but it's hard to understand.
class TestDetail(generic.DetailView):
model = Pregunta
context_object_name = 'lista'
You're confusing when you don't know about DetailView.
In DetailView, (as you can see here-ccbv.co.kr ) it has get_object() method. If any url_kwargs defined in your view, it use pk for basic. So it will find like Pregunta.objects.get(id=self.kwargs.get(pk)) that takes from your urls.py.
Then you can use your object in template, using lista or object.
<br/>
<p>Pregunta: {{ lista.textopregunta }}</p>
You DONT have to forloop all objects (actually CANT) because DetailView basically find your object from your kwargs (in this situation, pk).
I highly recommend reading django docs (CBV) and seeing ccbv.co.kr for understanding CBV, or trying to use FBV in django.
try to override the get_context_data() method, as below then change your template also,
class TestDetail(generic.DetailView):
model = Pregunta
context_object_name = 'lista'
def get_queryset(self):
return Pregunta.objects.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['sample'] = self.get_queryset()
return context
Try to change your template as below,
{% for test in sample %}
<br/>
<p>Pregunta: {{ test.textopregunta }}</p>
{% endfor %}
By default Generic.DetailView looks for pk in the url parameters which is used to search data from your database. In your case you are using tipo as url parameters. So, you need to override the default inside your view. Your code should be something like this:
class TestDetail(generic.DetailView):
model = Pregunta
context_object_name = 'lista'
pk_url_kwarg = 'tipo'
def get_queryset(self):
return Pregunta.objects.all()
Now it will
look for tipo in your url and take the parameters to search from your database. More on Generic views can be found on this link: https://ccbv.co.uk/projects/Django/1.10/django.views.generic.detail/DetailView/

Django: Get all objects from a specific user

I have a problem when trying to display all the Announce objects from a user.
My problem is : Consider that I am logged in as a user with an id=1. When I go to /users/1/ it displays all my posts. But the problem is when I want to display all the posts from another user with id=2 by going to /users/2/, it still display all my Announce objects, and not the user with the id=2.
models.py
class Announce(models.Model):
owner = models.ForeignKey('auth.User', related_name='announces')
created_date = models.DateTimeField(auto_now_add=True)
body = models.TextField(max_length=1000)
views.py
class UserAnnouncesList(ListView):
model = Announce
template_name = 'myApp/user_announces_list.html'
context_object_name = 'all_announces_by_user'
def get_queryset(self):
return Announce.objects.filter(owner=self.request.user)
urls.py
urlpatterns = [
url(r'users/(?P<pk>[0-9]+)/$', views.UserAnnouncesList.as_view(), name='user_announces_list'),]
user_announces_list.html
{% extends "account/base.html" %}
{% block content %}
{% for announce in all_announces_by_user %}
<h1>{{announce.user.username}}</h1>
<p>{{announce.body}}</p>
{% endfor %}
{% endblock content %}
Do I have to use some kind of like : Announce.objects.get(pk=???) ?
I appreciate your help!
The request.user is the user that is logged in. You need to use the pk that is passed as url. This is stored in the kwargs dictionary of the listview:
class UserAnnouncesList(ListView):
model = Announce
template_name = 'myApp/user_announces_list.html'
context_object_name = 'all_announces_by_user'
def get_queryset(self):
return Announce.objects.filter(owner=self.kwargs['pk'])

Django Detailview display properties of parent

I'm trying to use DetailView. I don't have a deep understanding of it.
What I'm trying to do is display the properties of an object from the pk. That is, I'm at, say, /notendur/34, and I want to display information about the object with pk=34.
I'm trying to make sense of this:
https://docs.djangoproject.com/en/dev/intro/tutorial04/
But I can't make sense of it. Perhaps one of you can help me understand? I'm looking at the second block of code in that link, not the first one.
{% extends "index.html" %}
{% block content %}
{{ "placeholder" }}
{% endfor %}
{% endblock %}
I'm looking to use the HTML to fetch the pk from /notendur/34 for example.
The detail view automatically pass object with primary key 34 named as object in context. You can access that in template e.g. {{ object.pk }} or {{ object.some_property_name }}
First of all in your views you need to load the appropriate class:
from django.views.generic import (
DetailView,
)
According to the Class Based View Inspector (keep a ref on this link):
http://ccbv.co.uk/
The DetailView has the following properties:
content_type = None
context_object_name = None
http_method_names = [u'get', u'post', u'put', u'patch', u'delete', u'head', u'options', u'trace'] View
model = None
pk_url_kwarg = 'pk'
queryset = None
response_class = <class 'django.template.response.TemplateResponse'>
slug_field = 'slug'
slug_url_kwarg = 'slug'
template_name = None
template_name_field = None
template_name_suffix = '_detail'
As you can see from the above, when the DetailView is called, it will check first for the existence of a pk or slug argument in the request,
this is done in your urls.py file:
urlpatterns = patterns('',
...
url(r'^view/(?P<slug>[\d]+)/$', MyTestDetailView.as_view(), name='myurl-name'),
...
)
By defining the slug parameter in the url, the DetailView knows which item you request details for (alternative you could use pk, but slug makes more friendly urls).
It then will fetch the model or the queryset (defined in your view) based on either the slug or pk field, this is performed in the def get_object(self, queryset=None) method.
After grabbing the model (if it fails it raises a 404 error) you can use the object within your template (specified under the template_name property) as:
{{ object }}
If you want to change the name of the template variable, you can assign a context_object_name property. A quick example is bellow:
from django.views.generic import (
DetailView,
)
from myapp.models import (
MyModel,
)
class MyTestDetailView(DetailView):
"""
Set context object name to mytemplatevar
"""
context_object_name = "mytemplatevar"
"""
Define the model to use
"""
model = MyModel
"""
Define the template
"""
template_name = "myapp/detail_view.html"
Appart from that you don't need anything else, in your template then you can access your object:
{{ mytemplatevar.something }}

Categories