Alternative for Absolute Path in Django - python

I am making a Django Project, A Business Directory.
Here I have used ABSOULATE PATHS for Template rendering,
I thnk this might create problem in future.
Please look into my codes and Suggest me how to solve this problem so that it does not create any problem in future.
Please help
my models.py is::
from django.db import models
class Directory(models.Model):
Bussiness_name = models.CharField(max_length=300)
Description = models.CharField(max_length=900)
Number = models.CharField(max_length=100)
Web_url = models.CharField(max_length=800)
Catogory = models.CharField(max_length=200)
def __unicode__(self):
return self.Bussiness_name
class Adress(models.Model):
directory = models.ForeignKey(Directory)
adress_name = models.CharField(max_length=300)
def __unicode__(self):
return self.adress_name
class Photos(models.Model):
directory = models.ForeignKey(Directory)
Photo_path = models.CharField(max_length=100)
Photo_name = models.CharField(max_length=100)
def __unicode__(self):
return self.Photo_name
My view.py is ::
# Create your views here.
from django.http import HttpResponse
from crawlerapp.models import Directory
from crawlerapp.models import Adress
from crawlerapp.models import Photos
from django.template import Context, loader
from django.shortcuts import render
def index(request):
Directory_list = Directory.objects.all()
t=loader.get_template('C:/Python27/django/crawler/templates/crawlertemplates/index.html')
c = Context({'Directory_list': Directory_list,})
return HttpResponse(t.render(c))
def contactus(request):
Directory_list = Directory.objects.all()
t=loader.get_template('C:/Python27/django/crawler/templates/crawlertemplates/contactus.html')
c = Context({'Directory_list': Directory_list,})
return HttpResponse(t.render(c))
def search(request):
if 'what' in request.GET and request.GET['what']:
what = request.GET['what']
crawlerapp = Directory.objects.filter(Catogory__icontains=what)
return render(request, 'C:/Python27/django/crawler/templates/crawlertemplates/search.html',
{'crawlerapp': crawlerapp, 'query': what})
elif 'who' in request.GET and request.GET['who']:
who = request.GET['who']
crawlerapp = Directory.objects.filter(Bussiness_name__icontains=who)
return render(request, 'C:/Python27/django/crawler/templates/crawlertemplates/search.html',
{'crawlerapp': crawlerapp, 'query': who})
else:
message = 'You submitted an empty form.'
return HttpResponse(message)
And my urls.py is::
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'crawler.views.home', name='home'),
# url(r'^crawler/', include('crawler.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
url(r'^crawlerapp/$', 'crawlerapp.views.index'),
url(r'^crawlerapp/contactus/$', 'crawlerapp.views.contactus'),
url(r'^crawlerapp/search/$', 'crawlerapp.views.search'),
)
I have 3 html pages INDEX, CONTACTUS, and SEARCH.
Please suggest an alternative of Absolute path so that it create no errors if I someone else clones it from GITHUB and try to run it.
Please help to solve this.

You should list you're template directories in your setting.py files, in the TEMPLATE_DIRS list.
Whether you do that or not, you should dynamically generate the absolute path by using the os.path module's function.
os.path.abspath(__file__)
will return the absolute path to the file it's called in.
os.path.dirname('some/path')
will return the path to the last directory in 'some/Path'
By combining them you can get absolute pathes which will remain accurate on different systems, eg
os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
will return an absolute path to the directory one level above the one containing the current file.
Go read the docs for the os.path module. You'll probably need to use os.path.join as well.

Have you considered reading the Django tutorial?.
Don't forget to set TEMPLATE_DIRS in your settings.py file, a good tip for doing so can be found on another answer; Django template Path

In your project settings.py file:
Add this at the top
import os.path
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
Then to set template path do this:
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, "templates"),
)

With this you going to be in the obligation in a future to recheck your all files to change the path in case if you change directories so: in you settings.py file define:
import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__),'templates').replace('\\','/'),
'/path/to/my/project/'
'/path/to/my/project/template/', # for the apps
)
Where templates/ is the directory for your templates.

Related

Django MEDIA not accessible

