Django passes incorrect query results to template - mysql

I am writing a web app that displays user profiles.
The profile includes a display of the user's interest in other users, which can be uni- or bidirectional. I am using django's included User model to handle authentication and authorization.
The problem I have is that under some circumstances the rendered pages present data from queries executed earlier. Specifically, this happens when I am using the app as two different users on the same computer but on different browsers (Chrome and Safari on OS X; using the django development web server). Right after I load a page for user 1, if I reload a page for user 2 I see user 1's query results.
I have confirmed that my queries are correct by printing them to the console. I think the problem may be at the web server, because the pages load the right queries right after a server restart.
Any ideas?
** Edit: as Daniel points out, the problem is that the interest_view function has a dictionary as a default parameter.**
Relevant code snippets:
models.py
class Profile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True)
class Interest(models.Model):
user = models.ForeignKey(User, related_name=u'interests')
interest = models.ForeignKey(User)
views.py
from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
def interest_view(request, username, extra_context={}):
user = get_object_or_404(User, username__iexact=username)
profile = user.get_profile()
if not profile.can_view_profile(request.user):
return HttpResponseForbidden("You can't view this page.")
interests = Interest.objects.filter(user=user)
if len(interests) > 0:
extra_context['active_interests'] = interests
return render_to_response('interest_detail.html',
extra_context,
context_instance=RequestContext(request)
)
interest_detail.html
{% if active_interests %}
{% for interest in active_interests %}
<li>
{{ interest.interest.first_name }} {{ interest.interest.last_name }}
</li>
{% endfor %}
{% endif %}

You haven't shown any code, so this is impossible to debug. But the issue is almost certainly that you are defining queries at module level, where they persist for the lifetime of the process (which is many requests).
Edit:
Well, I was almost right - it is an issue with things being defined at module level, although in your case it's the Python default argument gotcha. See the effbot for a great explanation, although the default SO question on this is one: Least astonishment in Python.

Related

How to display a list of timezones for vendors to choose from when he lists an event and other visitors are able to see the time in their local time?

We have a web app(Django based backend and Node/ReactJs based front-end, MySQL based DB), and a Flutter based mobile app. We are creating a system where a vendor can create a meeting invite and list the time (and timezone) at which the meeting starts.
Visitors for that meeting should be able to see the time (and timezone) in their local time.
We will be having visitors' location and timezone ID based on their IP.
I can't figure out how to display the list of timezones(preferably in the GMT+xxxx format ) in the front-end for the vendor to choose when he creates an invite and in what format it should be sent to the backend and stored so that I am able to convert it and display it to the visiting user based on his location's timezone?
I would be really grateful if someone here can point me to the right question if it has been asked already or some document from which I can refer to for the implementation?
You can use pytz for creating a list of timezones.
There's documentation in Django stating how to select current timezone and creating a list of timezones link
Create a list of timezone select option
# views.py
import pytz
def your_views(request):
# code
return render(request, 'your_template.html', {'timezones': pytz.common_timezones})
In your_template.html file
<select name="timezone">
{% for tz in timezones %}
<option value="{{ tz }}">{{ tz }}</option>
{% endfor %}
</select>
Normal people don't like GMT+X. Second, basing a timezone on IP is irritating for people using VPNs, especially since the browser stores a timezone based on computer settings. Granted, it takes a request to be sent via javascript, so the first page won't know what the timezone is. See Intl.DateTimeFormat.resolvedOptions().timeZone.
To generate choices that correspond with that list, use pytz.common_timezones:
import pytz
class YourModel(models.Model):
TZ_CHOICES = ((v, v) for v in pytz.common_timezones)
time_zone = models.CharField(choices=TZ_CHOICES)

How safe is using if statements in html with django?

How safe is using if statements in html templates with django? Eg.
{% if post.visibility == 'PUBLIC' %}
show something....
{% endif %}
How easy is it to change that from public to private if we don't filter it accordingly in the backend for hackers or other people?
It is perfectly safe. It is not 'in html' at all.
That code is being evaluated on the backend using the Jinja2 template engine. A frontend user can't edit your if statement at all because by the time the message reaches them Jinja2 has already deleted it and replaced it with the computed version.
See: https://en.wiktionary.org/wiki/render#Verb
Django template processing happens on server side. A visitor of the page will only see the final result, but not the if statements. It is thus not possible for him to access different content by changing the if statement (unless there is some other way to attack the server itself or inject different values into the if statement that are generated from user input).

Is there a way to request a specific dataset from a rest api?

