How to fill Django database on view buttonclick - python

I'm just learning Django, so my question might seem not worth attention, but i spent some time googling and havnt found an answer.
I have two models and a function to fill it
urls.py
url(r'^upd/$', update_database, name="upd")
views.py
def update_database(request):
grabdata()
def grabdata():
url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_day.geojson"
weburl = urllib.request.urlopen(url)
if (weburl.getcode() == 200):
data = json.loads(weburl.read())
EarthQuakes.objects.all().delete()
LastGetSession.objects.all().delete()
lastsession = LastGetSession(hand=data["metadata"]["title"])
lastsession.save()
for i in data["features"]:
place = i["properties"]["place"]
place = str.split(",")
place = place[-1]
time = i["properties"]["time"]
mag = i["properties"]["mag"]
rept = i["properties"]["felt"]
if rept is None:
rept = 1
longitude = 0
latitude = 0
earthquake = EarthQuakes(place=place, time=time,
mag=mag, rept=rept,
longitude=longitude, latitude=latitude)
earthquake.save()
template
<a id="update_button" class="btn btn-info btn-lg" href="{% url 'upd' %}" >Update_database</a>
But i didn't get how to execute it from a view.
Or I assume there is a way to call a conroller function that calls the model function or something like that
It returns the "The view earthquake.views.update_database didn't return an HttpResponse object. It returned None instead."
It feels like there is one missing piece or the pazzle

On Your views.py
def my_view(request):
grabdata()
return HttpResponse('Done')
in urls.py add a new url
url(r'^my-view/$', views.my_view,name='my_view')
in your template
Update

Related

I cannot retrieve the corresponding data when I want to relate the foreign key with the User object

models.py
class Order(models.Model):
PAYMENT_OPTIONS = (
('VISA','VISA'),
('Master','Master'),
('Octopus','Octopus'),
('Cash','Cash'),
)
STATUS = (
('Pending','Pending'),
('Delivered','Delivered'),
)
user = models.ForeignKey(User,models.CASCADE,null=True,blank=True)
customer = models.CharField(max_length=200,null=True,blank=True)
card_id = models.IntegerField(null=True,blank=True)
mobile = models.IntegerField(null=True,blank=True)
email = models.CharField(max_length=200,null=True,blank=True)
total_price = models.DecimalField(decimal_places=2,max_digits=7)
payment_method = models.CharField(max_length=50,choices=PAYMENT_OPTIONS,null=True,blank=True)
status = models.CharField(max_length=50,choices=STATUS,default='Pending')
date = models.DateTimeField(auto_now_add=True)
address = models.CharField(max_length=350,null=True,blank=True)
def __str__(self):
return str(self.customer)+'\'s Order'
views.py
def order_summary(request,order_id,user_id):
user = User.objects.get(id=user_id)
customer_order = Order.objects.get(id=order_id,user=user)
food_order = OrderDetail.objects.filter(order=customer_order)
context = {
'customer_order':customer_order,
'food_order':food_order}
return render(request,'menu/order_summary.html',context)
urls.py
path('order_summary/<int:order_id>/<int:user_id>/',views.order_summary,name='order_summary'),
navbar.html
<li><a class="dropdown-item" href="{% url 'order_summary' [order_id]%}我的訂單</a></li>
Error:
Reverse for 'order_summary' with arguments '('', 1)' not found. 1 pattern(s) tried: ['order_summary/(?P<order_id>[0-9]+)/(?P<user_id>[0-9]+)/$']
For the above code, I may want to have the hyperlink that can access the order_summary method with filtering the correct User object. However, if I try to put the corresponding parameters that are corresponding to the user's order and the user.id, I received the error message even though I already included the url in the urls.py. Can anyone find out the problem if I want to refer the parameters in the navbar of HTML?
You should add a user_id parameter in your urls.py file, so you can pass the currently logged in user (or any other user id you may desire).
So, your views would look like this:
def order_summary(request,order_id, user_id):
user = User.objects.get(id=user_id)
customer_order = Order.objects.get(id=order_id, user=user)
food_order = OrderDetail.objects.filter(order=customer_order)
context = {
'customer_order':customer_order,
'food_order':food_order}
return render(request,'menu/order_summary.html',context)
And then in your templates, you can simply pass in the user id.
<li><a class="dropdown-item" href="{% url 'order_summary' [order_id] [user_id] %}我的訂單</a></li>
I thinks you can directly get this by reverse relation you can try this,
request.user.order_set.all()
this will fetch the order data for current user.

