Changing URL pattern in Django so it doesn't show app name - django

I've got a folder/app named "projects" and there I want to make a new site there, named, let's say, "cheese".
In my urlpatterns in urls.py in projects folder I've got
path('cheese/', views.cheese, name='cheese')
but the whole URL looks like domain.co/projects/cheese
I'd like to omit that projects in URL, so it could just be domain.co/cheese
Those URL-things are kinda hard to understand for me and as I couldn't properly name my problem, I couldn't find a solution out there, though I believe there must be some.

The idea of having an app inside another app is kinda weird, but anyways, that won't enforce the inner app's urls to be like <outer_app>/<inner_app>/... if you set the url patterns correctly.
Basically, you've got domain.co/projects/cheese because, you include your project's app urls as:
# main urls.py file for your project
path('projects/', include('projects.urls'))
and in your project's urls file you have:
# projects/urls.py
path('cheese/', include('projects.cheese.urls'))
So if you want to have the cheese urls as domain.co/cheese, simply add the include to the main url file:
# main urls.py file for your project
path('projects/', include('projects.urls'))
path('cheese/', include('projects.cheese.urls'))

Related

How can I add new URLS to Django 3.2 under /admin?

I am working on upgrading an old Django project to 3.2. Previously, our urls.py for the main project included the following so that the urls from impersonate were below /admin
url(r"^admin/", include(admin.site.urls))
url(r"^admin/impersonate/", include("impersonate.urls")),
When I update this code to django 3.2, I don't seem to be able to include any urls beneath /admin. The following code:
re_path(r"^admin/", admin.site.urls),
re_path(r"^admin/impersonate/", include("impersonate.urls")),
does not work, but it does work if I modify the impersonate line to:
re_path(r"^impersonate/", include("impersonate.urls")),
Basically, I want to preserve all of the impersonate urls to be beneath /admin, if this is still possible. I understand that this does not make them require admin permissions, rather this is just to group all the admin views of the project together.
I have seen that I can write a custom ModelAdmin also, but this will still move the urls to under /admin/myapp/mymodel/my_view/. I do not want the extra part of the path mymodel here.
The solution to this was to reorder the paths:
re_path(r"^admin/", admin.site.urls),
re_path(r"^admin/impersonate/", include("impersonate.urls")),
Any URL patterns you define for custom admin views must occur before the admin patterns.
re_path(r"^admin/impersonate/", include("impersonate.urls"))
re_path(r"^admin/", admin.site.urls),

Problem with i18n urls where I'm redirected to the right url but the template is not found

I read on the documentation page of i18n the following:
Warning
Ensure that you don’t have non-prefixed URL patterns that might collide with an automatically-dded language prefix.
I don't get this warning at all, what's the meaning of it??
I'm actually having a problem where I'm directed to my en/sitepages/news-events-listing or ar/sitepages/news-events-listing by a url defined like this in the root urls.py:
urlpatterns += i18n_patterns(
path("sitepages/", include("sitepages.urls")),
)
and I've put it before thr wagtail urls line, but the template returned by the view inside sitepages/views.py:
def sitepages_view(request):
template = loader.get_template('sitepages/news_events_page_listing.html')
context = {
'news_pages': NewsDetails.objects.all(),
'events_pages': EventsDetails.objects.all(),
'listing_page': NewsEventsListing.objects.first(),
}
return HttpResponse(template.render(context, request))
and the sitepages/urls.py:
app_name = "sitepages"
urlpatterns = [
path("news-events-listing/", sitepages_view, name='listing'),
]
I can't think of anything but this warning, and that I might need to understand it to solve the problem, although I know that the order of urls in the root urls.py matter, so I might include it if anyone's think it might cause the problem but I don't want to make the question too long
Note: if I replace the HttpResponse with a simple one like this HttpResponse('Hi') it works!
If your simple HttpResponse('Hi') works but your Response with the rendered template is not, this has nothing to do with your i18n prefixed URLs but with the loading of the template.
Make sure the template actually exists in PROJECT_ROOT/sitepages/templates/sitepages/news_events_page_listing.html' and sitepages is listed in your INSTALLED_APPS.
As an alternative, you could move the template to any app you've listed in your INSTALLED_APPS and make sure the path, starting from the templates/ directory of that app, matches the template name you use in your view.

Is it possible to hardcode CSS link in django?

