anon says hello
anon says hello

Reputation: 141

django admin panel image field produces wrong path to image

I have an image field that uploads to the media/ directory. In the django admin panel, it links to admin/api/character/2/change/media/image.jpg, instead of media/image.jpg. How do I correct this?

edit: the html are all default django admin templates. in fact, nothing about this is special. the imagefield is straight django. the admin template is straight django. the implementation is all straight django. settings.py looks like this

 13 import os
 14 
 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 17 
 23 from loot_tracker.secrets import secrets
 24 SECRET_KEY = secrets['secret_key']
 25 
 27 DEBUG = True
 28 
 29 ALLOWED_HOSTS = ['*',]
 33 
 34 INSTALLED_APPS = [
 35     'jet.dashboard',
 36     'jet',
 37     'django.contrib.admin',
 38     'django.contrib.auth',
 39     'django.contrib.contenttypes',
 40     'django.contrib.sessions',
 41     'django.contrib.messages',
 42     'django.contrib.staticfiles',
 43 
 44     'django_extensions',
 45     'django_filters',
 46     'django_user_agents',
 47     'rest_framework',
 48     'tracking_analyzer',
 49 
 50     'api',
 51 ]
 52 
 53 MIDDLEWARE = [
 54     'django.middleware.security.SecurityMiddleware',
 55     'django.contrib.sessions.middleware.SessionMiddleware',
 56     'django.middleware.common.CommonMiddleware',
 57     'django.middleware.csrf.CsrfViewMiddleware',
 58     'django.contrib.auth.middleware.AuthenticationMiddleware',
 59     'django.contrib.messages.middleware.MessageMiddleware',
 60     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 61 ]
 62 
 63 ROOT_URLCONF = 'loot_tracker.urls'
 64 
 65 TEMPLATES = [
 66     {
 67         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 68         'DIRS': [],
 69         'APP_DIRS': True,
 70         'OPTIONS': {
 71             'context_processors': [
 72                 'django.template.context_processors.debug',
 73                 'django.template.context_processors.request',
 74                 'django.contrib.auth.context_processors.auth',
 75                 'django.contrib.messages.context_processors.messages',
 76             ],
 77         },
 78     },
 79 ]
 80 
 81 WSGI_APPLICATION = 'loot_tracker.wsgi.application'
 82 
 87 DATABASES = {
 88         'default': {
 89         'ENGINE': 'django.db.backends.postgresql_psycopg2',
 90         'NAME': 'postgres',
 91         'USER': 'postgres',
 92         'PASSWORD': secrets['db_pass'],
 93         'HOST': 'db',
 94         'PORT': '',
 95     }
 96 }
 97 
102 AUTH_PASSWORD_VALIDATORS = [
103     {
104         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
105     },
106     {
107         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
108     },
109     {
110         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
111     },
112     {
113         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
114     },
115 ]
120 
121 LANGUAGE_CODE = 'en-us'
122 
123 TIME_ZONE = 'UTC'
124 
125 USE_I18N = True
126 
127 USE_L10N = True
128 
129 USE_TZ = True
134 
135 STATIC_URL = '/static/'
136 STATIC_ROOT = os.path.join(BASE_DIR, 'public')
137 
138 REST_FRAMEWORK = {
139     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
140     'PAGE_SIZE': 50
141 }
142 
143 CORS_ORIGIN_ALLOW_ALL = True
145 
146 GEOIP_PATH = os.path.join(BASE_DIR, 'geoip/')
147 
148 CLIENT_ID = secrets['client_id']
149 CLIENT_SECRET = secrets['client_secret']
~                                                   

models.py, note the avatar field.

  8 class Character(models.Model):
  9     name = models.CharField(max_length=20, unique=True)
 10     level = models.IntegerField(default=2)
 11     game_class = models.CharField(max_length=20)
 12     guild = models.ForeignKey('Guild', blank=True, null=True, on_delete=models.PROTECT)
 13     avatar = models.ImageField(upload_to='media/', default='media/tyrone.jpg')

admin.py for brevity

  9 class CharacterAdmin(admin.ModelAdmin):
 10     search_fields = ('name', 'game_class', 'level')
 11 admin.site.register(Character, CharacterAdmin)


Upvotes: 0

Views: 668

Answers (1)

Victor
Victor

Reputation: 2919

Assumptions:

  • You serve the django admin through mysite.com/admin/
  • You have a directory in your server named .../media/ where files are uploaded correctly
  • These files in .../media/ are correctly served through the URL mysite.com/media/ (e.g. If you manually type mysite.com/media/myfile.jpg in your browser you get the file .../media/myfile.jpg in your server)
  • You are in mysite.com/admin/api/character/2/change/ and you have a file field there where you can upload files (and you see them in your server when uploading)

Issue:

  • The URL/link of the file being presented by the Django admin AFTER uploading is mysite.com/admin/api/character/2/change/media/image.jpg, instead of mysite.com/media/image.jpg

Solution:

  • In the settings of your Django app, define the setting MEDIA_URL so Django knows where to serve the media files from. Since you haven't defined the setting, it defaults to MEDIA_URL='', so in effect it only appends the file's path to the current URL.

Side Note:

  • The upload_to parameter in FileField refers to the directory INSIDE the storage you are using. In this case, if you are uploading files to a folder in your server named /home/mysite/media/, and you set upload_to='media/', all files uploaded to that field will be uploaded to /home/mysite/media/media/.

Upvotes: 1

Related Questions