I am new to Django and in need of some help. I have my database entries being displayed on a template (6 entries). I am aware that to sort your database objects, you need to write Model_Name.objects.all().order_by('Choose_Sort_Option') in the views.py. I would like to make this function a link in that same template. So far, the only thing I've been able to come up with is making a new view, new url pattern, and new template just to display that one new sort. I don't want have to make 30 pages just for sorting. I am thinking that I need to assign that line of code above to a variable(see product d and product_a below). Then i would call that variable in the template, but I'm not sure how to replace the existing list of database items. In short: How do I create clickable links to sort my database objects all within the same template. This is already done in the admin. Thank you!
my views.py:
from django.http import Http404, HttpRequest
from django.contrib import messages
from vendor_db.models import Itemo
from django.db.models import Q
from django.shortcuts import HttpResponse, HttpResponseRedirect,
render_to_response, render, redirect, get_object_or_404
def index(request):
return render(request, 'vendor_db/index.html')
def vendors(request):
items = Itemo.objects.all()
var_2 = request.GET.get("q")
product_d = Itemo.objects.all().order_by('-Product_Name')
product_a = Itemo.objects.all().order_by('Product_Name')
if var_2:
items = items.filter(Vendor_Name__icontains=var_2)
context = {'items': items,
'product_d' :product_d,
'product_a' :product_a,
}
return render(request, 'vendor_db/vendors.html', context)
my template (it is already displaying all of my database objects in an arbitrary order):
{% extends "base.html" %}
{% block content %}
{% load static %}
<h2>All Vendors</h2>
<h3>Search</h3><div>
<form method='GET' action=''>
<input type='text' name="q" placeholder='Search Vendors'/>
<input type='submit' value='Search'/>
<form action="{% url 'vendors' %}">
<input type="submit" value="Reset">
</form>
</form>
<br>
{% if items %}
{% for stuff in items %}
<a href="{% url 'vendors_detail' stuff.id %}">
{{ stuff.Product_Name|capfirst }}<div></div>
</a>
{% endfor %}
{% else %}
<p>No Results Found</p>
{% endif %}
<h3>Sort by:</h3>
Product Name
{% endblock %}
EDIT
While I am sure the 2 answers below would the do the trick, I was unable to comprehend (my own fault). I places my database entries in a table and used a javascript library to change the sort order just by clicking the column header. You can see the question I asked and the code here
In your model.py class use
Class XYZ()
...................
...................
class Meta:
ordering = [
"your_first_field_name",
"your_second_field_name",
........................
]
You could use a form with a variable as you said, pass the form back to the same view and get the sort option from that and create the sorted query for your product items dynamically or using if statements. Then rerender the page. This means only one view would be needed.
Or you may be interested in an app called django-tables2, it gives you the ability to render a nice table which can then be sorted as you wish by clicking on arrows.
Related
How can I insert spaces in form data?
For example, when I submit this data,
it outputs like this.
How can I fix this?
You can also use the built in linebreaksbr template tag to accomplish this.
You can use a custome template filter, check the documentation on how to set it up:
In file foo_extras.py:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter(name='add_br')
def add_br(value, autoescape=True):
return mark_safe(value.replace('\n', '<br>' ))
And in your html:
{% load bar_extras %}
{% for foo in foos %}
<h1>{{ foo.comment|add_br }}</h1>
{% endfor %}
Could anyone correct my code?
Background:
The user, once on the 'start.html' template, will enter their name and press submit. Then on the next template, 'game.html', there should be a paragraph tab that contains that users name.
Problem:
I must be writting something incorrectly because the user's name does not render on the 'game.html' template. Or, I could also be storing it wrong. Any suggestions or corrections would be very appreciated!
models.py - fp
from django.db import models
class Player(models.Model):
#first player name
fp_name = models.CharField(max_length=30, default='')
forms.py - I'm not sure if this is actually needed...?
from django import forms
class PlayerInfo(forms.Form):
fp_name = forms.CharField(max_length=30, label='First player name')
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, render_to_response
import os
from .forms import PlayerInfo
from .models import Player
def index(request):
return render(request, 'index.html')
def start(request):
if request.method == 'Post':
form = PlayerInfo(request.POST)
if form.is_valid():
obj = Player()
obj.fp_name = form.cleaned_data['fp_name']
return HttpResponseRedirect('/')
else:
form = PlayerInfo()
return render(request, 'start.html')
def game(request):
return render_to_response('game.html', {'obj': Player.objects.all()})
start.html - Meant to submit player one's name
{% extends 'base.html' %}
{% block botRow %}
<form method="post">
{% csrf_token %}
<label for="fp_name">First Player Name</label>
<input id="fp_name" type="text" name="fp_name" maxlength="30" required />
<input type="submit" value="Submit" />
</form>
{% endblock %}
game.html - Meant to render the player one's name
{% extends 'base.html' %}
{% block midRow %}
<p>{{ obj.fp_name }}</p>
{% endblock %}
in your game.html the obj is query set of all Users, so you should walk through the list, look on block for in the docs:
{% extends 'base.html' %}
{% block midRow %}
{% for user in obj %}
<p>{{ user.fp_name }}</p>
{% endfor %}
{% endblock %}
Using User.objects.all() you are getting a Collection of all site's users. It isn't current user. So, the collection doesn't have parameter fp_name. Use request.user to get current logged in user.
Also, there is some redundancy in your code:
Django contains User class with ability to store First Name out of the box. So, you don't need to declare it at all. https://docs.djangoproject.com/en/1.11/ref/contrib/auth/#django.contrib.auth.models.User
There is special class of forms - ModelForm. It helps you to map model's fields to form's fields as fast as possible. (https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/)
There is special class of views - CreateView. It helps you to realize basic logic of model creating. (https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView)
Forms intended to save your time. So, in templates it's better to use built-in rendering engine of forms, than to declare their fields manually. (https://docs.djangoproject.com/en/1.11/topics/forms/#the-template)
If game.html is permitted only for registered users it's a good idea to use #login_required decorator to restrict access to this part of the site.
I have the following in urls.py:
url(r'frameworkslist/(?P<pk>\d+)$', DetailView.as_view(queryset=Category.objects.all().order_by("id"), template_name='home/subcategory.html'))
And in my html template:
{% extends "Layout.html" %}
{% block content %}
{{ subcategory.Name }}
{% for item in object_list %}
<h5> {{ item.Name }} </h5>
{% endfor %}
Back to framework list
{% endblock %}
I was wondering why object_list was empty but when I changed my urls to the following, it worked. (returned the ListView template instead of DetailView):
url(r'frameworkslist/(?P<pk>\d+)$', ListView.as_view(queryset=Subcategory.objects.all().order_by("id"), template_name='home/subcategory.html'))
Also to note, it seems like passing the variable "model=Subcategory" to the DetailView would return the first record (or what should be a single model) of the Subcategory table and pass that to the Template. So my question is two-part, the second being: How do you a collection of objects to DetailView Template?
DetailView is used for viewing a single object, and ListView is for, well, a list of objects. Usually the pattern is you have a ListView which has links to many individual things (like products), and then each product is viewed through a DetailView.
ListView is the one that automatically populates the object_list variable with your queryset.
In case of DetailView, it takes the queryset you provide and then uses the variables in the url to get() a single one. In your example that would be Subcategory.objects.all().order_by("id").get(pk={some number}). This is then given to the template in the object variable by default.
Lots more info on class based views here.
As a side note, you should be using the {% url %} tag in your templates rather than hard coding the urls.
With this HTML:
...
{% for thing in things %}
<form method="post">
{% csrf_token %}
{{ thing.name }}
{{ form.value }}
<input type="submit" value="Submit" />
</form>
{% endfor %}
...
My website lists multiple 'things' from my database, so there can be many forms generated on the one page. How can I somehow determine in my views.py, which 'thing's' form is being submitted?
More elaboration:
Imagine you have a page of objects listed one after the other, and each object has a like button associated with it, that adds a like to the object it is next to. That's essentially what I'm trying to do here.
The problem is, I have a form that can process the like, but how do I take that like and add it to the object that it's displayed next to on the page? (by the aforementioned 'for loop')
I'm completely confused on how to go about this, am I looking at the problem the wrong way, or is there a standard idiom around this problem that I don't know about?
Thank you :)
The most common design pattern for model instance updates is to provide the primary key of an object in the url where you are submitting your post data.
# urls.py
from django.conf.urls import *
from library.views import UpdateThing
urlpatterns = patterns('',
url('^update_thing/(?P<pk>[\w-]+)$', UpdateThing.as_view(), name='update_thing'),
# views.py
def my_view(request, pk=None):
if pk:
object = thing.objects.get(pk=pk)
form = MyModelForm(data=request.POST or None, instance=object)
if form.is_valid():
...
Now, let's specify (using Django's url template tag) that we want to submit post data for each object to the correct url.
{% for thing in things %}
<form method="post" action="{% url 'update_thing' thing.pk %}">
{% csrf_token %}
{{ thing.name }}
{{ form.value }}
<input type="submit" value="Submit" />
</form>
{% endfor %}
The url tag does a reverse lookup through your urls for the name kwarg supplied for a given url, and accepting positional arguments (such as, in this case, thing.pk) and, when needed, keyword arguments.
The standard way to handle multiple forms of the same kind on one page with Django is to use Formsets.
It handles the annoying details like displaying errors on one form while preserving the input on others etc.
However, in your specific case that might be overkill. If you just want to create a like for an object, there isn't really any user input that needs to be validated, so you don't really need a form. Just perform a POST to a specified URL, maybe with Javascript. If the user messes with the URL, you display a 404.
I have a index.html where my form is implemented:
...
{% block searchform%} {% endblock %}
...
In my search/ folder I have two files.
search.html, which is the actual form for the index.html
{% extends 'index.html' %}
{% block searchform %}
<form method="get" action="/results/">
<table>
{{ form.as_table }}
<tr>
<td> </td>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
{% endblock %}
and the file result.html, where I want to see my search results:
{% if query %}
<h3>Results</h3>
...
{% endif %}
urls.py:
from django.conf.urls import include, patterns, url
from dev_devices.views import *
urlpatterns = patterns('',
url(r'^$', include('haystack.urls')),
url(r'^results/$', results, name = 'results')
)
view.py
def results(request):
return render_to_response('results.html')
My problem is, that there are no results showing up. When I click on the submit Button of my form, I will redirected to the correct file (results.html), but no results are showing up. This question exists already but i found no answer, so can someone help me? Thank you !
Well, you aren't passing any results to the template. Check out your views.py:
def results(request):
return render_to_response('results.html')
Your template has this logic:
{% if query %}
<h3>Results</h3>
...
{% endif %}
query is not a variable in context. You'd have to pass the query in from the view:
def results(request):
return render_to_response('results.html', {'query': 'some query'})
But more than that, you need to get the actual results from Haystack and put those in context too. I think you are confused about what's happening here. If you want to use haystacks default views for search/results, then you shouldn't define any custom views at all. The way your results view is defined, how is Django to know this page has anything to do with Haystack at all?
If you do want to define custom views, then those views need to implement Haystack search forms, creation of SearchQuerySets, pagination, (and so on), and pass that data to the template. See the Haystack documentation on creating you own views:
http://django-haystack.readthedocs.org/en/latest/views_and_forms.html#creating-your-own-view
If you just want to see your results and this particular URL structure is not important to you, then just change your form action to point at the same page action="" and move your results display logic from results.html to search.html. That should get you the basic search results that ship with Haystacks default views and forms.