My Django app is unable to see MEDIA directory. When I run one of my views I need to open a file. The scenario is to:
take a record with requested id from data base
get the file path to a file
send the file to external server for OCR purposes
urls.py
from django.conf.urls.static import static
urlpatterns = [
#my urls
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
models.py
from django.db import models
from django.contrib.auth.models import User
class Homework( models.Model):
title = models.CharField(max_length = 200, default = None)
image = models.FileField(upload_to='user_scans/')
author = models.ForeignKey(User, default=None, on_delete = models.CASCADE)
latex = models.TextField(default = "No LaTeX Here")
settings.py:
from pathlib import Path
from django.conf.urls.static import static
BASE_DIR = Path(__file__).resolve().parent.parent
...
DEBUG = True
...
STATIC_ROOT = BASE_DIR / 'static'
STATIC_URL = '/static/'
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = "/media/"
views.py
import requests
import json
from django.shortcuts import render, get_object_or_404
from .models import Homework
def create_homework(request):
if request.method == 'GET':
#some GET stuff
if request.method == 'POST':
homework = Homework()
homework.title = title
homework.image = image
homework.author = author
homework.save()
id = homework.id
json_to_mathsnip(id)
....
def json_to_mathsnip(id):
homework = get_object_or_404(Homework, pk=id)
f = open(homework.image.url, "rb")
...
some later stuff
...
Unfortunately I'm constantly running into an error:
FileNotFoundError at /homework/new
[Errno 2] No such file or directory: '/media/user_scans/kwa.png'
My main concern is I can access file from localhost:8000/media/user_scans/kwa.png
and from admin panel. Requested file is saved properly:
Also settings.py configuration seems to be in tact. What might be the issue?
(env) $ pip freeze
asgiref==3.5.0
backports.zoneinfo==0.2.1
certifi==2021.10.8
charset-normalizer==2.0.12
Django==4.0.1
idna==3.3
Pillow==9.0.0
psycopg2-binary==2.9.3
requests==2.27.1
sqlparse==0.4.2
urllib3==1.26.9
This may not be the best way, but I tried it and it works. The bottom line is that when using the open() function with a relative path, such as /media/user_scans/kwa.png, then that file must be in the same directory as where the function is called. You could just find the absolute path of your image files in your computer, then append the filename to that and it will work, or you can do what I have below.
import requests
import json
from django.shortcuts import render, get_object_or_404
from .models import Homework
# ADD THESE
import os
from pathlib import Path
def create_homework(request):
if request.method == 'GET':
#some GET stuff
if request.method == 'POST':
homework = Homework()
homework.title = title
homework.image = image
homework.author = author
homework.save()
id = homework.id
json_to_mathsnip(id)
....
def json_to_mathsnip(id):
homework = get_object_or_404(Homework, pk=id)
# ADD THESE
BASE_DIR = Path(__file__).resolve().parent.parent
path_to_image_file = str(BASE_DIR) + homework.image.url
f = open(path_to_image_file, "rb")
...
some later stuff
...
When you show an image in Django, or you access its url, it is a relative path, but the root is the url root, localhost:8000/, and the image url is appended to that, and Django manages to find the file (how exactly, I don't know). But the image file is in your computer, and that is what you want to open.

unable to display images from model usingo django

in settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'pictures')
MEDIA_URL = '/pictures/'
in models.py
class Campaign(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
# this is many to one relationship, on_deleting user, profile will also be deleted
campaign_title = models.CharField(max_length=200, blank=True)
campaign_image = models.ImageField(default="default_campaign.png",upload_to="campaign_pictures")
in views.py
def landing_page(request):
campaigns = Campaign.objects.all().order_by('-id')
print(campaigns)
return render(request, 'core/landing_page.html',{'campaigns':campaigns})
in landing_page.html
{% for campaign in campaigns %}
<img src="{{campaign.campaign_image.url}}">
{% endfor %}
issue
if file name is abc xyz.jpg, it gets saved into /pictures/campaign_pictures as abc_xyz.jpg
in html template, the src of image should be '/pictures/campaign_pictures/abc_xyz.jpg' but it shows only '/pictures/abc%20xyz.jpg'
I think you missed in urls.py file
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
Also correct it with
campaign_image = models.ImageField(default="default_campaign.png",upload_to="campaign_pictures/")
You can define the 'upload_to' as a callable function and use the os.path to join the directory name with the media url.
Your field will call a function which will provide the path.
campaign_image = models.ImageField(default="default_campaign.png",upload_to=get_campaign_path)
and define your function like this
import os
def get_campaign_path(instance, filename):
return os.path.join('campaign_pictures/',filename)
Reference:
https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.FileField.upload_to

trying to get data from text file to insert into database

I am got stuck to read data from text file which I want to insert into database.
here's my models.py file ..the text file is saved in static folder.
settings.py:
STATIC_URL = '/static/'
STATIC_ROOT=os.path.join(BASE_DIR,'static_cdn')
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static')
]
urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
models.py:
from django.db import models
import os
from django.conf import settings
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=100)
author=models.CharField(max_length=20,blank=True)
#classmethod
def create(cls, title,author):
obj = cls(title=title,author=author)
# do something with the book
return obj
file=open(os.path.join(settings.BASE_DIR,'/static/product.txt','r'))
line=file.readline()
for lines in line:
split_line=lines.split("|")
a=split_line[0]
b=split_line[1]
obj=Book.create(a,b)
obj.save()
please help me ..thanks in advance
You are missing a ) after the '/static/product.txt', so the overall address will be:
<BASE_DIR>/static/product.txt/r
(the os.path.join accept any number of arguments)
Simply change it as:
file = open(os.path.join(settings.BASE_DIR,'static/product.txt'), 'r')
It should work if your file is located at <BASE_DIR>/static/product.txt

I can't figure out how to refer to my template from a Django view

