Django Templates can not access to context - python

I checked all the questions and answers in this site, but could not find a solution. I am new in Django, trying to develop a storage model and stucked already in the ListView.
part of my view.py:
from django.shortcuts import render, redirect
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from Storage.models import Storage
from django.http import HttpResponse
class StorageListView(LoginRequiredMixin, ListView):
model = Storage
print(Storage.objects.order_by('-barcode'))
template_name = 'Storage/Storagelist.html'
def get_queryset(self):
return Storage.objects.order_by('-barcode')
I add print statement to check whether I reach the model and
everyting seems normal:
<QuerySet [<Storage: 123>, <Storage: 122>, <Storage: 121>]>
However, I can not reach the context from the template file 'Storagelist.html':
<h3>trial</h3>
{% if storage_list %} <h3>trial</h3> {% endif %}
Just to check access via url configurations, I added 'trial' at the beginning of the template and it also seems normal. I also tried to use context_object_name, but did not help either. Somehow, I can not reach to ListView context data from the template.
My versions of applications are as follows:
Django 2.0.3
Python 3.6.1
Can somebody please help me?

In a ListView I believe the objects will populate into the template as object_list. You might consider using this method to make the template context variable human readable (and also match what you are expecting). In other words, try adding context_object_name = storage_list to your view.

Related

I want to use the if statement based on the existence of a web page

So basically i have a complicated scenario. I am current using Django to build a website and i have current made two apps. Both apps have almost identical fields. The field I would want to focus on though is the Information field(which they both have and which i have auto generated with the help of the Wikipedia model)
So the case here is that I want to create an if and else statement in the html in such a way that if the page i am hyperlinking to exists it would go to the link dealing with DetailView but if it doesnt exist I would redirected to the Create View
I should also note that the two apps have their names linked with the help of the foreign key but when i try to open information links using the same name , they gave me different pks
I dont feel like i explained my problem well enough but I hope someone can understand what i mean
UPDATE
ok I create the get function using
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
except Http404:
return redirect('/create/')
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
but i dont know how to use the CreateView fuction i created instead of the link i put
This is the Detail View Html
{%extends "home.html"%}
{%block head_title%} {{block.super}}{%endblock head_title%}
{% block content%}
<!-- verify authentication -->
{% if request.user.is_authenticated%}
<h3>{{object.title}}</h3><br/>
{% endif %}
<ul type="disc">
<div class="container">
<li><b>Artist: </b>{{object.Summary}}</li>
<li><b>Genre: </b>{{object.Genre}}</li>
<li><b>Bio: </b><br>{{object.Bio}}</li>
EDIT
</div>
</ul>
{%endif%}
{% endblock %}
This is my model
from django.db import models
from django.conf import settings
from Blog.models import MainPage
from django.urls.base import reverse
from Blog.Retrieve import retriever
from django.db.models.signals import pre_save,post_save
import InfoPedia
class InfoPedia(models.Model):
user =models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
Name =models.ForeignKey(MainPage,on_delete=models.CASCADE)
Location =models.CharField(max_length= 50,null=True,blank=True)
Information =models.TextField(null=True,blank=True)
TrackListing=models.TextField(null=True,blank=True)
Published=models.BooleanField(default=True)
Timestamp=models.DateTimeField(auto_now=True)
Updated=models.DateTimeField(auto_now=True)
def get_absolute_url(self):
# return f"/Blog/{self.slug}"
return reverse('InfoPedia:DetailView', kwargs={"pk":self.pk})
class Meta:
ordering=["-Updated","-Timestamp"] #orranges in order of updated
def get_tracklist(self):
return self.TrackListing.split(",")
def Information_create_pre_save( instance, sender, **kwargs):
instance.Information=retriever(instance.Name)
def rl_post_save_reciever(sender, instance,created,*args,**kwargs):
print("saved")
print(instance.Timestamp)
pre_save.connect(Information_create_pre_save, sender=InfoPedia)
post_save.connect(rl_post_save_reciever, sender=InfoPedia)
An alternative - rather than checking the if/else in the HTML, just make all the links to the DetailView URL.
Then, in the get() handler for the DetailView, you perform a queryset lookup for the object. If no object is found, then instead of displaying the DetailView HTML, return to the user a 302 redirect (i.e. a temporary redirect) to the CreateView for that object. So all your if/else logic is in the view function or class, instead of HTML.

Convert the Django direct_to_template function to use class based view

I am updating a Django project which used the direct_to_template as a function ie:
return direct_to_template(request, 'bprofile/init.html', targs)
As described a short way down this page
I have seen the SO question here and read the documentation on this page which decribe the migration of statements of the form
('^about/$', direct_to_template, {'template': 'about.html'})
to look like
('^about/$', TemplateView.as_view(template_name='about.html'))
Unfortunatelty I cannot seem to figure out how to change statements from the form that I have into a working new form.
How might one modify this code to work with the new Templateview form?
You shouldn't be using the generic views for this, that's not what they are for. If you want to render a template, you should use the render shortcut: it takes exactly the same arguments.
return render(request, 'bprofile/init.html', targs)
To use TemplateView you import TemplateView into your urls.py:
from django.views.generic.base import TemplateView
Then you just add the urlconf:
('^about/$', TemplateView.as_view(template_name='bprofile/init.html'))

