Confused about configuring django-avatar for storing avatar - python

Edit: Some random edits seem to do the work, but I don't understand how.
I have just "installed" the app django-avatar into my django project. (currently, it is under development, so I am using the server which comes with django)
However. after I upload an avatar, neither can I find the avatar in any folder, nor is it being displayed. I am new to django, and python, so I don't know what to do, or which part of my code to post. I am completely clueless. I have set up a url, at which static files are server(via django.views.static.serve)
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
(settings is imported)
However. I feel this is wrong. I would like some guiding.
Media/Static related settings:
MEDIA_ROOT = 'd:/a4m/media/'
MEDIA_URL = '/media/'
STATIC_ROOT = ''
STATIC_URL = '/static/'
STATICFILES_DIRS = (('d:/a4m/static/'),)
As for templates, I am just using the ones which django-avatar provides.

First, don't add your project's static directory to STATICFILES_DIRS. You shouldn't be manually putting anything in that directory, so there's no reason to serve it in development (which is why Django doesn't by default). Also, I don't think it's related to this issue, but STATIC_ROOT needs a real value, which should be in your case:
STATIC_ROOT = 'd:/a4m/static/'
That said, two things from looking at the django-avatar source:
It uses a setting named AVATAR_STORAGE_DIR, so you should probably define that if you haven't. It seems the following would be sensible:
AVATAR_STORAGE_DIR = MEDIA_ROOT + 'avatars/'
If, for whatever reason, the avatar can't be written to the filesystem, django-avatar returns silently. So, I would check things like permissions to ensure that Django will have no problems writing to any directory under AVATAR_STORAGE_DIR.
Hopefully, that will be enough to get you a further in debugging this issue.

Related

Changing the name of the sub folder inside Django Template path

I am new to Django and I have a path to my HTML file as
./templates/registration/login.html and I want to change it to
./templates/index/login.html
After renaming it to /templates/index/login.html, it is still picking up the old directory /templates/registration, could not find login.html screen and it throws an error.
Could someone tell me what changes we have to make in settings.py when we rename a folder name inside templates structure?
In your settings.py, you can define the templates location, which applies the template function per app.
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates')
)
I assume your app is named registration, hence why it is looking there. You can either rename your app or place all your templates in a global folder at the same level as the apps (and not within the apps themselves). The latter is not recommended for large applications.
Edit: Why is this labeled Python2? What version of Django is this?

Django: how to get template views to display images -- Noob edition

Note: There are a lot of questions related to this on Stack Overflow. However, this is not duplicate, as it requests noob level explanation (i.e. someone who has completed the Django tutorial).
So I completed the Django tutorial and am off to make my own site to reinforce what I learned (and augment it as well). I wanted to make a site which could display some images of a given object. Since a lot of the before mentioned posts use goods and pictures (e.g. to emulate multiple images for a product on Amazon), lets go with that for this post as well.
I made myself an app, and am using name-spaced urls and templates (as described in the tutorial).
In addition, following the Many-to-One documentation, I have two models Product and ProductImage with the latter having a ForeignKey to the former.
class Product(models.Model):
...
class ProductImage(models.Model):
product = models.ForeignKey("Product", on_delete=models.CASCADE)
image = models.ImageField(upload_to=product_dir_path)
Using a reverse many-to-one monitor (e.g. aSpecificProduct.productimage_set.all() ) I grabbed all my images which I set up in a directory under the app's directory <my_app>/uploads/product_<id>/image_<id> using the little upload_to trick in the model field reference part of the documentation.
def product_dir_path(instance, filename):
return "<my_app>/uploads/product_{0}/{1}".format(instance.product.id, filename)
Great, so I am all ready to make a view that grabs a specific item, uses the above semantics to get all the images for that item, and use a template view to display those images!
So I put these images into a variable img_list and put it into my context, which is passed to render as an argument.
I have a loop set up and inside that loop I have
<img src="{{img.image.url}}"/>
which when inspecting the website I see
<img src="<my_app>/uploads/<specific_product>/image_<number>.png"/>
awesome!... except for the 404 error.
Now a lot of these other posts talk about setting MEDIA, MEDIA_ROOT, STATIC, in settings.py and adding something to the urlpatterns (but not specifying if it is the project urls.py or the app one...).
There is some other text explaining this, but waaaaay too technical for someone who just completed the django tutorial and has no idea what any of these things do, or why they are needed. To be fair, the ModelField reference for ImageField and FileField do not make it that clear either (at least to me) as to how one would do this (whereas the documentation for Many to One has plenty of examples to figure it out).
So, please, in a tutorial like fashion, what am I missing to getting my images to display? Please be very explicit as to what files are being changes (e.g. my_site/urls.py vs my_app/urls.py), what these changes do, and why they are needed. Given the host of actual duplicates, it is clear that figuring this out is not!
Thanks
EDIT:
I moved the where the file "uploads" to be under <my_app>/static/<my_app> and renamed it to product_images. Following the linked page on static files I tried the following. Hardcoding the link works. Using the solution by most of the other posts, does not.
<img src="{% static '<my_app>/product_images/product_<id>/<img_file>' %}"/>
works but
<img src="{{img.image.url}}"/>
does not where the latter has src="<my_app>/static/<my_app>/product_images/product_<id>/<img_file>"
and the former static/<my_app>/product_images/product_<id>/<img_file>
make certain changes to your mysite/urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py file
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static_cdn')
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media_cdn')

Django Doesn't Serve STATIC_ROOT in DEBUG

