Thursday 3 December 2020

Django how to limit the Template view depending on the Users Groups.

 What we need to do is check the Users group list from inside the ' if user.is_authenticated' statement in the template. And to do this we need to harness the power of Django's 'template tags'

Create the folder and following pages in your main app folder - in my case ‘mysite’

1 2 3 -- templatetags ---- __init__.py ---- mysite_templatetag.py

__init__.py will be a blank file .

in mysite_templatetag.py I have .

1 2 3 4 5 6 7 from django import template register = template.Library() @register.filter(name='has_group') def has_group(user, group_name): return user.groups.filter(name=group_name).exists()

 

And then in the template base.html

1 2 3 4 5 6 7 {% load mysite_templatetag %} ... {% if request.user|has_group:"Coordinator" %} <li class="nav-item"> <a class="nav-link" href="{% url 'users:user_list_view' %}">Your Surveyors</a> </li> {% endif %}


According to some instructions that should be it; however I was getting the error


template tags '%_extras' is not a registered tag library. must be one of: …


To solve this .

  1. The server will need to be rebooted.

  2. Make sure the files are in the right place

  3. I added the following to my settings.py ‘TEMPLATES’ object.



    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'mysite','templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], 'libraries':{ 'mysite_templatetag': 'mysite.templatetags.mysite_templatetag', } }, }, ]



Reebooted the server and now it works.

Monday 30 November 2020

Django restricting a Class Based View page depending on a User attribute / Group etc.

The following code is an example of how you can make it so users get redirected depending on conditions taken from their User model . 


This code is to go in a Class Based View. 

1 2 3 4 def dispatch(self, request, *args, **kwargs): if request.user.username == 'david.smith': return redirect('home_page') return super().dispatch(request, *args, **kwargs)



This example would redirect the user 'david.smith'.  This next example would redirect if the User does not belong to the group that we want. 


def dispatch(self, request, *args, **kwargs): if request.user.groups.filter(name = 'Coordinator').exists(): return super().dispatch(request, *args, **kwargs) return redirect('home_page')


Monday 23 November 2020

PythonAnywhere Internal Server Error ager '/favicon.ico' call added.

 After adding my Favicon pack to the Static files in PythonAnywhere ( using the 'Files' link; and then adding the files in mysite/static folder ) 
And then when accessing the site the next time I was seeing the following message on the homepage. 


Internal Server Error


On checking the error.log ( go to > Webb > Scroll down to 'Error.log' ) 
I could see the message ' Internal Server Error: /favicon.ico' 


So my next port of call was to check that the favicon.ico could be seen at the same URL ( relatively ) as the one that I have working on my local server.  It was working though, so no issue there. 


So my next port of call was to check that the favicon.ico could be seen at the same URL ( relatively ) as the one that I have working on my local server.  It was working though, so no issue there. 

After revisiting the issue I realised it was the message above the 'Internal Server Error' that was most useful . 


raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)

ValueError: Missing staticfiles manifest entry for 'images/favicon.ico'

2020-11-23 14:39:05,951: Internal Server Error: /favicon.ico


Missing staticfiles manifest entry in Django issue


Which led me to adding the following change which worked. 

OPEN 
/mysite/settings/base.py

FIND

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'


and changed this to . 

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'



It might not be recommended but for the small site I'm working on this fix will be fine.  And felt it's worth noting for anyone else who stumbles over the same issue. 

Monday 16 November 2020

Visual Studio Code - "go to definition" not working .

 This was happening on VSC "Version: 1.51.1" 

For example if I was to create the following test.py code 

<code>

def my_function():
  print("Hello from a function")

my_function()

</code>

Then I should be able to right click 'my_function' and get an option 'go to definition' which will take to to the above function.  Unfortunately I was getting a 'no definition' available message. 

To fix this open VSC . 

use Command + Shift + P ( Mac ) 








Search for 'settings.json' 

And add this to your code 

<code>

{
// Defines type of the language server.
"python.jediEnabled": false,
"python.languageServer": "Microsoft"
}

<code> 

Restart VSC .  This then resolved my issue for the code example given above.

 
However I discovered another issue 'Visual Studio Code unresolved import python ' 

Which I would get when clicking on imported code , for example if I clicked on 'selenium' here. 

from selenium import webdriver

The solution for me here was to click on 'Python 3.8.2 64-bit' and replace it for another one. 


Monday 21 September 2020

Python Anywhere issue with Disk Space Quota Limit.

The official help page for this on Python can be found at https://help.pythonanywhere.com/pages/DiskQuota/