Sorry if this seems dumb to some of you, I am a total noob and literally have no idea what I'm trying to google, so I can't even try googling this before I ask.
I would like to pull specifically england covid19 data from this page: https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/Coronavirus_2019_nCoV_Cases/FeatureServer/1/query?where=1%3D1&outFields=*&outSR=4326&f=json
and then set it as a json attribute (if possible).
I'm trying to create a sensor in Home Assistant for England Covid19 data, using the rest platform.
I am taking this idea from someone else who has already successfully acheived this:
platform: rest
name: covid_19_folkhalsomyndigheten
resource: https://www.arcgis.com/sharing/rest/content/items/2dc63e26f509468f896ec69476b0dab3/data
value_template: "{% if value_json.embedCode == '' %} Otillgänglig {% else %} Tillgänglig {% endif %}"
json_attributes_path: $.widgets.widget_1.config
json_attributes: [embedCode]
scan_interval: 21600
But there are differences in the actual resource he is using and mine so maybe I cannot just copy his method.
If anyone has the spare time to guide me through this I would be very greatful. Thanks!
Here ya go, here's an answer using python3
import json
import requests # you'll have to install this with something like pip
r=requests.get('https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/Coronavirus_2019_nCoV_Cases/FeatureServer/1/query?where=1%3D1&outFields=*&outSR=4326&f=json')
print(r.text, ' this will be your json object')
# if you want to write the data to a file called data.txt (note you can choose any name like corona.txt)
with open('data.txt', 'w') as outfile:
json.dump(r.text, outfile)
The following code would fetch the data, and then write and create a file called data.txt

django what variables available in a template .html file?

I'm trying to figure out what objects and variables are available within the template .html file
This is in the view file
from django.contrib.auth import get_user_model
Userx = get_user_model()
class ProfileDetailView(DetailView):
template_name ='profiles/user.html'
def get_object(self):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(Userx,username__iexact=username, is_active=True)
In the user.html file
{% block content %}
username={{ user.username }}
{% endblock content %}
my questions
1. why is the name of the object in the user.html file called user?
how would one find documentation on the object names and fields of the user object?
how would one see all available variables accessible in a particular .html template"
Thank you for your help
This is the name defined to refer to the user object (hard to expect something else)
Here you can find every fields of this User object
You can use {% debug %} to inspect the context and A LOT of other informations, and this link can help you to find a specific keyword to use in the templates.
Check this post too, especially for the following line (helpful to inspect the debug output) :
{% filter force_escape %} {% debug %} {% endfilter %}

Flask-Admin link back to main site

Is there any way to modify the home button url link on the flask-admin admin top panel so that I redirect back to a main site?
I can add a link in a custom.html page eg:
{% extends 'admin/master.html' %}
{% block body %}
Home
{% endblock %}
But this is hidden away inside the custom page. I'd prefer a top-bar link out of admin.
Easiest way is to add a menu link and leave the admin home page alone (you might want to add a dashboard or suchlike in the future):
from flask_admin.menu import MenuLink
# Create admin
admin = Admin(app, name='Admin', url='/')
admin.add_view(ImageView(model=Image, session=db.session, category='Database', name='Images'))
# Add custom link to public website home page
admin.add_link(MenuLink(name='Public Website', category='', url=url_for('main.home')))
Note, url_for needs to be called within a Flask application context. For example, if using the Flask application factory pattern, this would look something like the following:
def create_app(config):
app = App('app')
# setup config
# setup blueprints
# setup Flask-Admin
from app.admin import create_admin
from app.admin.configure import configure_admin
with app.app_context():
admin = create_admin(app=app)
configure_admin(app, admin)
# more stuff
return app
__init__.py in app.admin module
def create_admin(app=None):
return Admin(app, template_mode='bootstrap3')
configure.py in app.admin module
def configure_admin(app, admin):
# setup views
# add link to home page
admin.add_link(MenuLink(name='Public Website', category='', url=url_for('home.HomeView:index')))
You can override get_url method of MenuLink. That way you get around application context problem.
from flask import url_for
from flask_admin import Admin
from flask_admin.menu import MenuLink
class MainIndexLink(MenuLink):
def get_url(self):
return url_for("main.index")
admin = Admin(name="Admin")
admin.add_link(MainIndexLink(name="Main Page"))
def create_app():
app = Flask(__name__)
from app.admin import admin
admin.init_app(app)
return app
If you are having issues with app context error when using app.app_context():
RuntimeError: Unable to build URLs outside an active request without 'SERVER_NAME' configured. Also configure 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as needed.
You can simply 'test_request_context()' method.
with app.test_request_context():
admin.add_link(MenuLink(name='Name', category='', url=url_for('home.home_route')))
This is documented here