Form input to a template - django

EXPECTED OUTPUT
Assuming that the user enters "anaconda" in the Form:
Hashtag Search Results
You searched for: anaconda
ACTUAL OUTPUT
Hashtag Search Results
1) You searched for: <QuerySet [<Hashtag: >, <Hashtag: anaconda>]>
CODE
models.py
from django.db import models
class Location(models.Model):
""" Model representing a Location, attached to Hashtag objects through a
M2M relationship """
name = models.CharField(max_length=1400)
def __str__(self):
return self.name
class Hashtag(models.Model):
""" Model representing a specific Hashtag serch by user """
search_text = models.CharField(max_length=140, primary_key=True)
locations = models.ManyToManyField(Location, blank=True)
def __str__(self):
""" String for representing the Model object (search_text) """
return self.search_text
def display_locations(self):
""" Creates a list of the locations """
# Return a list of location names attached to the Hashtag model
return self.locations.values_list('name', flat=True).all()
forms.py
from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from .models import Location, Hashtag
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean_hashtag(self):
data = self.cleaned_data['search_text']
# Check search_query doesn't include '#'. If so, remove it.
if data[0] == '#':
data = data[1:]
# return the cleaned data
return data
class Meta:
model = Hashtag
fields = ['search_text',]
labels = {'search_text':_('Hashtag Search'), }
help_texts = { 'search_text': _('Enter a hashtag to search.'), }
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from .models import Location, Hashtag
from .forms import SearchHashtagForm
def hashtag_search_index(request):
""" View function for user to enter search query """
# If POST, process Form data
if request.method == 'POST':
# Create a form instance and populate it with data from request (binding):
form = SearchHashtagForm(request.POST)
# Check if form is valid
if form.is_valid():
search_text = form.cleaned_data['search_text']
form.save()
# redirect to a new URL
return HttpResponseRedirect(reverse('mapping_twitter:results'))
# If GET (or any other method), create the default form
else:
form = SearchHashtagForm()
context = {'form':form, 'search_text':Hashtag.search_text}
return render(request, 'mapping_twitter/hashtag_search_index.html', context)
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
qs = super(SearchResultsView, self).get_queryset()
return qs
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = Hashtag.objects.all()
return context
results.html
<h1>Hashtag Search Results</h1>
<p>1) You searched for: {{ search_text }}</p>
{% for obj in queryset %}
<p>2) You searched for: {{ obj.search_text }}</p>
{% endfor %}

I think you should pass the queryset of the Model HashTag as you need to render out hashtag.search_text which is an element of that model.
So you can pass the queryset in the view and for loop through it and print all the search_text or pass the object alone and render out its search_text.
context = {
'queryset': qs
}
{% for obj in queryset %}
<p>{{ obj.search_text }}</p>
{% endfor %}

This is my guess, correct me if I am wrong.
For a template to display something, you have to send context or data to that template to print, how can it print something when you don't send anything. So,
context.update({
'hashtag': //value you want to send.
})

Related

how to get a data from database of django and display it in html

I am new to django and i am trying to get data from the database based on a key and include it into html
this is my models.py
from django.db import models
# Create your models here.
class Car(models.Model):
billing_number = models.BigIntegerField(primary_key=True)
customer = models.CharField(max_length=100)
price = models.IntegerField()
purchase_date = models.DateTimeField()
company = models.CharField(max_length=100)
model = models.CharField(max_length=100)
serial_number = models.BigIntegerField()
mfg_date = models.DateTimeField()
shipping_date = models.DateTimeField()
This is my forms.py
from django.forms import ModelForm
from .models import Car
class CarForm(ModelForm):
class Meta:
model = Car
exclude = ()
class CarAccessForm(ModelForm):
class Meta:
model = Car
fields = ('billing_number',)
This is my views.py
from __future__ import unicode_literals
from django.shortcuts import render
from django.views.generic import TemplateView
from django.http import HttpResponseRedirect, HttpResponse
# Create your views here.
from .forms import CarForm, CarAccessForm
def add_car(request):
if request.method == 'POST': # data sent by user
form = CarForm(request.POST)
if form.is_valid():
form.save() # this will save Car info to database
return render(request,'saved.html')
else: # display empty form
form = CarForm()
return render(request, 'add_car.html', {'car_form': form})
def get_car(request):
if request.method == 'POST': # data sent by user
form = CarAccessForm(request.POST)
if form.is_valid():
form.save() # this will save Car info to database
return render(request,'saved.html')
else: # display empty form
form = CarAccessForm()
return render(request, 'get_car.html', {'car_form': form})
how can i change them to display data based on key value
If you want to get data without change page use Ajax (Asynchronous JavaScript)
send data from ajax to view
In the view, prepare the data as json and return them
to return them you can use JsonResponse

Set form input as variable in get_queryset