Here's my notes on what I've tried so far. 

du -hs /tmp ~/.[!.]* ~/* /var/www/


4.0K /home/mysite/.bashrc4.0K /home/mysite/.gitconfig4.0K /home/mysite/.profile4.0K /home/mysite/.pythonstartup.py4.0K /home/mysite/.viminfo4.0K /home/mysite/README.txt4.0K /tmp8.0K /home/mysite/.local8.0K /home/mysite/.vimrc17M /home/mysite/.cache160M /home/mysite/aroundaboutslaundry321M /home/mysite/.virtualenvs


An easy fix is if the Cache is bloated. 

rm -rf ~/.cache

rm -rf ~/.cache/*

Or lets clean up Unused files. 

rm -rf /tmp/*
In my case this neither of these helped.    


CLEAN UP ANY UNUSED VIRTUALENVS

How see old virtual environments ( see what virtualenvs I have) 



lsvirtualenv

Running this command showed me that I only had the one Environment working . 




Uninstall python packages you don't need anymore

To see what packages you have take a look at your requirements.txt page or run 

pip list

I then ran through a handful that I believed I'm not using ; although I may need to install them again at a later date. 

To remove here is an example


pip uninstall django-cripsy-forms

And then Remove from requirements.txt.  



From here I could now install the package I wanted, which was 'wagtail' 

pip install wagtail







Thursday 17 September 2020

ImportError: No module named django.core.management

 I got this error when running

python manage.py migrate


Traceback (most recent call last):

  File "manage.py", line 8, in <module>

    from django.core.management import execute_from_command_line

ImportError: No module named django.core.management


And then realised I should have run 

python3 manage.py migrate

Doh! 

Thursday 20 August 2020

Adding Mobile Phone Check and UK Landline check together.

 In the current project I'm looking at I have two input fields for telephone numbers. 

1. UK Mobile Phone Number
2. UK Landline Number 

They each have their own regex checks .  


It's been requested that we should have just the one input field; this could be a UK landline OR UK Mobile .  So I'd like to merge the 2 regexes together.   Which is real easy but I found googling the exact answer very difficult.   So I thought I'd note it here. 

So here's the two seperate Regex's

Regex for UK Mobile Numbers. 

^(\+44\s?7(\d ?){3}|\(?07(\d ?){3}\)?)\s?(\d ?){3}\s?(\d ?){3}

Regex for UK Landlne Phone Numbers 

^\(?0( *\d\)?){9,10}$

So to use both we can add the OR statement which is '|' 

And to group the two sides together using the '(' and ')' 

which gives us the following combined statement. 

(^(\+44\s?7(\d ?){3}|\(?07(\d ?){3}\)?)\s?(\d ?){3}\s?(\d ?){3})|(^\(?0( *\d\)?){9,10}$)





Monday 17 August 2020

Calling API from another Docker container returning a 'Cannot assign requested address' Error

This article is to document an issue I had recently that was caused by having two docker installation on my local computer and using them as API’s to each other. Doing this means you cannot call localhost like we would have previously. I found the issue quite hard to search for because at first I was unaware it was the Docker containers that were at fault. At first I had Drupal 7 website running locally and it would call my API ( Django ) , which was on another server.

However it made sense for development to have both things on my local environment; they would both be Docker installations. On doing so I'd set the Django API up on http://localhost:8000/ which I could see worked and could connect to using Postman. However when I tried to make the request through Drupal I would get the error 'Cannot assign requested address' Basically You cant use localhost for something within a container…

Each container thinks it is an entire server in its own right, and sees ‘localhost’ as only the container, and not the host. To fix this I did the following . On the Django ( API ) side open docker-compose.yml

Add "host.docker.internal" to the list of ALLOWED_HOSTS

for example.

1 - 'ALLOWED_HOST={"hosts": ["localhost", "api.localhost", "api.docker.localhost", "host.docker.internal"]}'

This was diagnosed by viewing the logs of the fafeapi container with docker-compose logs -f fafeapi  and seeing:
Also thank you to this post https://medium.com/it-dead-inside/docker-containers-and-localhost-cannot-assign-requested-address-6ac7bc0d042b

Wednesday 5 August 2020

Getting my Wagtail / Django project working on PythonAnywhere

On PythonAnywhere you have some instructions on how to set up a Django project; for the record these are. 

In brief, the differences are:

  • The version of Django that you've written your code for might not be the version we have installed by default; the best way to use the exact version you want is to set up a virtualenv.
  • manage.py runserver and localhost:8000 won't work on PythonAnywhere, because our console servers aren't accessible from the outside world.
  • Instead, go to the Web tab (using the button near the top right) and start a new web app using manual configuration. Click through to the link to edit your wsgi file and uncomment the section for Django. From then on, your Django site will be live at your-username.pythonanywhere.com.
  • You'll need to hit the Reload button to reload your web app, whenever you want to see the effects of code changes on your site.

That's ultra-brief overview. For detailed instructions, check out the Following the Django Tutorial on PythonAnywhere wiki page.


And after Googling for 'How to set up a Wagtail Project on Python Anywhere' I found the following instructions on Github https://github.com/texperience/wagtail-pythonanywhere-quickstart

Using these articles the following procedure worked for me.   My project here by the way is called 'sb_goals' 


>> Open a bash console on PythonAnywhere 

mkvirtualenv wagtail-django-project --python=/usr/bin/python3.7

>> Clone the site into my project. 

git clone https://github.com/deejayM/django_sb_goals.git


cd mysite


pip install django


Next up is to install any Requirements which I didn’t have .

pip install -r requirements.txt


However I didn’t have a requirements.txt file created, so I needed to go and create one of those first off. 

And you can do this from your root folder ( that has the manage.py file in it ) with the following :



pip freeze > requirements.txt

Then add that file to PythonAnywhere; I opened up the file using VIM and pasted the generated code in.  

vim requirements.txt 


i ( to insert in VIM )
ctrl + v ( to paste )
ESC
:wq

At this point you can now hopefully run Migrate command.


python manage.py migrate



I had a few issues here; which I believe were caused by me hitting disk quota limits.  This following command will show you how and where your resources are being used up.

du -hs /tmp ~/.[!.]* ~/* /var/www/


Which in my case showed me that my .cache folder was pretty big. To clear it use

rm -rf ~/.cache


NOTE :  I've had additional similar issue on disk Quota limits since and have written some note on this here https://littleripplesproject.blogspot.com/2020/09/python-anywhere-issue-with-disk-space.html


The above issue in turn resulted in seeing the following type of errors when re-running the migrate.  The list was much longer than this , but this is an example


python anywhere modulenotfounderror: no module named 'crispy_forms'

ModuleNotFoundError: No module named 'rest_framework'


You can resolve these with the following, not that some needed to pre preceeded by 'django-' and some you just enter the module name.

pip install django-crispy_forms

Finally I was able to continue with . 

python manage.py migrate

python manage.py createsuperuser

Back in the PythonAnywhere console we need to create a New Web App . 



We need hange the 'virtualenv' to the one we've set up, this is done in the Web App section on the control panel . 

This way our account will see all the Installed packages. 




We'll also need to add our URL to ALLOWED HOSTS in the settings file, we can edit that with VIM . 

mysite/settings/base.py


vim settings.py
i
# TO BE ADDED SOMEWHERE

ALLOWED_HOSTS = ['mysite.pythonawhere.com']

[ESC]
:wq!





Here are some screenshots of the help instructions from the PA website. 





Further Troubleshooting : 



Here's an example of my WSGI file that works. 

# This file contains the WSGI configuration required to serve up your # web application at http://aroundaboutslaundry.eu.pythonanywhere.com/ # It works by setting the variable 'application' to a WSGI handler of some # description. # # The below has been auto-generated for your Django project import os import sys # add your project directory to the sys.path project_home = '/home/myaccountname/myappprojectname' if project_home not in sys.path: sys.path.insert(0, project_home) # set environment variable to tell django where your settings.py is os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings.base' # serve django via WSGI from django.core.wsgi import get_wsgi_application application = get_wsgi_application()
One thing to notice here is that os.environ['DJANGO_SETTINGS_MODULE'] is set to 'mysite.settings.base'.
Whereas Django projects will have this set to 'mysite.settings' . This is because Wagtail has the settings in base.py in the Settings folder. Next Issue .

Error: The SECRET_KEY setting must not be empty

To fix this I opened mysite/settings/base.py file and added 

SECRET_KEY = "myuniquesecretkey1234"


Next Issue . 


raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)
ValueError: Missing staticfiles manifest entry
The solution for this is to run 

python manage.py collectstatic

Although doing so for me gave me another 'disk quota exceeded' message. 

You could go back to the section above where you remove some more unneeded packages from your installation.  But for me I decided to pay the monthly fee, as I'd been spending too much time setting up. 


>> After doing so and 'reloading' my Web app.  I know have a site that I can see :)