How can I keep GET instance on template form after submission?

I have a simple search bar, I would like to keep the data the user submited and show it on the search bar after the form submission. How can I do that ?
I'm using GET for the search method, but I do not save any searched items on any model and I prefer not to, I was wondering if there was another way to show it without using the database storage.
Here is what my code looks like :
views.py
def index(request):
allGigs = Gig.objects.filter(status=True)
context = {'gigs': allGigs}
return render(request, 'index.html', context)
def search_gigs(request):
title = request.GET['title']
request.session['title'] = title #a try with session, but the data is kept once the user returns to front page...
gigs = Gig.objects.filter(title__contains=title)
return render(request, 'index.html', {"gigs": gigs})
models.py Gig Model has title CharField.
index.html
<form role="search" method="GET" action="{% url 'search' %}">
<input type="text" name="title">
<input type="submit" value="submit">
</form>
urls.py
url(r'^search/$', views.search_gigs, name='search'), #example : /search/?title=my_search_word
url(r'^$', views.index, name='index'),
I thought about using Django Sessions but the problem is that the user can only see what he searched after returning to the index page, any suggestion ?
You can use this sticky query method decorator on your view.
from urllib.parse import urlencode
try:
import urlparse
except ImportError:
from urllib import parse as urlparse
import wrapt
from django.http import HttpResponseRedirect
'''
Originally From:
https://www.snip2code.com/Snippet/430476/-refactor--Django--sticky-URL-query-para
'''
"""
File: decorators.py
Author: timfeirg
Email: kkcocogogo#gmail.com
Github: https://github.com/timfeirg/
Description: remember_last_query_params is from
http://chase-seibert.github.io/blog/2011/09/02/django-sticky-url-query-parameters-per-view.html
"""
class sticky_query(object):
"""Stores the specified list of query params from the last time this user
looked at this URL (by url_name). Stores the last values in the session.
If the view is subsequently rendered w/o specifying ANY of the query
params, it will redirect to the same URL with the last query params added
to the URL.
url_name is a unique identifier key for this view or view type if you want
to group multiple views together in terms of shared history
Example:
#remember_last_query_params("jobs", ["category", "location"])
def myview(request):
pass
"""
def __init__(self, views_name, query_params):
self._cookie_prefix = views_name + '_'
self._query_params = list(set(
query_params + ['page', 'paginate_by', 'order_by_fields']))
def _get_sticky_params(self, request):
"""
Are any of the query parameters we are interested in on this request
URL?
"""
gum = []
for current_param, v in request.GET.items():
if current_param in self._query_params:
gum.append(current_param)
return gum
def _get_last_used_params(self, session):
"""
Gets a dictionary of JUST the params from the last render with values
"""
litter = {}
for k in self._query_params:
last_value = session.get(self._cookie_prefix + k, None)
if last_value:
litter[k] = last_value
return litter
def _digest(self, current_url, litter):
"""
update an existing URL with or without paramters to include new
parameters from
http://stackoverflow.com/questions/2506379/add-params-to-given-url-in-python
"""
parse_res = urlparse.urlparse(current_url)
# part 4 == params
query = dict(urlparse.parse_qsl(parse_res[4]))
query.update(litter)
query = urlencode(query)
parse_res = urlparse.ParseResult(
parse_res[0], parse_res[1], parse_res[2], parse_res[3], query,
parse_res[5])
new_url = urlparse.urlunparse(parse_res)
return new_url
#wrapt.decorator
def __call__(self, wrapped, instance, args, kwargs):
request = args[0]
session = request.session
query = request.GET
gum = self._get_sticky_params(request)
if gum:
for k in gum:
sticky_key = self._cookie_prefix + k
session[sticky_key] = query[k]
else:
meta = request.META
litter = self._get_last_used_params(session)
if litter:
current_url = '{0}?{1}'.format(
meta['PATH_INFO'], meta['QUERY_STRING'])
new_url = self._digest(current_url, litter)
return HttpResponseRedirect(new_url)
return wrapped(*args, **kwargs)
Use this decorator on your view:
from django.utils.decorators import method_decorator
#method_decorator(sticky_query("search_page", ["title"]), name='dispatch')
There is a simple way to do so :
<input type="text" name="title" value="{{ request.POST.title }}">
After the form submit it will keep the POST title field value and use it as the input value.