Django - CreateView form on existing view and url

I'm using django generic views in my project CRUD. The CreateView class uses the following url to work:
urls.py
url(r'^create', BookCreate.as_view(model=Books, template_name='Myproj/book_create.html'), name='book_create'),
If I go the www.mywebsite.com/create the form appears just how I wanted it.
My problem is that I want to incorporate the form on another page, that already has a url, a view and a template. The url is like the one bellow:
urls.py
url(r'^author/(?P<id>[0-9]{1,})/$', author_view_handler, name='author_view'),
How can I resolve this?
The CreateView uses a ModelForm. If you want to use it also, you need to create a a Book model form yourself, something like this:
from django.forms import ModelForm
class BookModelForm(ModelForm):
pass
And then instantiate it form=BookModelForm() and pass it to the context of your author_view_handler view.
However I am not really sure why you would want to do something like that...
Update: To pass it to your view, use
from django.shortcuts import render
def author_view_handler(request):
form = BookModelForm()
return render(request, 'author_view_handler.html', {"form": form},
The above just passes the form to the author_view_handler view and does not contain any form handling code.

Django: generic.UpdateView with form_class won't render form

I'm having a really confusing issue with some views in Django. I created Update and Create views, both using the generic versions, both using the same template. They worked perfectly...until I added a custom modelForm to exclude a field. Now, the Create view still works correctly, but the Update view won't render a form at all.
Form:
class member_form(ModelForm):
class Meta:
model=member
exclude=('created_by',)
Views:
class member_detail(generic.UpdateView):
form_class=member_form
model=member
template_name_suffix='_detail'
class member_create(generic.CreateView):
form_class=member_form
model=member
template_name_suffix='_detail'
Urls (main):
url(r'^members/',include(members.urls',namespace=members),name='members_list'),
Urls (app):
url(r'^$',login_required(views.member_list.as_view()),name='index'),
url(r'^(?P<pk>\d+)/$',login_required(views.member_detail.as_view(success_url=".")),name='detail'),
url(r'^new/$',permission_required('members.add_member')(views.member_create.as_view(success_url='/members/')),name='create'),
This worked perfectly for both views until I added the form_class. Now, member_create still works perfectly, but member_detail shows nothing for {{ form.as_table }}. When I switch it to just {{ form }} in that template, I get this for member_detail:
<members.views.member_form object at 0x7f7de3f20d50>
What's going on here? Any ideas? Thanks!
The problem was a stupid naming mistake on my part, on the production code, which I found while trying to redact new sections to add to the question; the _create and _form objects in my question were both named _form in production.

How to add button next to Add User button in Django Admin Site

I am working on Django Project where I need to extract the list of user to excel from the Django Admin's Users Screen. I added actions variable to my Sample Class for getting the CheckBox before each user's id.
class SampleClass(admin.ModelAdmin):
actions =[make_published]
Action make_published is already defined. Now I want to append another button next to Add user button as shown in fig. . But I dont know how can I achieve this this with out using new template. I want to use that button for printing selected user data to excel. Thanks, please guide me.
Create a template in you template folder: admin/YOUR_APP/YOUR_MODEL/change_list.html
Put this into that template
{% extends "admin/change_list.html" %}
{% block object-tools-items %}
{{ block.super }}
<li>
Export
</li>
{% endblock %}
Create a view function in YOUR_APP/admin.py and secure it with annotation
from django.contrib.admin.views.decorators import staff_member_required
#staff_member_required
def export(self, request):
... do your stuff ...
return HttpResponseRedirect(request.META["HTTP_REFERER"])
Add new url into YOUR_APP/admin.py to url config for admin model
from django.conf.urls import patterns, include, url
class YOUR_MODELAdmin(admin.ModelAdmin):
... list def stuff ...
def get_urls(self):
urls = super(MenuOrderAdmin, self).get_urls()
my_urls = patterns("",
url(r"^export/$", export)
)
return my_urls + urls
Enjoy ;)
The easy and accepted way is to override the template.
If you don't want to mess with the Django templates, you could add a Media class to your admin and add some javascript to create the button although I think creating elements with javascript is a bit nasty and should be avoided.
Though other answers are entirely valid, I think it is important to note that it is absolutely not necessary to add a button to get such behavior. You can use admin actions, as you did for the make_published action.
This as the advantage of not requiring to override any template, and thus prevent from potential troubles when upgrading django version (as admin templates may change, and changes might not be "compatible" with the way you overrode it).
import csv
from django.http import HttpResponse
from django.utils import timezone
def export_as_csv(modeladmin, request, queryset):
opts = modeladmin.model._meta
filename = format(timezone.now(), "{app}_{model}-%Y%m%d_%H%M.csv").format(
app=opts.app_label, model=opts.model_name)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
writer = csv.writer(response)
field_names = [f.get_attname() for f in opts.concrete_fields]
writer.writerow(field_names)
for obj in queryset.only(*field_names):
writer.writerow([str(getattr(obj, f)) for f in field_names])
return response
Admin actions are made for this, adding a custom button is one step closer to "over-customization", which means it's probably time to write your own views.
The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.
Quote from the introduction paragraph of Django Admin's documentation

Categories

Resources