Django & Haystack: Beautify the search url - python

I have a problem with Django and Haystack. I'm trying to beautify the url (example.com/search/?q=hey in example/search/hey/) as follows:
def go(request):
"""
Search > Beautify
"""
search_query = request.GET.get('q', None)
return HttpResponseRedirect(reverse('search.views.root', kwargs={
'search_query': search_query,
}))
def root(request, search_query):
"""
Search > Root
"""
form = HaystackSearchForm(request.GET)
tutorials = form.search()
return render(request, 'search/search_root.html', {
'search_query' : search_query,
'tutorials' : tutorials,
})
The problem is that it doesn't work because the request for the go function is not the same than the root function. I want to find a way to pass the appropriate request to the HaystackForm (which mean with the query).

Related

How to retrieve data from url using django urls

this is the call back URL which am getting from the payment gateway I am integrating with
http://127.0.0.1:8000/checkout/mfsuccess/?paymentId=060630091021527961&Id=060630091021527961
I want to extract the paymentId int from this URL so I can use it in my function
this is the URL line am using
path('checkout/mfsuccess/?<str:paymentId>', gateway_Success, name='mf_success'),
and this is my function
def gateway_Success(request, id):
payment_id = request.GET.get('id')
print(payment_id)
context = {
"payment_id": payment_id
}
return render(request, "carts/checkout-mf-success.html")
How I do that since the way am doing not working I am getting the following error
Not Found: /checkout/mfsuccess/
[20/Nov/2020 03:38:59] "GET /checkout/mfsuccess/?paymentId=060630091121528060&Id=060630091121528060 HTTP/1.1" 404 4378
You don't need to adjust your path() function to catch the URL query parameters
path('checkout/mfsuccess/', gateway_Success, name='mf_success'),
also, change your view as,
def gateway_Success(request):
id_ = request.GET.get('Id') # retrieving the `Id`
payment_id = request.GET.get('paymentId') # retrieving the `paymentId`
context = {
"payment_id": payment_id,
"id_": id_
}
return render(request, "carts/checkout-mf-success.html", context=context)
This is enough to catch the redirection.

With Flask-Admin and Flask how can I submit a form\view based on ModelView from code?

With Flask-Admin and Flask how can I submit a form\view based on ModelView from code?
I'm trying to create a separate view\form that would allow user to add multiple entries with one form. Specifically allowing to upload multiple images with common prefix name and common parameters. I'd like to do it by submitting a single-image upload form from code, because it does some additional processing like resizing images and I'd like to let Flask-Admin handle connecting database entries and files.
Here's the form I'd like to submit from code:
class ImageView(ModelView):
def _list_thumbnail(view, context, model, name):
if not model.path:
return ''
return Markup('<img src="%s">' % url_for('media',
filename=form.thumbgen_filename(model.path)))
column_labels = dict(show_in_header="Show In Header?",
path="Image")
form_create_rules = ("name",
"tags",
rules.Text(
"Use this image as header. If more than one image is selected header image will be random each time the page is loaded."),
"show_in_header",
"path")
form_excluded_columns = ("timestamp")
column_formatters = {
'path': _list_thumbnail
}
thumbnail_size = config("media", "thumbnail_size")
form_extra_fields = {
'path': BroImageUploadField('Image',
base_path=IMAGES_FOLDER,
thumbnail_size=(thumbnail_size, thumbnail_size, True),
endpoint="media",
url_relative_path='media',
relative_path=None)
}
def is_accessible(self):
return current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('login', next=request.url))
And here I'm creating a form and I'm just not sure that .process() is the function to submit it? Is there one at all?
lass MultipleImagesUploadView(BaseView):
#expose("/", methods=["GET", "POST"])
def index(self):
if request.method == "POST":
a_form = MultipleImagesForm(request.form)
base_name = a_form.base_name.data
tags = a_form.tags.data
show_in_header = a_form.show_in_header.data
print (request.files.getlist(a_form.images.name))
uploaded_files = request.files.getlist(a_form.images.name)
for i, uf in enumerate(uploaded_files):
try:
name, ext = os.path.splitext(uf.filename)
if ext not in IMAGE_EXTENSIONS:
flash("Image file {} was skipped as it's extension is not supported ({}).".format(uf.filename, ext), category="warning")
continue
image_contents = uf.stream.read()
image_form = ImageView()
image_form.name.data = "{}_{}".format(base_name, i)
image_form.tags.data = tags
image_form.show_in_header.data = show_in_header
image_form.path.data = image_contents
image_form.process()
except Exception as e:
flash ("Unhandled exception: {}".format(e), category="warning")
flash("Images were added to the gallery.", category='success')
a_form = MultipleImagesForm()
print("############", a_form)
return self.render('/admin/multiple_images_upload.html', form=a_form)
I can't figure out a way to submit a form from code, been trying to find the answer in docs and google for hours now with no luck.
Found the issue. In my case I was missing the enctype="multipart/form-data". Without that files part was sent as empty.
Also changed to using from flask_wtf import FlaskForm and enabling it as {{ form.files(class="form-control", multiple="") }} in the template.
Files can then be accessed with uploaded_files = request.files.getlist("files") on POST request, it will hold array of file-objects.
I hope this helps someone. If any additional formatting is required I will add or expand the answer.

Django: Testing Post View