I'm using Python 3.5 and Django 1.10 to run a development server:
./manage.py runserver 0.0.0.0:8000
In my settings.py I have:
DEBUG = True
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
And an app directory, with a static subdirectory for its static files:
proj/
proj/
...
app/
static/
a.txt
...
static/
b.txt
Pretty standard.
However: Django doesn't serve the STATIC_ROOT when DEBUG = True. It returns app/static/a.txt for /static/a.txt alright, but not static/b.txt for /static/b.txt.
Changing settings.py to read:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
Works - but then I have to comment out STATIC_ROOT (otherwise Django complains it can't be in STATICFILES_DIRS).
Now, I can't just "use a different external static directory", e.g. static2, because I'm using django-sass-processor, which compiles .sass files into .css files, and puts these .css files in the STATIC_ROOT (which, as I've said, is inaccessible).
Things I've tried:
Settings up NGINX to serve that directory (like in a production environment). Works, but there just has to be another way.
Configuring django-sass-processor to write the .css files into said "different external static directory", e.g. static2, and including it in STATICFILES_DIRS. Again, works, but it just can't be that complicated!
Manually adding static files URLs in urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
This one was quite a trip, so I thought I'd share it to save other people the trouble: it turns out that Django does that anyway, and actually overwrites my URLs - but it includes, as I've said, only my apps' static directories and those in STATICFILES_DIRS.
I even changed DEBUG to False and removed the if - but that didn't work as well, because then the django.conf.urls.static.static function actually returns an empty list. So, I implemented it myself using django.views.static.serve, and it finally worked, but again - it doesn't make sense I have to turn off debugging and manually implement serving static file.
Update
If you're working with django-sass-processor and running into similar problems, they've actually provided a solution I just noticed in their documentation: a special static finder you can add in your settings.py like so:
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'sass_processor.finders.CssFinder',
]
(The first two are Django's default finders, so when you override this configuration you should include them manually).
But even now, for anything other than .css files, the STATIC_ROOT is actually the only static directory that is inaccessible via /static/, which I find pretty odd. So, I'd still like to solve (or at least understand...) it.
At first glance it seems very strange that Django doesn't serve files from STATIC_ROOT, but it makes sense when you consider the workflow Django intends for static files. Django expects that you bundle static files alongside apps and you save project-level static files in a separate directory that is checked into version control. Then, when you run manage.py collectstatic the STATICFILES_FINDERS are used to gather up all the files into a single directory (which should not be in version control) so they can be deployed to AWS S3 or whatever.
So the staticfiles finders have two jobs:
find a file via path, used for DEBUG mode static file serving
list all of the available files, used for collectstatic
If you were able to include STATIC_ROOT in your STATICFILES_DIRS then the collectstatic command would probably get stuck in a loop. Also, the Django developers don't intend for you to save files in STATIC_ROOT since it shouldn't be checked into version control.
However, there's times when you actually do want to serve files from STATIC_ROOT. In my case, I have a Celery task that creates thumbnails of uploaded images and saves them to the static files storage. In production that ends up saving on AWS S3 where it can be served.
So, if you have a valid use case for serving files from STATIC_ROOT just define your own file finder and add it's path to STATICFILES_FINDERS:
from django.contrib.staticfiles.finders import BaseFinder
from django.contrib.staticfiles.storage import staticfiles_storage
class StaticRootFinder(BaseFinder):
"""
For debug mode only. Serves files from STATIC_ROOT.
"""
def find(self, path, all=False):
full_path = staticfiles_storage.path(path)
if staticfiles_storage.exists(full_path):
return [full_path] if all else full_path
return []
def list(self, ignore_patterns):
return iter(())

Why absolute paths to templates and css in django ? (Isn't that a bad practice ?)

In django, the documentation asks to use the absolute paths and not the relative paths.
Then, how do they manage portability ?
If I have my template in the project folder then, even a rename of the folder will cause breakage.. !
Then what is the reason behind this practice ?
Please explain ?
Could you post a link to that piece of documentation, please?
In Django you configure, in settings.py, the search path for templates (through TEMPLATE_DIRS variable). Then, inside a view, you render a template naming its file relative to one of the path included in TEMPLATE_DIRS. That way, whenever you move you template dir you just need to modify your settings.py
As for static files, like CSS docs, Django does not need to know anything about them (unless you are serving static files through django itself, which is discouraged by django's documentation): you only need to tell your web server where to find them.
I switch environments from a Linux desktop to a Windows laptop, so hard coding paths won't work for me either.
There may be a better way to do this, but I wrote this function that goes at the top of my settings.py to get the absolute path from a relative path in my project:
#settings.py
import os
def map_path(directory_name):
return os.path.join(os.path.dirname(__file__), \
directory_name).replace('\\', '/')
That allows me to do:
MEDIA_ROOT = map_path('static')
TEMPLATE_DIRS = (
map_path('templates'),
)
"static" and "templates" live under my project root. Hope that helps you out.

What does Django do with `MEDIA_ROOT`?

What does Django do with MEDIA_ROOT exactly? I never understood it. Since Django itself doesn't serve static media, and you have to set up apache or something similar for it, why does it care in which directory it sits?
You're not the only one who wonders; check out Django ticket #10650. Based on the comments by Django developers there, I think this pretty much sums up what MEDIA_ROOT is used for:
Unfortunately, Django is also at fault for being far too vague in its docs about what
MEDIA_ROOT and MEDIA_URL are used for. Searching through Django's code confirms that
MEDIA_ROOT & MEDIA_URL are used for file upload, and that MEDIA_URL is provided as a
convenience to templates via the default context processors (available when using
RequestContext??).
It appears to be used by some classes in Django as a default -- for instance, FileSystemStorage uses it as the default place to store files.
When you creates a model with ImageField or FileField attributes, you should pass the upload_to argument. That is a relative path will be appended to your MEDIA_ROOT path and there will be save and retrieve that files.

Categories

Resources