We are making our school site on Django, we made a gallery app but i think the images are not getting uploaded to designated folder, rather they are not even getting uploaded i think so .
Code : -
# views.py
def upload(request, template_name="gallery/form.html"):
form = GalleryForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
messages.success(request, "image has been uploaded")
return redirect('gallery.views.index')
return render(request, template_name,{'form':form})
from django.db import models
# models.py
class GalleryPhoto(models.Model):
image = models.ImageField(upload_to='pic_folder/')
description = models.CharField(max_length=50)
def __unicode__(self):
return self.image.url
The rest of the code can be seen in this repo
Note : the the gallery template contains some conflicts but that is not the actual problem.
It took me a while to notice it, because it's kinda tricky. But in retrospect it's obvious.
So after configuring MEDIA_URL = "/MEDIA/" I noticed that http://127.0.0.1:8000/media/ was giving me a 404. If everything is configured correctly (and it is) then usually the problem is conflicting urls. See the url patterns used in django are always evaluated in order. That means if you have urls like so:
url(r'^mypage/', 'myapp.mypage'),
url(r'^mypage/another/', 'myapp.different')
Then the second url will never be available. Why? because there's nothing up there that tells the url dispatcher that the first url should end at mypage/. As far as it's concerned, everything starting with http://DOMAIN/mypage/ will be caught and passed to the first function.
To avoid that, we use the $ sign to tell the dispatcher at what point to stop. Like so:
url(r'^mypage/$', 'myapp.mypage'),
url(r'^mypage/another/$', 'myapp.different')
Now let's look at your last two urls:
url(r'^', include('pages.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
See that? url(r'^' swallows everything that comes after it, so no media is being served. It's true that pages.urls uses a dollar for its first url:
url(r'^$', views.index, name='index'),
but that doesn't matter for the main url dispatcher, which evaluates r'^' first. What's the solution? the simplest would be to move the pages urls to the end:
url(r'^ckeditor/', include('ckeditor.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += patterns('', url(r'^', include('pages.urls')))
You can also isolate that one problematic url from the others using a direct call, like so:
url(r'^/$', 'pages.views.index'),
url(r'^pages/$', include('pages.urls')),
After that, this will work:
<img src="{{ MEDIA_URL }}{{ image.image.url }}" alt="{{ image.description }}">
p.s.
Eventually you're going to pass the media and static files through your server, when you move to deployment level, so maybe the whole thing wouldn't matter then. If you do decide to keep the r'^' in use, just keep in mind that it might cause conflicting problems with other urls, so be sure to always put it last.
Related
There is a complex app (not possible to just paste the code). Going to try to explain.
Django
There is a urls.py file from the native Django app. The urlpatterns defines and register its urls. The ^foo/ defines a group of related urls and the foonamepsace.
urlpatterns = patterns('',
...
url(r'^foo/', include('foo.urls', namespace='foonamespace')),
...
Now there is a method generate_report which does some logic inside and then uses render_to_string to return the HTML:
def generate_report(..):
...
return render_to_string('foo/foo_report.html', args)
Everything works inside the app, the url get reversed successfully.
Django Rest Framework (DRF)
Now there is a DRF implementation and one of its resources is supposed to return a report in a binary format.
class PDFReportViewSet(APIView):
renderer_classes = (BinaryFileRenderer, )
def get(..):
...
pdf = generate_report() # <-- fails with NoReverseMatch
...
return response
Problem
The ViewSet calls the generate_report, however one gets an error when trying to parse the HTML:
NoReverseMatch: foonamespace' is not a registered namespace
Question
Any clues why DRF cannot reverse the namespcae/url from the the core of Django app? How to make sure DRF can reverse a namespace from the core urls.py urlpattern?
Added
After investigation, inside the foo_report.html any usage of the url, for example {% url 'foonamespace:123' %} or {% url 'barnamespace:123' %} produces the error - only if ran from the DRF (running the same page using native Django works fine).
URLS
foo.urls.py
from django.conf.urls import patterns, url
from foo.views import (FooListView, FooDetailView...)
urlpatterns = patterns('',
url(r'^$', FooListView.as_view(), name='foo_list'),
url(r'^(?P<pk>\d+)/$', FooDetailView.as_view(), name='foo_details'),
Important note. The app is served at some.domain.com/, while the REST is served from some.domain.com/rest. So may be this way /rest just don't include anything because it is a parent of the root (which includes the foo.urls.py)
I was managed to resolve my issue with the help from #dirkgroten. It was difficult to see the problem without looking at the source code.
Solution
Updated the routers.py file:
urlpatterns = router.urls
urlpatterns += patterns('',
url(r'^foo/', include('foo.urls', namespace='foonamespace')),
)
Explanation
Basically, the app was serve from the root url / while the rest was served from /rest. The DRF router simply didn't include any of the root routes. Adding them manually like it is shown in solution resolved the problem and made foonamespace visible for all DRF elements.
I have yet to wrap my head around django and URLs, and my confusion is now preventing me from doing what I feel like should be a very simple task.
I have successfully implemented file upload.
In my settings.py file, I have added the specifications for where to store the uploaded files and the URL Django should use to serve them.
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL= '/media/'
I also added the necessary line to urls.py to allow Django to serve files from MEDIA_URL.
from django.conf.urls import url, include
from django.contrib import admin
from login_app import views as login_app_views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', login_app_views.login_user),
# creating registered namespaces for each app
url(r'^login/', include('login_app.urls', namespace = "login_app")),
url(r'^CMIRS/', include('dashboard_app.urls', namespace = "dashboard_app")),
url(r'^CMIRS/', include('submit_app.urls', namespace = "submit_app")),
url(r'^CMIRS/', include('filter_app.urls', namespace = "filter_app")),
url(r'^CMIRS/case/',include('report_app.urls', namespace = "report_app")),
url(r'^CMIRS/', include('search_app.urls', namespace = "search_app")),
url(r'^search/', include('haystack.urls')), ##used in navbar-search
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In an app report_app, I want the webpage to display a hyperlink that can be used to view an uploaded file. When I click on the hyperlink, I want it to request the URL to the uploaded file.
The upload looks like such in my models:
upload1 = models.FileField(upload_to = 'documents/%Y/%m/%d/')
I am having trouble figuring out what to use in the render(request) in my view and how to correctly code this in HTML. When I attempt to use "media", I get an error saying it cannot be matched.
Here is a snippet of the HTML I am trying:
<dt>Upload</dt><dd><tr><td>{{ case.upload1 }}</td></tr></dd>
I am also confused as how to set up my render(request) so that it knows to access media/, and then go to the correct documents/Y/M/D depending on the primary key.
You don't want to use the url tag here at all. Your media's URL is stored in your model, and has nothing to do with Django's path resolution logic. Just reference the url method of the field:
<a href="{{ case.upload1.url }}">
See the docs.
(Note also that serving files via your urls.py like this works in dev only; for prod you'll need to configure your webserver to do it.)
I'm trying to change the url of http://localhost:8000/stories-and-literature/fairy-tales/ to http://localhost:8000/stories-and-literature/classic-literature/, and I'm not to sure how I can change it in my urls.py. So far, I have this code in urls.py:
from django.conf.urls import patterns, url
from topictree import views
urlpatterns = patterns('',
(r'^$', 'topictree.views.index'),
(r'^(?P<slug>\D+)/$', 'topictree.views.tree')
)
I want to change the slug of url from "fairy-tales" to "classic-literature" because I want to present the url like a tree. In this case, both "fairy-tales" and "classic-literature" are children of "story-and-literature", so when I click on the "fairy-tales" link and then click on the "classic-literature" link, the "fairy-tales" slug should be removed, and be replaced by the "classic-literature" slug.
I was thinking of changing the url in views.py instead of urls.py since views.py contains the control flow of the program. Is it possible to change the url in views.py instead of urls.py?
Any help would be much appreciated.
Foo Bar User's link is a good place to start but judging by your question I would say you should go straight to the Django Docs
https://docs.djangoproject.com/en/1.6/topics/http/urls/
That should get you back on your feet. :)
I'd like to run two apps with the same url patterns. I would like to avoid having an app-specific slug like domain.com/pages/something-here or domain.com/blog/something-there.
I tried this:
# urls.py
urlpatterns = patterns('',
url(r'^$', 'my.homepage.view'),
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('pages.urls')),
url(r'^', include('blog.urls')),
)
# pages/urls.py
urlpatterns = patterns('',
url(r'^(.+)/$', views.page),
)
# blog/urls.py
urlpatterns = patterns('',
url(r'^(.+)/$', views.post),
)
My code doesn't work, whichever include comes first (here, pages.urls) works ok, other urls (for blog) throw 404.
Thanks in advance
EDIT: I did it like this: created glue.py in the same directory as settings.py. It will handle my homepage and this dispatcher view:
def dispatcher(request, slug):
try:
page = get_object_or_404(Page, slug=slug)
return render(request, 'pages/page.html', {'page': page})
except:
post = get_object_or_404(Post, slug=slug)
return render(request, 'blog/post.html', {'post': post})
I don't know if it's ok. I hope there is a better way.
Thanks for the comments.
I don't know if this is a better answer. But, if these situations are satisfied for you..
if your django app is based on django template rendering.
The url you are talking about, need not be accessed directly by typing the endpoint in the browser itself.
Then, maybe you could consider url namespaces and template redirections.
https://docs.djangoproject.com/en/1.11/topics/http/urls/#url-namespaces
This doesn't work because django urls are resolved in order, meaning that the first url that matches the regexp will be the resolved one. In your case, the the urls included from the blogs application will never be searched, as django already resolved the url on the pages includes line.
Also, the django url module is not supposed to know if a certain page or blog post exists, as i believe in your application this is determined with a database lookup.
The urls module just executes the view that is connected to the first regexp that matches.
You should change your logic, e.g. with perpending "blog/" to blog urls (what's wrong with that?)
url(r'^blog/', include('blog.urls')),
url(r'^', include('pages.urls')),
Notice that the i moved the blog url up, as most generic regxexp should always be the last to be tried by django url resolver.
Alternatively, you could code a proxy view that tries both blog posts and pages. but it doesn't seem the best way to do it to me.
How would you like this to work? They're both using the same URL (which of course is causing problems). How would a user get to a "page" rather than a "blog" or vice versa?
In general, you can't have overlapping URLs in your URL patterns (without including additional data).
EDIT:
So you want the first app to check if it has a view to match the URL and next to take over if the first doesn't? You could do something complicated like writing a "view matcher" to do want you want, but there are much more straigtforward solutions.
The easiest way would be to alter the slug generation function for one of your apps. Have one use some delimeter other than underscores, or always append the name of the app to the slug. This way you could find pages because their url would be "some-slug-page" and blogs would be "some-slug-blog", which you could then write a URL pattern for. If you don't want to add the entire URL, you can append/prepend just the first letter, or whatever you want.
Just think about a way that's acceptable to you to generate URLs for each app which, just by reading the URL, lets you know which app the page belongs to.
I've building a app right now that I'm trying to keep properly decoupled from the other apps in my Django project (feel free to lecture me on keeping Django apps decoupled, I'd be happy to learn more any/all the time).
My problem is this: The get_ absolute_url() method I've written is returning a relative path based on my view. I think it's wrong to have to add a special named view in the project urls.py just so I can have absolute urls in my app, and I can't figure out what I'm doing wrong. So if someone can help me out, I'll really appreciate it (and mention you when I release this sucker!)
I have a project-level urls.py that includes another urls.py based on the URL pattern like so (the names are verbose for this example only):
project-urls.py
urlpatterns = patterns('',
('^$', direct_to_template, {'template': 'base.html'}),
(r'^app', include('project.app.urls')),
)
app-urls.py
urlpatterns = patterns('',
url(r'(?P<slug>[-\w]+)?/?$', 'app.views.home', name='app_home'),
)
Now, in my Model, I have something like this:
class AppModel(models.Model):
title = models.CharField(_('title'), max_length=100)
slug = models.SlugField(_('slug'), unique=True)
#permalink
def get_absolute_url(self):
return ('app_home', None, {'slug': self.slug})
When I call {{ AppInstance.get_ absolute_url }} in the template, I get something like this:
/slug-is-here
Which is obvs not absolute & makes sense based on my urls.py. What should I change to get a real absolute url while keeping this app clean & not couple it too deeply w/the project?
Welp,
It turns out that when I was seeing this:
/slug-is-here
I should have looked closer. What was really happening was:
/app-pathslug-is-here
I was missing a trailing slash on my app's regex in my project urls.py.
So yea. let that be a lesson to y'all.