Flask-Login: KeyError: 'security' when trying to call login_user - python-2.7

I have the following code that logs in a user on my Flask application:
#app.route('/login', methods = ['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
db = get_db()
member = member_from_phone(request.form['phone_number'])
member_obj = Member(member)
if member is None:
g.result = json.dumps({'head' : 200, 'body' : "invalid phone" })
return 'no member...'
elif request.form['password'] == member['password']:
login_user(member_obj)
return 'login successful'
else:
return 'login failed'
return home_page()
However it throws a KeyError: 'security' when I try log in:
File "/Library/Python/2.7/site-packages/flask_security/utils.py", line 64, in login_user
if _security.trackable:
File "/Library/Python/2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
File "/Library/Python/2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
return self.__local()
File "/Library/Python/2.7/site-packages/flask_security/utils.py", line 35, in <lambda>
_security = LocalProxy(lambda: current_app.extensions['security'])
KeyError: 'security' when trying to call login_user
I have no idea what's going on, I think I might need to fix my flask configuration but I don't know how.

Related

How to fix TypeError: validate() got an unexpected keyword argument 'extra_validators'?

I've put together basic login/register forms in a flask app using WTForms. I included parts of code from two files that I thought might be relevant.
I am getting the error:
Traceback (most recent call last):
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2548, in __call__
return self.wsgi_app(environ, start_response)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.handle_exception(e)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions\[rule.endpoint\])(\*\*view_args)
File "/home/neon/flask-app/src/accounts/views.py", line 18, in register
if form.validate_on_submit():
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask_wtf/form.py", line 86, in validate_on_submit
return self.is_submitted() and self.validate(extra_validators=extra_validators)
TypeError: validate() got an unexpected keyword argument 'extra_validators'
This is my code:
src/accounts/forms.py
from flask_wtf import FlaskForm
from wtforms import EmailField, PasswordField
from wtforms.validators import DataRequired, Email, EqualTo, Length
from src.accounts.models import User
class RegisterForm(FlaskForm):
email = EmailField(
"Email", validators=[DataRequired(), Email(message=None), Length(min=6, max=40)]
)
password = PasswordField(
"Password", validators=[DataRequired(), Length(min=6, max=25)]
)
confirm = PasswordField(
"Repeat password",
validators=[
DataRequired(),
EqualTo("password", message="Passwords must match."),
],
)
def validate(self):
initial_validation = super(RegisterForm, self).validate()
if not initial_validation:
return False
user = User.query.filter_by(email=self.email.data).first()
if user:
self.email.errors.append("Email already registered")
return False
if self.password.data != self.confirm.data:
self.password.errors.append("Passwords must match")
return False
return True
src/accounts/views.py
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import login_required, login_user, logout_user, current_user
from src import bcrypt, db
from src.accounts.models import User
from .forms import LoginForm, RegisterForm
accounts_bp = Blueprint("accounts", __name__)
#accounts_bp.route("/register", methods=["GET", "POST"])
def register():
if current_user.is_authenticated:
flash("You are already registered.", "info")
return redirect(url_for("core.home"))
form = RegisterForm(request.form)
if form.validate_on_submit():
user = User(email=form.email.data, password=form.password.data)
db.session.add(user)
db.session.commit()
login_user(user)
flash("You registered and are now logged in. Welcome!", "success")
return redirect(url_for("core.home"))
return render_template("accounts/register.html", form=form)
It's throwing an error in the register function at the second conditional on form.validate_on_submit(). I looked at the WTForms documentation, and from what I could understand, the validate() function is supposed to take an argument extra_validators. So I don't understand why it would be throwing this error.
Full disclosure, I was following a tutorial, and did compare my code to their final code and it matched.
What am I missing here?
You ignore that validate takes additional parameters. If you add this in your implementation it should work.
def validate(self, extra_validators=None):
initial_validation = super(RegisterForm, self).validate(extra_validators)
# ...

Sending Confirmation Emails with Flask, RQ (Working outside of application context.)