I have an django project and want to hardcode a link to CSS (I do not want to use STATIC_FILES...etc). The reason is because I want to be able to click index.html and it will work on browser (including getting the css file).
I put both index.html and index.css in the same directory and added this line in index.html:
<link rel="stylesheet" type="text/css" href="./index.css"/>
When I double-click index.html, it imports index.css perfectly.
However, when I load it with the django development server and open via browser, it does not import the index.css.
What should be done so that index.html takes the index.css?
The answer by Christopher Schäpers works nicely, I'd like to extend her answer by showing how you may actually do what she suggests.
Let's say you have
<link rel="stylesheet" type="text/css" href="/index.css"/>
which means the browser is requesting to localhost:8000/index.css, so in your root urls.py file, you add something like this
from django.urls import path
from django.conf import settings
from django.http import HttpResponse
def css_path(request): # This is basically a "view"
path = settings.BASE_DIR / 'index.css' # For earlier Django version: os.path.join(settings.BASE_DIR, 'index.css')
with open(path, 'rb') as f:
content = f.read()
return HttpResponse(content, content_type='text/css')
urlpatterns = [
# ... (your other url patterns)
path('index.css', css_path)
]
NOTE: Remember to set the content_type keyword argument correctly base on what you are serving (Example: application/javascript for .js, image/png for .png, .etc).
That's because the browser uses a directory based approach.
Say your template directory looks like this:
/home/yura/project/templates/
→ index.html
→ index.css
When opening index.html with your browser it plainly looks for index.css in the same directory, thus for /home/yura/project/templates/index.css.
Now when you run the development server it's not directory based anymore. There's the urls.py file that specifies where each path leads to.
You probably have a route / that leads to index.html even though index.html isn't called nothing. You could also add a route /blog/ that may lead to blog_home.html even though the file is called blog_home.html.
Every url that enters django is routed through the urls.py file.
This is one of django's core concepts. URLs should be user-typable and readable without cruft as .php, .html and so on that comes from directory based approaches like PHP or CGI.
Since you haven't defined a route called /index.css thus index.css isn't found.
If the thing you are doing is a one-off your best bet would be to just add a route to /index.css that delivers index.css.
Otherwise there is no way of doing this, since django isn't directory based, as pointed out above.
You might then want to think about why exactly you want to be able to open the raw html file directly in the browser too, since it makes the django templating language entirely useless for you, thus you can't do anything variable, loop and logic related and are stuck with basic html where you, instead of the django-dev server could just as well use a simple http-server instead.

Django-CMS AppHooks with conflicting urls?

I'm trying to use django-cms app hooks in a different way. I have only an app, with different website pages. For each page, i created an AppHook, since i want to have control of all of them with the cms.
To do that, inside the app, i did a package, with urls.py file for each of the page, example:
/urls
/home_urls.py
/portfolio_urls.py
/contacts_urls.py
Here are the definition of some app hooks:
class WebsiteHome(CMSApp):
name = _("cms-home")
urls = ["website.urls.home_urls"]
apphook_pool.register(WebsiteHome)
class WebsiteServices(CMSApp):
name = _("cms-services")
urls = ["website.urls.services_urls"]
apphook_pool.register(WebsiteServices)
Anyway, the problem is: i don't have any control on the regular expressions. Each one, is entering on the first regular expression that it founds, in this case, the urlpattern in the
website.urls.home_urls
Despite, having different apphHooks.
Example:
if i write a slug contacts (that has an apphook to WebsiteContacts), it still goes to the home_urls.py file, associated with the WebsiteHome (app hook).
Did anyone had a similiar problem?
Basically, what I'm trying to say is that it's something wrong with the regular expression. I can't make:
url(r'^$', [...]),
only:
url(r'^', [...]),
If I put the '$', it doesn't enter on any regex. If I take it, it enters always on the
website.urls.home_urls.py
Despite the slugs having different Apphooks, associated with different urls.py files.
Have you tried r'^/$'? I'm using r'^/?$' in some app-hook urls, but I wonder if r'^$' is failing for you because of a '/'?
As you've defined each of those URL files as individual app hooks in CMS then they'll each get attached to a certain page in the CMS e.g.
www.mysite.com/home
www.mysite.com/contacts
www.mysite.com/services
etc
Because those URL files are attached to pages this should prevent conflict between urlpatterns. For example, I've got an URLs file attached to a CMS app called News which looks like this;
urlpatterns = patterns(
'',
url(r'^(?P<slug>[-_\w]+)/$', NewsDetailView.as_view(), name='news_detail'),
url(r'^$', NewsListView.as_view(), name='news_list'),
)
Which is attached to a page at mysite.com/news so if I go to mysite.com/news/myslug I hit that NewsDetailView and if I go to mysite.com/news I hit NewListView.
Using this example, if you had a slug for a contact you'd go to mysite.com/contacts/contact-slug to hit that NewsDetailView.
And just a sidenote on the urlpatterns in case you're not aware, the ^ in the regex signifies the start of a pattern to match, and the $ signifies the end. URL dispatcher docs

Breaking Django views into seperate directories and files

I'm quite new to Django and I'm enjoying it a lot. I have broken my app's views into different files and placed them in a directory called app/views/(view files).
I have made an __init__.py file in the views directory this has caused me to have to use myproj.app.views.views in my site code. Which of coarse not very digestible.
Any ideas around this. Or is renaming my views directory to something else the way forward.
Thanks.
Just import the views from the other modules in __init__.py.
My user profile app account has three views files: views.py, views_login.py, and views_profile.py. Maybe it's not the cleanest, but it separates the three parts of account pretty well for my needs. My apps/account/urls.py therefore looks like this:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^foo1$', 'apps.account.views.foo1'),
(r'^foo2$', 'apps.account.views.foo2'),
(r'^bar1$', 'apps.account.views_login.bar1'),
(r'^bar2$', 'apps.account.views_login.bar2'),
(r'^baz1$', 'apps.account.views_profile.baz1'),
(r'^baz2$', 'apps.account.views_profile.baz2'),
)