On the index page of my Django site I generate a list of urls that allow the user to navigate to a detail page. Once the detail page appears the navigation is no longer visible.
What I am trying to achieve is that the navigation list appears on the detail page (and every page that is added to my site).
What I have tried is the following: (the first line in each view is duplicated)
def index(request):
**collection_urls = Collection.objects.order_by('the_year')**
return render(request, 'index.html', {'collection_url': collection_urls})
def originalexample(request, collection_id):
**collection_urls = CarCollection.objects.order_by('the_year')**
car = get_object_or_404(CarCollection, pk=collection_id)
return render(request, 'detail.html', {'originalexample': car, 'collection_url': collection_urls})
Whilst this works, I know it is not right as I running the query twice. My next thought would be to perform the query once and then pass it to the pages as they are rendered. If so how would I do that? or is there a more pythonic method?
In case of need I'm using Django 1.6.2 and the list of urls does not change frequently (They can only be changed via the Django admin screens)
Thanks in advance.
You don't want to pass them from one to another, you simply want them to appear everywhere. That is usually done via context processors or custom tags.
Related
how to handle two different views witch match for the same url? (Both views need a database call to determine if the called element is available. Changing the url structure is not an option.)
url(r'^', include(wagtail_urls)),
This wagtail url is matching all url's and is raising an 404 if the according page/slug is not in the database.
But, I also have my own view witch behaves similar. How can I tell django to continue with the next url instead of raising a 404?
(I could place my own view before the wagtail view and modify it, but I don't know how to return to the next url?)
This is my solution at the end:
from wagtail.wagtailcore.views import serve
# ... in my view where I normally return a 404 => I set this:
return serve(self.request, self.request.path)
First of all, Sharing same url pattern in diffrent views is bad idea.
The bigger your project, the harder it will be to maintain it.
Nevertheless, there is a way if you want that way.
You can place your own view first in urls.py like your saying,
process some your own logic first and catch 404 exception when there is nothing to show in your view than simply call the "Wagtail" view with request original parameters(page, slug, etc..) with return statement.
Below is example.
This example is based on Django functional based view, but there is the way in class based view something like this.
def your_own_view(request, slugs):
try:
article = get_object_or_404(Article, slugs=slugs)
except Http404:
return some_wagtail_view(request, slugs)
...
return render(request, "article/view.html", context)
I have a view (views.loaditems) which runs some algorithm and passes items to a template(product.html) where the items are loaded, and with each item, I have a "add_to_shortlist" link. On clicking this link, the item is added in the user's shortlist (for which I have a function). I want that on click, the page is not reloaded and has its items, but simply add that item to the user's shortlist. Also, where should I define this shortlist function?
I'm new to Django, and any help would be much appreciated. Thanks.
Update: Here's my code:
views.py
def loaditems(request):
#some code
ourdeals = SDeals.objects.filter(**{agestring3:0})
sorteddeals = ourdeals.order_by('-total_score')
user = request.user
context = {'deals': sorteddeals, 'sl_products':sl_products, 'user':user,}
template='index.html'
return render_to_response(template, context, context_instance=RequestContext(request))
def usersl(request, id, id2):
userslt = User_Shortlist.objects.filter(id__iexact=id)
products = SDeals.objects.filter(id__iexact=id2)
product = products[0]
if userslt:
userslt[0].sdeals.add(product)
sl = userslt[0].sdeals.all()
return render_to_response('slnew.html', {'sl':sl}, context_instance=RequestContext(request))
in my index.html I have:
<div class="slist"></div>
which in urls.py takes me to views.usersl:
url(r'^usersl/(?P<id>\d+)/(?P<id2>\d+)/$', views.usersl),
I don't want to go to slnew.html, instead be on index.html without reloading it, and on click 'slist', just run the function to add to shortlist.
In order to make changes on the server and in a page without navigating with the browser you need to look at JavaScript solutions. Read up about Ajax. In essence you need to use some JavaScript to send the update to the server, and to change the HTML.
JQuery is one popular library that will help you to do this. A more sophisticated example is AngularJS. On the Django side you'll write some views that handle these small update tasks used in the page. Libraries like Django REST framework or Django Slumber will help you with that.
We have these moderately large and constantly growing tables and the most interesting stuff is always the most recent. Currently we have them ordered by creation time, so the interesting stuff is at the end. This requires 2 clicks when navigating, one to select the model and another select the last page.
I could of course change the order so the most recent stuff is at the front, but then the content of the pages would be continually changing as new stuff is pushed on the front, making exploration of the history harder.
So I was wondering if there was a way to have it go straight to the last page?
You can alter the change_list template (the pagination block) to show {{page.last}}
https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_list.html
This is a pretty peculiar request, but you could redirect the admin view if there is no page parameter in the URL (i.e. you are on the frontpage).
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
class MyAdmin(admin.ModelAdmin):
...
def changelist_view(self, request, extra_context=None):
if not request.GET.get("p", False):
return redirect("%s?p=%s" % (
reverse("admin:my_app__model__changeview"),
self.paginator.page_range[-1])
super(MyAdmin, self).changelist_view(request, extra_context=extra_context)
an alternative is to inject a p URL paremeter into the request before passing control over to the parent changelist_view method (but this requires copying the request). Edit: Wouter's solution is actually nice and simple
Hi Stackoverflow people,
In my Django project I created a form to register users. This forms can be called through a specific url -> view method. Once the user has filled in the form, presses submit, the same view method will be called and if form.is_valid() is true, then ... simply a standard form, nothing special.
Now, I would like to integrate this little form on every page, and therefore I would like to add it to the base template. I have read that I could populate the form variable through a context_processor, but could I define the process after the submission of the form?
I have created the context_processor.py (as below), added the context_processor to the TEMPLATE_CONTEXT_PROCESSOR dir in the settings (as described here):
from app.forms import Form
def registration_form(request):
return {
registration_form : Form()
}
First of all, the form variable won't be displayed.
And secondly, how do I manipulate the form submission?
I think I misunderstanding the context_processor of Django and would be more than happy about comments on the overall process.
Thank you!
how are you trying to access to form in your template? you probably don't want to use a function name as your dictionary key, maybe you want
return {
'registration_form': Form(),
}
not sure what you mean by manipulate the form submission, but i guess you'd need all the form processing logic in your context processor
if request.POST:
form = Form(request.POST)
# validate etc
instead of creating context processor, create template tag for the purpose and place the tag in base.html
for form submission and displaying errors use ajax, and front-end validations.
I have a purchase page, it can take an optional argument as a gift, if it is a gift, the view passes a gift form to the template and if not, a regular purchase form.
my old regular url, which redirects to two seperate views:
(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view'),
(r'^(?P<item>[-\w]+)/purchase/gift$', 'gift_view'),
and the views was like this:
def purchase_view(request,item):
....use purchase form
def gift_view(request,item):
....use giftform
It is a bad design indeed, as both views having are almost everything same but the forms used.
I have also thougt about using GET and giving gift as a GET param however it wasnt a good idea as I am using POST method for these pages, especially would cause issue after validation.
How can I make this a single url and a single view?
Thanks
urls.py
url(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view', name='purchase_view'),
url(r'^(?P<item>[-\w]+)/purchase/(?P<gift>gift)/$', 'purchase_view', name='gift_view'),
views.py
def purchase_view(request, item, gift=False):
if gift:
form = GiftForm
else:
form = PurchaseForm
...