I am new to Django and cannot figure out what the path to my templates is supposed to look like. My project's directory tree looks like this:
blog
blog/blog
blog/blog/__init__.pyc
blog/blog/wsgi.pyc
blog/blog/urls.py
blog/blog/urls.pyc
blog/blog/wsgi.py
blog/blog/__init__.py
blog/blog/settings.py
blog/blog/settings.pyc
blog/home
blog/home/views.py
blog/home/templates
blog/home/templates/home
blog/home/templates/home/main.html
blog/home/__init__.pyc
blog/home/urls.py
blog/home/urls.pyc
blog/home/models.py
blog/home/tests.py
blog/home/__init__.py
blog/home/views.pyc
blog/manage.py
Here is my view (from blog/home/view.py):
from django.shortcuts import render_to_response
def home(request):
return render_to_response("home/main.html", {"name" : "maxwell"})
A redacted copy of my settings.py file can be found here: http://pastebin.com/UMTepK9j
And finally, here is the error I get when I browse to 127.0.0.1:8000:
TemplateDoesNotExist at /home/main.html
Can anyone tell me what the path ought to look like in my call to render_to_response?
The TEMPLATE_DIRS in your settings.py should point to the template folder.
Should be something like this:
TEMPLATE_DIRS = (
'../home/templates'
)
That should work.
Note: There you're using relative paths which is not recommended. You should have something like this in your settings.py:
import os
settings_dir = os.path.dirname(__file__)
PROJECT_ROOT = os.path.abspath(os.path.dirname(settings_dir))
...
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, '../home/templates/'),
)
Also, you're calling render_to_response without passing it a RequestContext. With this, your templates will lack of some variables important for your project like user. It's better to call it this way:
return render_to_response(
"home/main.html",
context_instance=RequestContext(
request,
{'name':'maxwell'}
)
)

Django Context Processor Trouble

So I am just starting out on learning Django, and I'm attempting to complete one of the sample applications from the book. I'm getting stuck now on creating DRY URL's. More specifically, I cannot get my context processor to work. I create my context processor as so:
from django.conf import settings
#from mysite.settings import ROOT_URL
def root_url_processor(request):
return {'ROOT_URL': settings.ROOT_URL}
and I placed this file in my app, specifically, mysite/photogallery/context_processors.py . My settings.py file in the root of my project contains:
TEMPLATE_CONTEXT_PROCESSORS = ('mysite.context_processors',)
When I try to go to the ROOT_URL that I've also specified in my settings.py, I receive this error:
TypeError at /gallery/
'module' object is not callable
/gallery/ is the ROOT_URL of this particular application. I realize that perhpas this could mean a naming conflict, but I cannot find one. Furthermore, when I comment out the TEMPLATE_CONTEXT_PROCESSORS definition from settings.py, the application actually does load, however my thumbnail images do not appear (probably because my templates do not know about ROOT_URL, right?). Anyone have any ideas as to what the problem could be?
EDIT: Here's some information about my settings.py in case it is of use:
ROOT_URLCONF = 'mysite.urls'
ROOT_URL = '/gallery/'
LOGIN_URL = ROOT_URL + 'login/'
MEDIA_URL = ROOT_URL + 'media/'
ADMIN_MEDIA_PREFIX = MEDIA_URL + 'admin/'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
TEMPLATE_CONTEXT_PROCESSORS = ('mysite.photogallery.context_processors',)
EDIT2: I'm going to add some information about my url files. Essentially I have a root urls.py, a real_urls.py which is also located at the root, and a urls.py that exists in the application. Basically, root/urls.py hides ROOT_URL from real_urls.py, which then includes my app's urls.py.
root/urls.py:
from django.conf.urls.defaults import *
#from mysite.settings import ROOT_URL
from django.conf import settings
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
(r'^blog/', include('mysite.blog.urls')),
url(r'^%s' % settings.ROOT_URL[1:], include('mysite.real_urls')),
)
root/real_urls.py:
from django.conf.urls.defaults import *
from django.contrib import admin
urlpatterns = patterns('', url(r'^admin/(.*)', admin.site.root),
url(r'^', include('mysite.photogallery.urls')),
)
root/photogallery/urls.py (note that this one probably is not causing any of the problems, but I'm adding it here in case anyone wants to see it.):
from django.conf.urls.defaults import *
from mysite.photogallery.models import Item, Photo
urlpatterns = patterns('django.views.generic', url(r'^$', 'simple.direct_to_template', kwargs={'template': 'index.html', 'extra_context': {'item_list': lambda: Item.objects.all()}
},
name='index'), url(r'^items/$', 'list_detail.object_list', kwargs={'queryset': Item.objects.all(), 'template_name': 'items_list.html', 'allow_empty': True },
name='item_list'), url(r'^items/(?P<object_id>\d+)/$', 'list_detail.object_detail', kwargs={'queryset': Item.objects.all(), 'template_name': 'items_detail.html' }, name='item_detail' ), url(r'^photos/(?P<object_id>\d+)/$', 'list_detail.object_detail', kwargs={'queryset': Photo.objects.all(), 'template_name': 'photos_detail.html' }, name='photo_detail'),)
TEMPLATE_CONTEXT_PROCESSORS should contain a list of callable objects, not modules. List the actual functions that will transform the template contexts. Link to docs.

Categories