Django: How to pass variable on form submit

I have a django 1.6.11 form (views.py):
def posneg_nlp(request):
sys_project_name = request.GET.get('project', 'graph') # here oll is ok, it can get correct project value
success = False
monitoring_words = ''
pos_features = ''
neg_features = ''
date_saved = datetime(2015, 7, 29)
print('posneg_nlp form')
print("posneg_nlp request.GET.get('sys_project_name', 'graph')", request.GET.get('project', 'graph'))
if request.method == 'POST':
posnegnlp_form = PosnegnlpForm(request.POST)
if posnegnlp_form.is_valid():
print('posneg_nlp form is_valid')
success = True
sys_project_name = sys_project_name
# here it cannot get project value, it replaced with default:
print("posneg_nlp form is_valid request.GET.get('sys_project_name', 'graph')", request.GET.get('project', 'graph'))
print("sys_project_name ", sys_project_name)
monitoring_words = posnegnlp_form.cleaned_data['monitoring_words']
pos_features = posnegnlp_form.cleaned_data['pos_features']
neg_features = posnegnlp_form.cleaned_data['neg_features']
print('pos_features:', pos_features, 'neg_features:', neg_features)
posneg_nlp_filter(sys_project_name, pos_features, neg_features, db_collection=Vkwallpost)
#get_likes_wallposts_by_owner_id(typeobject='post', owner_id=None, item_id=None, filter_posts='likes')
else:
posnegnlp_form = PosnegnlpForm()
success = False
ctx = {'posnegnlp_form': posnegnlp_form, 'sys_project_name': sys_project_name, 'monitoring_words': monitoring_words,
'pos_features': pos_features, 'neg_features': neg_features, 'success': success}
return render_to_response('choose_nlp_filter.html', ctx, context_instance = RequestContext(request))
This is the second form among two. From first form i pass a variable sys_project_name to this form via template:
<div class="rowSubmit">
<a style="outline: medium none;" hidefocus="true" href="{{ DOMAIN_URL }}/post/choose_nlp_filter/?project={{ sys_project_name }}" class="btn btn-right"><span class="gradient">К шагу 2. Выбор фильтров </span></a>
</div>
When i print current value of sys_project_name in form function posneg_nlp(request) above it shows correct value request.GET.get('project', 'graph') equal to graph2 (happens on form render).
But after that after if posnegnlp_form.is_valid(): it stops to see it and request.GET.get('project', 'graph') shows value in case it not found, equal to "graph".
So, how to pass variable and dont allow to rewrite it?
In the first case, the view is responding to an http GET request, so request.GET contains your project parameter. When the form is submitted, now the view is responsing to an http POST request, and request.POST contains the form data. In the latter case, if you want request.GET to still contain the 'project' parameter, then you can pass it via the form action parameter in your form tag:
form action="/some/url/?project={{ sys_project_name }}"

Django unable to read variable specified in form action