AIM
I wish to render results.html with all the locations associated with the search_text entered by the User.
To do so, I am attempting to filter the results in get_quersey(), but am struggling to set the form_input variable. I am currently using form_input = self.request.GET.get('search_text').
CODE
models.py
import re
from django.db import models
from twython import Twython
class Location(models.Model):
""" Model representing a Location (which is attached to Hashtag objects
through a M2M relationship) """
name = models.CharField(max_length=1400)
def __str__(self):
return self.name
class Hashtag(models.Model):
""" Model representing a specific Hashtag serch by user """
search_text = models.CharField(max_length=140, primary_key=True)
locations = models.ManyToManyField(Location, blank=True)
def __str__(self):
""" String for representing the Model object (search_text) """
return self.search_text
def display_locations(self):
""" Creates a list of the locations attached to the Hashtag model """
return list(self.locations.values_list('name', flat=True).all())
forms.py
from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from .models import Location, Hashtag
class SearchHashtagForm(ModelForm):
''' ModelForm for user to search by hashtag '''
def clean_hashtag(self):
data = self.cleaned_data['search_text']
# Check search_query doesn't include '#'. If so, remove it.
if data[0] == '#':
data = data[1:]
return data
class Meta:
model = Hashtag
fields = ['search_text',]
labels = {'search_text':_('Hashtag Search'), }
help_texts = { 'search_text': _('Enter a hashtag to search.'), }
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from django.views.generic.edit import FormView
from .models import Location, Hashtag
from .forms import SearchHashtagForm
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
template_name = 'mapping_twitter/hashtag_search_form.html'
form_class = SearchHashtagForm
def get_success_url(self):
return reverse('mapping_twitter:results')
def form_valid(self, form):
# the method is called when valid form data has been POSTed, and returns an HttpResponse
form.clean_hashtag()
form.save()
return super().form_valid(form)
def form_invalid(self, form):
# Check if the search_text is invalid because it already exists in the database. If so, render results.html with that search_text
search_text = self.request.POST.get('search_text')
if search_text and Hashtag.objects.filter(pk=search_text).exists():
return HttpResponseRedirect(reverse('mapping_twitter:results'))
else:
return super(HashtagSearch, self).form_invalid(form)
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
# ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
qs = Hashtag.objects.all()
form_input = self.request.GET.get('search_text')
if form_input:
qs = qs.filter(search_text__iexact=form_input)
return qs
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = Hashtag.objects.all()
return context
In get_context_data you don't use get_queryset method at all. You just write another query which fetch all Hashtag objects. You should rewrite it to this:
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
context['search_text'] = self.get_queryset()
return context
Note self.get_queryset() is using instead of Hashtag.objects.all().
Also note to use self.request.GET.get('search_text') you need to pass search_text as GET argument when performing redirect in HashtagSearch view:
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
template_name = 'mapping_twitter/hashtag_search_form.html'
form_class = SearchHashtagForm
def get_success_url(self):
return '{}?search_text={}'.format(reverse('mapping_twitter:results'), self.request.POST.get('search_text'))
UPD
But isntead of two views I recommend you to use single ListView. Just add GET form to your results.html and simple override get_queryset method:
# template
<form method="GET" action="">
<input type="text" name="search_text" placeholder="Search post" value="{{ request.GET.search_text }}">
<input type="submit" value="Search">
</form>
# view
class SearchResultsView(generic.ListView):
""" Generic class-based view listing search results of locations """
model = Hashtag
template_name = 'mapping_twitter/results.html'
def get_queryset(self, **kwargs):
# ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
qs = Hashtag.objects.all()
form_input = self.request.GET.get('search_text')
if form_input:
qs = qs.filter(search_text__iexact=form_input)
return qs

Querying a django DB with model forms

Okay, so I'm trying to teach myself django by trying to put together a simple DB query application.
So I have in my DB a relation mysql table storing triples (RDF, subj, obj, pred) and I have written a model form with the fields to query that. Though, I have initially setup my form to store the queries in a separate table. What I would like to do however, is the model form I created to instead query the triple table.
Here is my code:
view:
from django.shortcuts import render, get_object_or_404, render_to_response
from django.template import RequestContext
# Create your views here.
from .forms import QueryForm
from .models import Query
def queries_create(request):
form = QueryForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"title":"Create",
"form": form,
}
#return HttpResponse("<h1>create</h1>")
return render(request, "query_form.html", context)
model:
from __future__ import unicode_literals
from django.db import models
from django.core.urlresolvers import reverse
# Create your models here.
class Query(models.Model):
studyName = models.CharField(max_length=250)
population = models.IntegerField()
intervention = models.CharField(max_length=250)
comparison = models.CharField(max_length=250)
outcome = models.CharField(max_length=250)
outcomeTiming = models.CharField(max_length=250)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.studyName
def get_absolute_url(self):
return reverse("queries:detail", kwargs={"id": self.id})
#return "/queries/%s/" %(self.id)
form:
from django import forms
from .models import Query
class QueryForm(forms.ModelForm):
class Meta:
model = Query
fields = [
"studyName",
"population",
"intervention",
"comparison",
"outcome",
"outcomeTiming",
]
html:
<!--DOCTYPE html -->
<html>
<body>
<h1>Query the Model</h1>
<form method='POST' action=''>{% csrf_token %}
{{ form }}
<input type='submit' value='Query!' />
</form>
</body>
</html>
Any help would be appreciated I've tried several modifications but nothing seems to be working.
You need to handle the data differently for the form. Instead of saving it you need to extract the data and query for matching:
def query_queries(request):
form = QueryForm(request.POST or None)
if form.is_valid():
# this is the same as doing
# Query.objects.filter(studyName=form.cleaned_data['studyName']...)
queries = Query.objects.filter(**form.cleaned_data)
context = {
'queries': queries
}
return render(request, "query_queries.html", context)

