Django, {{ }}, interpolation bindings, double curly brackets, session, dynamic changes

Disclaimer, I am really new at this still, so if I have somehow blasphemed the use of Django sessions, I am sorry.  Feel free to leave a comment!  I'd love it honestly. 

Django's page on sessions:
https://docs.djangoproject.com/en/2.1/topics/http/sessions/


*If you just want the links to the full code that accomplishes this.
*  scroll to bottom
*Honest if you just want the code, it's cool.

Originally I wanted this to work with JavaScript:
<!--
<script>

function remove_bg(){
   document.getElementById("wiwa_bg").style.backgroundImage = "none";
   document.getElementById("wiwa_bg").style.backgroundColor = "white";
};
function add_bg(){
   document.getElementById("wiwa_bg").style.backgroundImage = "url('/static/images/unicorn4_12-22-18.png')";
}
document.getElementById("rm_button").addEventListener("click", remove_bg);
document.getElementById("add_image_button").addEventListener("click", add_bg);
</script>
-->

And then I had the buttons that would do this at the bottom:
<button id="rm_button" onclick=remove_bg()> remove image </button>
It had button styling too, but I ended up trashing that whole thing.

From what I can tell, JavaScript can't handle changing a {{}} variable that is passed in through a render.  I needed my background to stay changed through a user's experience with my whispering wall. But when retrieving a response for the user from the Wiwa Class, The page would be re-rendered as originally set up in the html file.  I needed a session, a way to store changes, preferences to a user's experience.

A lot of solutions used JQuery, and AJAX, and a bunch of things I've never used.
I wanted a solution that involved things I was already familiar with.  Google searches proved fruitless until I could find out what the {{thing}} was called.    The words 'interpolation binding' got me the search results I needed,  Big thanks to (io).
 
Django sessions are included in your settings.py when the site is set up, so if you haven't removed any of the initial MIDDLEWARE or INSTALLED_APPS you should be fine and not have to alter settings.py at all.

These should be what you had as defaults (in settings.py) -->

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
   ]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

So the steps may be a bit out of order, I was tinkering for a long time before it all came together.
I'd suggest changing the html in the place you want that render variable first.
If html can't decipher something you typed, it ignores it.

<body style = "{{ bg_preference }}" >

if it doesn't know what the bg_preference is,
it will ignore it and do nothing with it.
Try it.  Put something like this for your body style:

<body style = "{{ boobaloo }}" >

It should change nothing.  Be blank or the template styles you passed into it with a base template.

Unless of course you have a boobaloo in your views you pass into render.  In that case I'd be really curious what the boobaloo is.

* Note!  there is a boobaloo website!
https://www.boobaloo.com/

The views methods will not work without a path being made to them in your urls.py

So if you want these things to happen, we are working in the directory the web page (.html) you are changing is in.  For example, my website has a directory mysite, and blog.   I keep all the stuff i do on the actual website in blog directory, and all the settings.py and stuff is in mysite directory.
The mysite directory will point to all the urls in my blog.
like so:
      mysite/urls.py   :


from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
    path('/blog', include('blog.urls')),
]

     blog/urls.py     :

from django.urls import path
from . import views


urlpatterns = [
    path('', views.post_list, name='post_list'), #<-- home
    path('blog', views.blog_list, name='blogger'), #<-- blog post page
    path('wiwa', views.wiwa_page, name='wiwa'), #<-- whispering wall page
    path('wiwa_respond', views.wiwa_answer, name='responses'), #<--whispering
           #   walls response mechanism in veiws.py
    path('rm_background', views.remove_bg, name="rm_background"),
    path('bg_replace', views.bg_replace, name="add_bg_image"),

]
The part it took me a minuted to realize, was that in order for anything to happen on my website, I had to go through a 'path'.  So if I want something to change, I need to send info back and forth from the server that stores my information, to the place the website information is getting accessed, then sent to the user.  
A 404 error page for example is the server sending the message to the user, that the url, address, path they gave could not be found.  So if I get to a website, mine for example :
http://nelliesnoodles.pythonanywhere.com/
and add a nonsense path to the end:
http://nelliesnoodles.pythonanywhere.com/spam_and_eggs
the server will send back the 404 page instead of erroring out the server




Next changes:

In my views.py  I make some functions to change/set a session variable:

                blog/views.py     :


def get_preference(request): #used in Wiwa page
    #On first load, there will be no bg_preference , so create it
    if 'bg_preference' not in request.session:
       # whatever you'd want in the <body style = " "> would be your default 
        default =  "background: blue;"
        request.session['bg_preference'] = default
        bg_preference = default
    # If a bg_preference has already been set, return it for the page render
    else:
        bg_preference = request.session['bg_preference']
    return bg_preference

def remove_bg(request):  #<-- urls will use this,  when path "rm_background" is
                                         #    called in html
   """if they push my button for remove image, this will happen
       and return a newly rendered page""" 
    # remember to check if a bg_preference was set
    if 'bg_preference' not in request.session:
        bg_string = "background: white;"   #<-- change the colors to see results
        request.session['bg_preference'] = bg_string
    else:
        # if bg_preference is set, change it to 'background: white;" or whatever
        # styling of background you want.
        bg_string = 'background: white;' #<-- change the colors to see results
        request.session['bg_preference'] = bg_string

    bg_preference = request.session['bg_preference']
    #print("bg preference changed to:", bg_preference)
    return render(request, 'blog/wiwa_experiment.html', {'bg_preference': bg_preference})

The add image will be just like the remove, but you'd specify the image, or style settings you'd want.  

my wiwa--whispering wall view methods have a ton of stuff that won't be helpful, So I'll shave it down to just the initial render:

also in blog/views.py --
def wiwa_page(request):
   # I don't know why for sure, but get_preference would not work with request
   # i tried making the method without the argument and doing   
   # get_preference() but my theory is,
   # HTML: 'give me chocolate'
   # Django:  "What do you mean you want chocolate!  Get out!"
                 # VS 
   # HTML: "We are here to pick up that package of
   #              chocolate per the request #34567"
   # Django: "#34567 request confirmed" *hands HTML chocolate
    bg_preference = get_preference(request)

    return render(request, 'blog/wiwa_experiment.html', {'bg_preference': bg_preference})




Now to test it's working, I would go to my page for Wiwa, and check that when the html is rendered it is not blank/white and the style is just making the background blue like I set up in the get_preferences(request) function.  An intial render should be the default I set in there.
Or if there's a server error, I would check the error logs, and see where I might have set something up wrong, or made one of my many typo's. 







Now the HTML body:

Note: A button does not have to be in the <form> to access and submit to it



          I also could find no other way to so easily have a button perform a task 
          then to just add a form tag and let that do the work of GET, and 'action'

<body style = "{{ bg_preference }}" >
   <!-- all your stuff for body in here -->
</body>

And the buttons:

<!-- my buttons are below the body in a footer -->
<div>
    <form method="GET" action="rm_background" id="remove_background">
    </form>
    <button form="remove_background" class="btn btn-primary
       btn-lg btn block"  type='submit'>
        remove image
    </button>
 </div>
 

If you want to see the full code in action go to:
http://nelliesnoodles.pythonanywhere.com/wiwa
and the buttons are at the bottom

 If you want to see the whole webites code,  here's the github repository:
 https://github.com/nelliesnoodles/my-first-blog




Comments

Popular posts from this blog

JavaScript Ascii animation with while loops and console.log

playing with trigonometry sin in pygame

JavaScript and a Matrix