I am trying to send confirmation emails when a new user registers. When I send a confirmation email, everything works fine, however, when I try to run that task in the background I get the following error:
File "/Users/martifont/Dev/bz/./FlaskApp/utils.py", line 22, in send_confirmation_email
msg = Message()
I have tried running a different task in the background with no issues at all.
users.py
#imports
from .utils import send_reset_email, send_confirmation_email, example
users = Blueprint('users', __name__)
#SIGNUP
#users.route('/signup', methods=\['GET', 'POST'\])
def signup():
form = SignupForm()
if form.validate_on_submit():
user = User(email=form.email.data, username=form.username.data, confirmed=False, is_admin=False, password = generate_password_hash(form.password.data, method='sha256'))
db.session.add(user)
db.session.commit()
user_id=user.id
with app.app_context():
job = q.enqueue(send_confirmation_email, user)
login_user(user)
flash('A confirmation email has been sent to your inbox.', 'is-success')
return redirect(url_for('users.account', id=user.id))
return render_template('signup.html', form=form)
utils.py
def send_confirmation_email(user):
token = user.get_confirmation_token()
msg = Message()
msg.subject = ('Email Confirmation')
msg.sender = 'MAIL_DEFAULT_SENDER'
msg.recipients = [user.email]
msg.body = f'''
Welcome { user.username }!,
Thanks for signing up. Please follow this link to activate your account:
{url_for('users.confirm_email', token=token, _external=True)}
Thanks!
'''
mail.send(msg)
EDIT
After following Sebastian's advice, I think the issue is solved, however, I am still getting the following error message.
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 2548, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.handle_exception(e)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/Users/martifont/Dev/bz/FlaskApp/users.py", line 30, in signup
job = q.enqueue(send_confirmation_email, args=(app, user))
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/queue.py", line 514, in enqueue
return self.enqueue_call(
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/queue.py", line 410, in enqueue_call
return self.enqueue_job(job, pipeline=pipeline, at_front=at_front)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/queue.py", line 572, in enqueue_job
job.save(pipeline=pipe)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/job.py", line 694, in save
mapping = self.to_dict(include_meta=include_meta)
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/job.py", line 629, in to_dict
'data': zlib.compress(self.data),
File "/Users/martifont/Dev/bz/venv/lib/python3.10/site-packages/rq/job.py", line 305, in data
self._data = self.serializer.dumps(job_tuple)
When you are in a view or inside the creat_app factory function there is no need to use the app_context() context manager.
The traceback defines where the error is been emited and that is when you instantiated the msg=Message() variable so instead of calling the app context inside the view i suggest you to refactor your view and send functions like so:
users.py
from flask import current_app
#users.route('/signup', methods=\['GET', 'POST'\])
def signup():
form = SignupForm()
if form.validate_on_submit():
user = User(email=form.email.data, username=form.username.data, confirmed=False, is_admin=False, password = generate_password_hash(form.password.data, method='sha256'))
db.session.add(user)
db.session.commit()
user_id=user.id
# pass the current app object to the send_confirmation_email function.
# Its important to pass the object and no the proxy
app = current_app._get_current_object()
job = q.enqueue(send_confirmation_email, args=(app, user))
login_user(user)
flash('A confirmation email has been sent to your inbox.', 'is-success')
return redirect(url_for('users.account', id=user.id))
return render_template('signup.html', form=form)
utils.py
def send_confirmation_email(app, user):
with app.app_context():
token = user.get_confirmation_token()
msg = Message()
msg.subject = ('Email Confirmation')
msg.sender = 'MAIL_DEFAULT_SENDER'
msg.recipients = [user.email]
msg.body = f'''
Welcome { user.username }!,
Thanks for signing up. Please follow this link to activate your account:
{url_for('users.confirm_email', token=token, _external=True)}
Thanks!'''
mail.send(msg)

__init__() missing 1 required positional argument: 'get_response' error on Django HttpOnly JWT solution

I currently have a Django setup that followed the guide below. Pretty much, it's a workaround that allows for HTTPOnly cookies to be used with Django Rest Framework JWT authentication. It worked fine in Django 3.2, but I'm attempting to upgrade to Django 4, and I'm now running into the error below
How to store JWT tokens in HttpOnly cookies with DRF djangorestframework-simplejwt package?
Error:
__init__() missing 1 required positional argument: 'get_response'
I'm still a bit new to Django and DRF, so I have no idea what could be going on.
Edit:
Apologies, forgot to add some details. The error is in the following code, on CSRFCheck():
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings
from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions
def enforce_csrf(request):
# Enforce CSRF validation.
check = CSRFCheck()
check.process_request(request)
# populates request.META['CSRF_COOKIE'], which is used in process_view()
reason = check.process_view(request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
class CustomAuthentication(JWTAuthentication):
def authenticate(self, request):
header = self.get_header(request)
if header is None:
raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
enforce_csrf(request)
return self.get_user(validated_token), validated_token
Traceback messages:
(Full error: jsfiddle.net/Luizram/t7u03cqy/1 )
/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py, line 55, in inner
return inner
else:
#wraps(get_response)
def inner(request):
try:
response = get_response(request) <- Line 55
…
except Exception as exc:
response = response_for_exception(request, exc)
return response
return inner
Local vars
/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py, line 197, in _get_response
if response is None:
wrapped_callback = self.make_view_atomic(callback)
# If it is an asynchronous view, run it in a subthread.
if asyncio.iscoroutinefunction(wrapped_callback):
wrapped_callback = async_to_sync(wrapped_callback)
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs) <- Line 197
…
except Exception as e:
response = self.process_exception_by_middleware(e, request)
if response is None:
raise
# Complain if the view returned None (a common error).
Local vars
/usr/local/lib/python3.8/site-packages/django/views/decorators/csrf.py, line 54, in wrapped_view
def csrf_exempt(view_func):
"""Mark a view function as being exempt from the CSRF view protection."""
# view_func.csrf_exempt = True would also work, but decorators are nicer
# if they don't have side effects, so return a new function.
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs) <- Line 54
…
wrapped_view.csrf_exempt = True
return wraps(view_func)(wrapped_view)
Local vars
/usr/local/lib/python3.8/site-packages/django/views/generic/base.py, line 84, in view
self = cls(**initkwargs)
self.setup(request, *args, **kwargs)
if not hasattr(self, "request"):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs) <- Line 84
…
view.view_class = cls
view.view_initkwargs = initkwargs
# __name__ and __qualname__ are intentionally left unchanged as
# view_class should be used to robustly determine the name of the view
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 509, in dispatch
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc) <- Line 509
…
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
def options(self, request, *args, **kwargs):
"""
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 469, in handle_exception
exception_handler = self.get_exception_handler()
context = self.get_exception_handler_context()
response = exception_handler(exc, context)
if response is None:
self.raise_uncaught_exception(exc) <- Line 469
…
response.exception = True
return response
def raise_uncaught_exception(self, exc):
if settings.DEBUG:
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 480, in raise_uncaught_exception
def raise_uncaught_exception(self, exc):
if settings.DEBUG:
request = self.request
renderer_format = getattr(request.accepted_renderer, 'format')
use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
request.force_plaintext_errors(use_plaintext_traceback)
raise exc <- Line 480
…
# Note: Views are made CSRF exempt from within `as_view` as to prevent
# accidental removal of this exemption in cases where `dispatch` needs to
# be overridden.
def dispatch(self, request, *args, **kwargs):
"""
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 497, in dispatch
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs) <- Line 497
…
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 414, in initial
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(request) <- Line 414
…
self.check_permissions(request)
self.check_throttles(request)
def finalize_response(self, request, response, *args, **kwargs):
"""
Returns the final response object.
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/views.py, line 324, in perform_authentication
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
request.user <- Line 324
…
def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/request.py, line 227, in user
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate() <- Line 227
…
return self._user
#user.setter
def user(self, value):
"""
Sets the user on the current request. This is necessary to maintain
Local vars
/usr/local/lib/python3.8/site-packages/rest_framework/request.py, line 380, in _authenticate
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self) <- Line 380
…
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
Local vars
/django/users/authenticate.py, line 30, in authenticate
if header is None:
raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
enforce_csrf(request) <- Line 30
…
return self.get_user(validated_token), validated_token
Local vars
/django/users/authenticate.py, line 10, in enforce_csrf
from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions
def enforce_csrf(request):
# Enforce CSRF validation.
check = CSRFCheck() <- Line 10
…
check.process_request(request)
# populates request.META['CSRF_COOKIE'], which is used in process_view()
reason = check.process_view(request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message

AttributeError: 'tuple' object has no attribute 'get' in views.py

i want to create a registration form but i m getting an attribute error while running the application
from django.shortcuts import render
from basic_app.forms import UserForm,UserProfileInfoForm
def index(request):
return render(request,'basic_app/index.html')
def register(request):
registered=False
if request.method=="POST":
user_form=UserForm(data=request.POST)
profile_form=UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_from.is_valid():
user=user_form.save()
user.setpassword(user.password)
user.save()
profile=profile_form.save(commit=False)
profile.user=user
if 'profile_pic' in request.FILES:
profile.profile_pic=request.FILES['profile_pic']
profile.save()
registered=True
else:
print(user_form.errors,profile_form.errors)
else:
user_form=UserForm()
profile_form=UserProfileInfoForm()
return(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered})
output
Internal Server Error: /basic_app/register/
Traceback (most recent call last):
File "C:\Users\Shoaib Khan\AppData\Local\conda\conda\envs\myenv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Shoaib Khan\AppData\Local\conda\conda\envs\myenv\lib\site-packages\django\utils\deprecation.py", line 93, in call
response = self.process_response(request, response)
File "C:\Users\Shoaib Khan\AppData\Local\conda\conda\envs\myenv\lib\site-packages\django\middleware\clickjacking.py", line 26, in process_response
if response.get('X-Frame-Options') is not None:
AttributeError: 'tuple' object has no attribute 'get'
[24/Dec/2018 15:34:51] "GET /basic_app/register/ HTTP/1.1" 500 61448
That is because of this line:
return(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered})
You've actually created a tuple here. Notice the the parenthesis around the three things that you're returning?
This is how you render a template in django:
from django.shortcuts import render
render(request, 'polls/index.html', context)
So in your case this will work:
render(request,'basic_app/registration.html', {
'user_form':user_form,
'profile_form':profile_form,
'registered':registered
})
For more information on render check out its docs
Change this
return(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered})
to
return render(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered})

