In my Django project, specifically in my accounts app, I have 2 simple views, one allows users to view their profile (or other users' profiles), and the other one allows users to edit their own profile.
My account.urls looks like this
from django.urls import path
from accounts.views import ProfileView, EditProfileView
app_name = 'accounts'
urlpatterns = [
path('<slug:username>/', ProfileView.as_view(), name='profile'),
path('edit/', EditProfileView.as_view(), name='edit'),
]
Everything works great, but if an user creates an accounts with the word edit as their username, they will NEVER be able to edit their profile, since the first URL pattern will always be matched.
What's the best way of solving this problem in Django?
I know I could change my URLs to something like:
urlpatterns = [
path('<slug:username>/', ProfileView.as_view(), name='profile'),
path('<slug:username>/edit/', EditProfileView.as_view(), name='edit'),
]
But I prefer to NOT edit my URLs. I was wondering if there is another solution I don't know.
Related
```
I am creating CRUD for categories I make a CategoriesViewSet.
on the other hand, I register the router as default in urls.py(Products) for viewset of categories but I don't know how to add a path into the product => urls.py and also the path I want to include into the core url.py file.
product => urls.py
router =routers.DefaultRouter()
router.register(r'categories', CategoryViewSet)
urlpatterns = [
path('list/',ProductList.as_view(),name="View Product"),
path('add/',AddProduct.as_view(),name="Create Product"),
path('<int:pk>/',ProductDetails.as_view(),name="product_detail"),
# path('categories/', CategoryViewSet.as_view({'get':'list'}))
path(r'^', include(router.urls)),
re_path(r'categories/', CategoryViewSet.as_view({'get':'list'}),
name='product-detail')
]
Core => urls.py
path('admin/', admin.site.urls),
path('api/product/', include('products.urls')),
path('api/user/', include('user.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns = format_suffix_patterns(urlpatterns)
I don't think you have a clear idea of what Routers do in Django.
From DRF's official documentation:
Some Web frameworks such as Rails provide functionality for
automatically determining how the URLs for an application should be
mapped to the logic that deals with handling incoming requests.
REST framework adds support for automatic URL routing to Django, and
provides you with a simple, quick and consistent way of wiring your
view logic to a set of URLs.
This line:
router.register(r'categories', CategoryViewSet)
according to Django REST Framework's (DRF) documentation, generates 2 URL patterns:
categories/ - Return the list of categories
categories/{pk}/ - Return category with specified primary key (pk)
You don't need to add those again in Product's urls.py. You can either only specify the router.register(...) method, or manually add them like that:
path('categories/', CategoryViewSet.as_view(), name='product-detail')
It works. In my view I implemented and it works that's why I am asking First of all we have to add the
import [re_path and include] in the Urls.py (Products)
then we have to add--------------------
~the code will be added in the urls.py(Products) below the import library.
router = routers.SimpleRouter()
router.register(r'', CategoryViewSet, 'categories')
in Url Patterns~
re_path(r'^categories/',include((router.urls,'categories'),namespace='categories'))
it works.
What is the simplest way to add a view to my Django (3.2) admin UI? That is, add a URL mysite.com/admin/my-view so that visiting that URL acts like the rest of admin (in particular, requires similar permissions).
There is a whole page on this, but it's not obvious to me how to piece it together.
https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#adding-views-to-admin-sites says you can add a get_urls to your AdminSite class. Okay, so I need my own AdminSite class. And I need to register it in apps, maybe?
I did this:
class MyAdminSite(admin.AdminSite):
def get_urls(self):
urls = super().get_urls()
my_urls = [
path('my-view', self.my_view, name='my-view')
]
return my_urls + urls
def my_view(self, request):
# do something ..
admin_site = MyAdminSite(name='my_admin')
and this in urls.py:
from .admin import admin_site
urlpatterns = [
path('admin/', admin_site.urls),
and this in unchanged in INSTALLED_APPS in settings:
'django.contrib.admin',
But, now it only shows the admin for the one app, instead of for all the apps. So how do I get it to auto-discover all the apps like it used to? Or is there a simpler way?
P.S. There is also a question on this, but the answer didn't have enough detail for me to use it.
EDIT: I'm reading Make new custom view at django admin and Django (1.10) override AdminSite ..
EDIT 2: This was a hack, but it works for me:
from django.contrib.admin import site
admin_site._registry.update(site._registry)
I had to update in the right place (the project urls.py), perhaps when all the other admin stuff is already loaded.
Was hoping someone could point me in the right direction with this. I've tried nearly everything I can think of, but I can't seem to get it to work. I've got a set of URLs I'd like to match in Django:
www.something.com/django/tabs/
www.something.com/django/tabs/?id=1
Basically, I want to make it so that when you just visit www.something.com/django/tabs/ it takes you to a splash page where you can browse through stuff. When you visit the second URL however, it takes you to a specific page which you can browse to from the first URL. This page is rendered based on an object in the database, which is why the id number is there. I've tried to account for this in the URL regex, but nothing I try seems to work. They all just take me to the main page.
This is what I have in urls.py within the main site folder:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', include("tabs.urls")),
]
and within urls.py in the app's folder:
urlpatterns = [
url(r'\?id=\d+$', tab),
url(r'^$', alltabs)
]
Would anyone be so kind as to point me in the right direction? Thanks in advance!
You are not following the right approach here. Query paramers are used to change the behaviour of the page slightly. Like a added filter, search query etc.
What i would suggest is you have only one view and render different templates based on query parameters in the view.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', alltabs),
]
In your alltab views you can have something like this.
def alltabs(request):
if request.GET.get("id"):
id = request.GET.get("id")
your_object = MyModel.objects.get(id=id)
return render_to_response("tab.html", {"object":your_object})
return render_to_response("alltab.html")
Hope this helps
This is not the preferred 'django way' of defining urls patterns, I would say:-)
In the spirit of django would be something like
www.something.com/django/tabs/
www.something.com/django/tabs/1/
....
www.something.com/django/tabs/4/
and for this you define your url patterns within the app for example this way
tabs/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /tabs/
url(r'^$', views.index, name='index'),
# ex: /tabs/5/
url(r'^(?P<tab_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /tabs/5/results/
url(r'^(?P<tab_id>[0-9]+)/results/$', views.results, name='results'),
]
and something similar in your views
tabs/views.py:
from django.shortcuts import get_object_or_404, render
from tabs.models import Tab
def index(request):
return render(request, 'tabs/index.html')
def detail(request, tab_id):
tab = get_object_or_404(Tab, pk=tab_id)
return render(request, 'tabs/detail.html', {'tab': tab})
...
You can follow this django tutorial for more details:
My code is as follows:
root urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('app.urls')),
]
My applications url is like so
urlpatterns = [
url(r'^$',views.login, name='login'),
url(r'^homepage/$', views.homepage, name='homepage'),
]
The first screen the user will see is the login screen (views.login). At the moment I just want to set the login button to be a url that takes them to the homepage (just for practice) but it doesnt seem to work.
The login html is like so
<button type="button">Log-In</button>
This should go to my urls page above...find the name 'homepage' and take me to views.homepage which is as so:
def homepage(request):
return render(request, 'application/homepage.html', {})
but my homepage doesnt get rendered and I have absolutely no idea why its driving me crazy.
Any help would be appreciated.
This is nothing to do with Django, but a pure HTML problem. You can't put a link inside a button. A button needs to be part of a form, and submits to the action value of that form. Either do that, and take the a tag out; or, remove the button, and just use the a.
my site.py:
from django.contrib.admin import AdminSite
class OptiAdminSite(AdminSite):
def get_urls(self):
from django.conf.urls import patterns, url, include
from core import views
from django.contrib.contenttypes import views as contenttype_views
urlpatterns = patterns('',
#url(r'^$', wrap(self.index), name='index'),
url(r'^login/$', views.login, name='login'),
url(r'^logout/$', views.logout, name='logout'),
)
return urlpatterns
opti_site = OptiAdminSite()
I'm developing an authentication API. When user logs in to my API it generates a code which get destroyed once user hit logout.
My problem is that whenever I'm running my API and django admin site in same browser, then if I login into admin-site It automatically login me in my API too with out any token. When I try to logout in that case from my API it generates an error - 'Token does not exist'. I want to generate token when admin user login to admin-site.
I've tried to do it with above trick as in official documentation but didn't find the right way to do it.
Please suggest me the correct way to do it. Is it necessary to make a separate app for it?
Thanks! in advance.
This solution is almost complete... Almost, because you're simply creating your own admin site in opti_site variable, but probably not using it anywhere.
To make it work, you can monkey-patch default admin site with your site, using:
from django.contrib import admin
admin.sites.site = opti_site
admin.site = admin.sites.site
Remember that you must do it before root urlpatterns definition (especially before defining urls to your admin site).
Another approach is to change default admin to your admin in include of url patterns:
url(r'^admin/', include(opti_site.urls)),