2

There is a model Language. Language objects creates Admin through Django-admin. They have to choose from dropdown menu appropriate flag file.

The problem is that there is not flag to choice when I deploy project.

Since static files are being collected before deploy, I tried to set this path:

flag = models.FilePathField(path='static/img/flags/550px',default='')

But as you can see, it can't find anything.

enter image description here

I can choose from flags if I do this:

flag = models.FilePathField(path=settings.BASE_DIR+'/static/img/flags/550px',default='')

But then it doesn't work just calling language.flag because it returns absolute path.

<img src = "{{ language.flag }}">

produce this:

<img src="/home/django/MyProject/static/img/flags/550px/ar.png">

The only solution which comes to my mind is to create a property which strips path cutting "/home/django/MyProject/" but I'm not sure if it is a good idea.

Is there a better way?

class Language(models.Model):
    shortcut = models.CharField(max_length=40,
                                help_text=_('Shortcut of the language'),
                                unique=True)

    name = models.CharField(max_length=40,
                            help_text=_('Name of the language'),
                            unique=True, verbose_name=_("Language"))

    flag = models.FilePathField(path='static/img/flags/550px',default='/static/img/icons/check-icon.png')

    def __str__(self):
        return self.name

EDIT:

Admin.py:

from django.contrib import admin
from models import  Language

admin.site.register(Language)
Milano
  • 18,048
  • 37
  • 153
  • 353

2 Answers2

2

FilePathField.path
Required. The absolute filesystem path to a directory from which this >FilePathField should get its choices. Example: "/home/images".

Emphasis mine.

And when you use an absolute path here, your template really does produce a relative path I can't tell you what that is because that path you have set in the FilePathField and the path that you claim to get contradict each other. But i can assure you that the template will give a relative path.

Not sure, if it's a bug (probably is) but your admin is saving the full path in the flag object instead of just the relative path. So I guess using a property is one option

 @property
 flag_path(self):
     return self.flag.replace(settings.BASE_DIR,'')

The other option is to overide the admin save model method to do the stripping at that point

e4c5
  • 52,766
  • 11
  • 101
  • 134
  • No, when I do {{ language.flag }} in template I get /home/django/myproject/static/... but I need /static/.... so I dont understand what to do. – Milano Jan 17 '17 at 12:45
  • First fix the inconsistencies in your question. Then add the admin. I suspect you might be having a problem there – e4c5 Jan 17 '17 at 12:46
  • What inconsistencies do you mean? I've corrected a path. The problem is that FilePathField allows me to choose from flags if there is an absolute way set (BASE_DIR + /static/....). But when I choose from flags this way, then, in template, {{ language.flag }} returns /home/django/myproject/static/... but I need just /static/.... – Milano Jan 17 '17 at 13:03
  • I've added an admin.py but there is nothing except admin.site.register(Language) – Milano Jan 17 '17 at 13:04
  • please see the upate – e4c5 Jan 17 '17 at 13:28
  • It is a [bug](https://code.djangoproject.com/ticket/6896) against relative path of FilePathField. And a [proposed module](https://bitbucket.org/alexhayes/django-relativefilepathfield). I don't know if this module is uptodate – somenxavier Jul 15 '17 at 18:05
0

A design decision was made by Django to not give the option of storing a relative path in FilePathField (https://code.djangoproject.com/ticket/6896). Instead, @alexhayes kindly provided a RelativeFilePathField that stores relative paths, and otherwise works the same as FilePathFIeld: https://bitbucket.org/alexhayes/django-relativefilepathfield/src/master/.

Very briefly, you:

pip install django-relativefilepathfield

Then,you use it in your model like:

from relativefilepathfield.fields import RelativeFilePathField

class Language(models.Model):
    ...
    absflagpath = os.path.join(settings.BASE_DIR,'/static/img/flags/550px')
    flag = RelativeFilePathField(path=absflagpath, default='check-icon.png')

Admin works like it should, the choices being displayed and selected in the UI are the very same things as what's stored in the DB (!). language.flag returns just the relative part. Language.absflagpath is a class attribute/variable that is not stored in the DB, and returns the absolute path that the stored relative paths are relative to. Note that the default parameter for flag is relative.

iggie
  • 452
  • 4
  • 7