no search results Django 2.1 Solr 6.5

I implemented solr 6.5 for django 2.1 with haystack 2.5 and i succesfully built index but theres still no search results
q*:* returns
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"*:*",
"indent":"on",
"wt":"json",
"_":"1543140724323"}},
"response":{"numFound":5,"start":0,"docs":[
{
"id":"blog.post.1",
"django_ct":["blog.post"],
"publish":["2019-05-26T04:46:00+00:00Z"],
"text":["Chwalmy wodza\nsanacja, wódz, historia, sumienie\nBo jeden jest wódz\n\n"],
"django_id":[1],
"_version_":1618099571920994304},
{
"id":"blog.post.3",
"django_ct":["blog.post"],
"publish":["2018-11-15T20:59:39+00:00Z"],
"text":["Trwoga Krzyk Gardłowy\nwódz\nsome\n\n"],
"django_id":[3],
"_version_":1618099571923091456},
{
"id":"blog.post.4",
"django_ct":["blog.post"],
"publish":["2018-11-15T21:24:01+00:00Z"],
"text":["Jeszcze jeden post\nsanacja, wódz\nChwalmy wodza\n\n"],
"django_id":[4],
"_version_":1618099571924140032},
{
"id":"blog.post.5",
"django_ct":["blog.post"],
"publish":["2018-11-21T14:41:25+00:00Z"],
"text":["Yep\nsanacja, wódz\nffff\n\n"],
"django_id":[5],
"_version_":1618099571925188608},
{
"id":"blog.post.7",
"django_ct":["blog.post"],
"publish":["2018-11-21T21:30:30+00:00Z"],
"text":["Markdown\nhistoria, sanacja, wódz\n*wyróżnienie* **pogrubienie**\nlistę:\n\n\n\n\nSometimes you want bullet points:\n\n* Start a line with a star\n* Profit!\n* Start a line with a star\n* Else\n\nTutaj jest [sabaton](https://www.youtube.com/watch?v=_HLNMfCBUb0)\n\n"],
"django_id":[7],
"_version_":1618099571925188609}]
So core is populated
My view:
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post)\
.filter(content=cd['query']).load_all()
# Obliczenie całkowitej liczby wyników.
total_results = results.count()
return render(request,
'blog/post/search.html',
{'form': form,
'cd': cd,
'results': results,
'total_results': total_results})
else:
return render(request,
'blog/post/search.html',
{'form': form})
And my form
class SearchForm(forms.Form):
query = forms.CharField()
I tried procedure proposed by haystack itself
>>> from haystack.query import SearchQuerySet
>>> sqs = SearchQuerySet().all()
>>> sqs.count()
But I only recived
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/query.py", line 522, in count
return len(self)
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/query.py", line 86, in __len__
self._result_count = self.query.get_count()
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/backends/__init__.py", line 619, in get_count
self.run()
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/backends/solr_backend.py", line 802, in run
results = self.backend.search(final_query, **search_kwargs)
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/backends/__init__.py", line 33, in wrapper
return func(obj, query_string, *args, **kwargs)
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/backends/solr_backend.py", line 149, in search
distance_point=kwargs.get('distance_point'))
File "/home/hesmeron/first_env/lib/python3.5/site-packages/haystack/backends/solr_backend.py", line 425, in _process_results
app_label, model_name = raw_result[DJANGO_CT].split('.')
AttributeError: 'list' object has no attribute 'split'
So here's the problem, posts are indexed but unable to search and I really run out of ideas at this point