Can anyone help me with the below? I'm reading 'how to tango with django' project and stuck here.
I want a html form to revert back to a view function(add_page).
<h1>Add a Page</h1>
{% if category %}
<form id="category_form" method="post" action="/rango/category/{{category.slug}}/add_page/">
{% endif %}
This is my url map
urlpatterns = patterns('',
url(r'^$',views.index, name = 'index'),
url(r'^about/$',views.about, name = 'about'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/$',views.category,name = 'category'),
url(r'^add_category/$', views.add_category, name = 'add_category'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/add_page/$',views.add_page, name ='add_page'),
)
and my veiws.add_page function
def add_page(request,category_name_slug):
try:
cat = Category.objects.get(slug = category_name_slug)
except :
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit = False)
page.category = cat
page.views = 0
page.save()
return redirect('/rango')
else:
print (form.errors)
else:
form = PageForm()
context_dict = {'form':form,'category':cat}
return render(request, 'rango/add_page.html',context_dict)
the submit button doesnt seem to be taking to post data to the requested url. Please let me know where i am going wrong?
If you want to redirect to the same page
you should probably call
return redirect('add_page', category_name_slug=page.category)
or maybe use something like
return redirect(request.build_absolute_uri())
in the POST section of your code.
request methods
redirect() options
EDIT: To clarify the 'return redirect('rango/')' is not pointing to anything in the url mapping in the question.

GAE - Error: "The method POST is not allowed for this resource"

I'm trying to understand how to edit or update a model. I have tried several scenarios which sometimes give an error message: 405 Method Not Allowed - The method POST is not allowed for this resource. Below is my code:
The Python Models:
import os
import webapp2
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext.webapp import template
class MessageModel(db.Model):
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class Message(webapp2.RequestHandler):
def get(self):
doRender(self,'message.htm')
def post(self):
m = MessageModel()
m.content = self.request.get('content')
m.put()
self.redirect('/view')
class View(webapp2.RequestHandler):
def get(self):
que = db.Query(MessageModel)
messageview_list = que.fetch(999)
doRender(self,
'view.htm',
{'messageview_list': messageview_list })
class Edit(webapp2.RequestHandler):
def get(self):
doRender(self,'edit.htm')
def post(self):
updated_content = self.request.get('content')
content_query = db.GqlQuery("SELECT * "
"FROM MessageModel "
"ORDER BY date DESC LIMIT 1")
messageview_list = content_query.fetch(1)
m = MessageModel()
m.content = self.request.get(updated_content)
m.put()
doRender(self,
'edit.htm',
{'messageview_list': messageview_list })
class Main(webapp2.RequestHandler):
def get(self):
doRender(self,'index.htm')
def doRender(handler, tname = 'index.htm', values = { }):
temp = os.path.join(
os.path.dirname(__file__),
'templates/' + tname)
if not os.path.isfile(temp):
return False
newval = dict(values)
newval['path'] = handler.request.path
outstr = template.render(temp, newval)
handler.response.out.write(outstr)
return True
app = webapp2.WSGIApplication([('/', Main),
('/message', Message),
('/view', View),
('/edit', Edit)],
debug=True)
The HTML Form:
{% for messageview in messageview_list %}
<form method="post" action="/edit">
<p>
<textarea name="message" rows="3" cols="60" MAXLENGTH=60>
{{ messageview.content }}</textarea>
<br>
<input type="submit" value="Update"/>
</p>
</form>
{% ifnotequal error None %}
<p>
{{ error }}
</p>
{% endifnotequal %}
{% endfor %}
I am assuming the indentation is due to copy/paste, but make sure that the post() and get() functions are actually indented inside of your class.
In your form, you have <textarea name="message" rows="3" cols="60" MAXLENGTH=60>, but in your def post() you use updated_content = self.request.get('content'), which is looking for the content keyword in the request. Also, your edit doesn't look like it is doing what you want it to do. In order to edit an entity, the basic outline of the process is 1.) Retrieve the entity (so do as you do, query using some parameter); 2.) Modify the properties of the entity however you want; and 3.) put() the entity back in the datastore.
From your code, it looks like you are retrieving the last entity entered into the datastore, but then creating a new model instead of editing that one (assuming that is what you want to do - not quite sure if that is accurate :) ). If you are looking to modify the entity that is returned, this should work:
def post(self):
updated_content = self.request.get('message')
content_query = db.GqlQuery("SELECT * "
"FROM MessageModel "
"ORDER BY date DESC LIMIT 1")
# Your query will always return just one entity (due to the LIMIT),
# but you can use get() here instead of fetch(1)
latest_model = content_query.get()
# Update the model's content property
latest_model.content = updated_content
latest_model.put()
# Assuming you want to output that model, you'd output it now
doRender(self,
'edit.htm',
{'messageview_list': latest_model })

Categories

Resources