I'm trying to test my post with a testing suite. I've just been trying to follow the documentation to do this. The main problem I'm having right now is that response.context is returning None.
This is what my test class looks like:
class JSONHandlerTester(TestCase):
def setUp(self):
self.client = Client()
self.jsonTestPath = os.path.join(settings.MEDIA_ROOT,'json','jsonTests')
def testing(self):
for test in os.listdir(self.jsonTestPath):
testFile = os.path.join(os.path.join(self.jsonTestPath),test)
split = test.split('.')
testName = split[0]
testNameArray = re.findall('[a-zA-z][^A-Z]*', testName)
project = testNameArray[0]
team = testNameArray[1]
with open(testFile) as json:
response = self.client.post('/JSONChecker', {'json_project': project, 'json_team': team, 'json': json})
print response
print response.context
if (response.context['title'] == "Congratulations!!! Your JSON Passes!!!" and testNameArray[2] == "Pass") or (response.context['title'][2:] == "The" and testNameArray[2] == "Fail"):
print test+': Works'
else:
print test+': BREAKS: PROBLEM DETECTED'
Also this is what my render looks like:
return render(request, 'JSONChecker.html',context = {'title': title, 'validationErrors':validationErrors,'errors':errors, 'isLoggedIn':isLoggedIn, 'form': form, 'post':post})
If the form is invalid or the extension isn't json this is what the render looks like (this shouldn't be triggered by suite):
return render(
request,
'JSONChecker.html',
context = {'title': title,'errors': errors,'isLoggedIn':isLoggedIn,'team':team, 'email':email,'form':form, 'post': post},
)
Content-Length: 0
Content-Type: text/html; charset=utf-8
Location: /JSONChecker/
I'm using Django 1.11 and Python 2.7
Context attribute is only populated when using the DjangoTemplates backend.

Django Unit Testing testing views

I am testing my views using Django Unit testing. I am making get and post requests with params to check what status i get back.
But the problem how to check for context variables which are retuned in the response?
For example, on the View Cities page, I make a get request, the context dict in the view has the variable cities. So I want to check for context.
resp = self.client.post(
path=reverse('upload_video'),
data={"video_url": video_url, "pro": 1}
)
self.assertEqual(resp.status_code, 200)
Condition is True both ways, if the form is invalid or valid it returns 200. If I can check for context, then I can check what has been retuned from the view in response.
What I tried
=> resp.__dict__
{'templates': [], '_handler_class': None, '_headers': {'vary': ('Vary', 'Cookie'), 'content-type': ('Content-Type', 'application/json')}, '_charset': 'utf-8', '_closable_objects': [], 'cookies': <SimpleCookie: >, 'client': <django.test.client.Client object at 0x112bace10>, '_base_content_is_iter': False, 'context': None, 'request': {u'CONTENT_LENGTH': 202, u'wsgi.input': <django.test.client.FakePayload object at 0x113667990>, u'REQUEST_METHOD': 'POST', u'PATH_INFO': '/upload/video/modal/', u'CONTENT_TYPE': u'multipart/form-data; boundary=BoUnDaRyStRiNg', u'QUERY_STRING': ''}, '_container': ['{"error": {"msg": "Pro: Select a valid choice. That choice is not one of the available choices.", "head": null}}']}
Check _container has that variable. The form is invalidated, and retuned an error in the context. but when I do the following i get None
=> resp.context
None
Test
import os
from django.contrib.auth import authenticate
from django.core.urlresolvers import reverse
from django.test import TestCase
def test_video_upload(self):
""" Test that video upload is successful """
self.create_and_login(username="su", password="su", is_superuser=True)
video_urls = [
u"https://www.youtube.com/watch?v=abc",
u"https://vimeo.com/32222",
u"http://www.dailymotion.com/video/rer"
]
for video_url in video_urls:
resp = self.client.post(
path=reverse('upload_video'),
data={"video_url": video_url, "pro": 1}
)
set_trace() #Breakpoint
a = resp.context[-1] # <=== Not getting it here.
self.assertEqual(resp.status_code, 200) #passes
videos = Video.objects.all()
self.assertEqual(len(videos), 3)
View
ctx = {}
if request.method == Enums.Request.POST:
video_form = UploadVideoEasyForm(data=request.POST)
if video_form.is_valid():
video, log = video_form.save(request=request)
msg = 'Successfully Uploaded, View: here'.format(video.get_absolute_url())
ctx[Enums.ResponseAlert.Success] = {'msg': msg}
else:
ctx[Enums.ResponseAlert.Error] = make_alert(msg=form_error_to_string(video_form))
return HttpResponse(json.dumps(ctx), content_type="application/json")
elif request.method == Enums.Request.GET:
ctx['upload_video'] = UploadVideoEasyForm()
if request.user.is_authenticated() and request.user.is_superuser:
return render_to_response('new/modals/upload_video.html', context_instance=RequestContext(request, ctx))
Cheers.
The resp (An instance of django.test.Response) should have an context attribute.
You can access context value using context[..]:
self.assertEqual(resp.context['cities'], ...)

Django WSGI error

I'm using Django for a per project. When I use an external API call in my views (function based view), I'm getting bad responses.
Here are my code snippits:
views.py
def stock_name(request):
if request.method == 'POST':
form = StockForm(request.POST)
if form.is_valid():
stock_ticker = form.cleaned_data["stock_ticker"]
return render(request, 'article/stockinfo.html', get_search_query(stock_ticker),context_instance=RequestContext(request))
else:
form = StockForm
return render(request, 'article/index.html', {"form" : form })
.
def get_search_query(stock_ticker):
print stock_ticker
api = articleAPI('e4534187a7915ba69b41c1beab029d0f:8:71762357')
articles = api.search(q = stock_ticker,
fq = {"news_desk" : "technology"},
fl = ["headline", "abstract", "pub_date", "news_desk", "_id"],
sort = "newest",
begin_date = str(20100101),
end_date = str(20150401),
)
print articles
return articles
It seems I'm getting some kind of bad response and it looks like a wsgi error. But If run the get_serach_query as a standalone code, it works. The get_search_query takes a stock ticker and retrieves results with New York Times Article API.

Categories