Editing existing entries in Django forms

My problem is similar to how to edit model data using django forms, but I'm not able to solve it.
I would like to get an form with prefielled fields and to allow user to edit them.
I believe my problem is in views.py file, but unfrotuntely I'm not able to solve it.
models.py
from django.db import models
class Item(models.Model):
product = models.CharField(max_length=150)
quantity = models.DecimalField(max_digits=8, decimal_places=3)
price = models.DecimalField(max_digits=7, decimal_places=2)
purchase_date = models.DateTimeField()
warranty = models.DecimalField(max_digits=4, decimal_places=1)
comment = models.TextField()
forms.py
from django import forms
from items.models import Item
class EditItemForm(forms.ModelForm):
class Meta:
model = Item
fields = ('product','quantity', 'price', 'purchase_date', 'warranty', 'comment')
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^show_all/$', 'items.views.items'),
url(r'^(?P<item_id>\d+)/$', 'items.views.item'),
url(r'^edit/(?P<item_id>\d+)/$', 'items.views.edit'),
)
edit.html
<form action="/items/edit/" method="post" class="form horizontal well">{% csrf_token %}
{{ form.as_p }}
<imput type="submit" class="btn btn-inverse" value="Aktualizuj">
</form>
views.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from items.models import Item
from decimal import Decimal
from django.core.context_processors import csrf
from items.forms import EditItemForm
def edit(request):
if request.method == 'POST':
form = EditItemForm(request.POST, instance=request.item)
if form.is_valid():
form.save()
return HttpResponseRedirect('/items/show_all/')
else:
form = EditItemForm(instance=item)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('edit.html', args)
Above code is resulting this message:
TypeError at /items/edit/1/
edit() got an unexpected keyword argument 'item_id'
Can you please help me?
Django 1.6, Python 3.4
You've imagined an attribute called request.item. There's no such thing. You need to get the item from the database, via the ID passed into the function as alecxe showed.
def edit(request, item_id):
item = Item.objects.get(pk=item_id)
if request.method == 'POST':
form = EditItemForm(request.POST, instance=item)
edit() view should allow a keyword argument item_id:
def edit(request, item_id=None):
if request.method == 'POST':
...

Django view retrieve the object from the database

I had a Product object in models,
from django.db import models
class Product(models.Model):
title = models.CharField(max_length=255, unique = True)
description = models.TextField()
image_url = models.URLField(verify_exists=True, max_length=200, blank = True, null = True)
quantity = models.PositiveSmallIntegerField(default=0)
def sell(self, save=True):
self.quantity -= 1
if save:
self.save()
and a template called:product_view.html Product {{product.title}}
and a template called:product_list.html {% for p in products %}{{p.id}},{% endfor %}
I want to make the view retrieve the Product object from the database, use it to render the template and finally return an HttpResponse object that contains the resulting string. If the Product with the given product_id can not be found raise a 404 exception (or return HttpResponseNotFound)
def productview(request, product_id):
"""
I dont know how to write here
"""
#render template "product_view.html" with param product
return HttpResponse("product %s" % product_id)
Meanwhile,if i want to render a page with a list of all available products. A product is available if it has a quantity that's bigger than 0. The template product_list.html is expecting a single parameter products in the context which refers to an iterable of Product objects.
So how to make the view retrieve the the available products and how to use them to render the template and return an HttpResponse object that contains the resulting string?
def available_products(request):
"""
I dont know how to write here
"""
#render template "product_list.html" with param products
return HttpResponse("View not implemented!")
Thx very much
have you tried with generic views?
class ProductDetailView(DetailView):
model = Product
template_name = 'product_view.html'
class ProductListView(ListView):
model = Product
template_name = 'product_list.html'
def get_queryset(self):
"""
Here you can filter the product list
"""
query_set = super(ProductListView, self).get_queryset()
return query_set.filter(quantity__gt=0)
#views.py
from django.shortcuts import render_to_response
from .models import Product
def productview(request):
"""
Retrive all products
"""
products = Product.objects.all()
return render_to_response('product_list.html',{'products': products})
def available_products(request):
"""
Retrive available products
"""
products = Product.objects.filter(quantity__gt=0)
return render_to_response('product_list.html',{'products': products})
These two also can be combined in one view, depending on defined url pattern.
For example:
#urls.py
urlpatterns = patterns('',
url(r'^product/(?P<which>\w+)/$', 'app_label.views.product_view'),
)
#views.py
def product_view(request, which):
"""
Retrive available products
"""
if which == 'all':
products = Product.objects.all()
else:
products = Product.objects.filter(quantity__gt=0)
return render_to_response('product_list.html',{'products': products})