I am aware that "Django 2 with router url patterns has changed". I cant manage to work with Router because I am getting an error :
'Specifying a namespace in include() without providing an app_name '
django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.
I have written a basic model and after that I have created an api folder, I have prepared files "views.py":
from rest_framework import generics
from yogavidya.apps.articles.models import Article
from .serializers import ArticleSerializer
from rest_framework import routers, serializers, viewsets
class ArticleUpdateView(generics.RetrieveUpdateAPIView):
lookup_field = 'pk'
serializer_class = ArticleSerializer
queryset = Article.objects.all()
router = routers.DefaultRouter()
router.register(r'api/articles', ArticleUpdateView, base_name='api-articles')
after I have urls.py :
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
from .views import ArticleUpdateView
from django.urls import re_path
urlpatterns = [
re_path(r'articles/(?:page-(?P<page_number>\d+)/)?$', ArticleUpdateView.as_view(), name='article-update'),
]
now I want to add the api to project urls.py
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.conf import settings
from django.conf.urls.static import static
from yogavidya.apps.articles import views
from .views import home,home_files, pricing
from rest_framework import routers, serializers, viewsets
urlpatterns += i18n_patterns(
path('admin/', admin.site.urls),
path('articles/', include('yogavidya.apps.articles.urls', namespace="articles")),
)
urlpatterns += [
path('api/articles/', include('yogavidya.apps.articles.api.urls', namespace="api-articles")),
]
How can I set app_name = 'api-articles' as a global variable and manage to import app_name in my urls.py?
Related
views.py
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from django.contrib.auth.models import User
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from App.serializers import *
from App.models import *
from App.serializers import *
# Create your views here.
class ListUsers(APIView):
"""
View to list all users in the system.
* Requires token authentication.
* Only admin users are able to access this view.
"""
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [permissions.IsAdminUser]
def get(self, request, format=None):
"""
Return a list of all users.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
class CustomAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'email': user.email
})
#api_view(['GET'])
def consol_overall_view(request):
user = Users.objects.values('id','employee_name','billable_and_non_billable',)
qs = conso_serializers(user, many= True)
proj = Add_Job.objects.values('project','user','client')
qs1 = timelog_serializers(proj, many= True)
cli = Add_Timelog.objects.values('Date','Hours','project_id')
qs2 = time_serializers(cli,many= True)
return Response(qs.data+qs1.data+qs2.data,status = status.HTTP_200_OK)
urls.py
from django.contrib import admin
from django.urls import path,include
from django.urls import re_path
from django import views
from App.views import CustomAuthToken
from.router import router
from rest_framework.authtoken import views
from django.views.generic import TemplateView
from App.views import consol_overall_view
urlpatterns = [
path('', TemplateView.as_view(template_name="social_app/index.html")),
path('admin/', admin.site.urls),
path('api/',include(router.urls)),
path('accounts/', include('allauth.urls')),
re_path('rest-auth/', include('rest_auth.urls')),
path('api-auth/', include('rest_framework.urls')),
re_path('rest-auth/registration/', include('rest_auth.registration.urls')),
path('api-token-auth/', views.obtain_auth_token),
path('api-token-auth/', CustomAuthToken.as_view()),
path('over',views.consol_overall_view),
]
while I tried to migrate and runserver it is showing an error
path('over',views.consol_overall_view),
AttributeError: module 'rest_framework.authtoken.views' has no attribute 'consol_overall_view'
I need the consol_overall_view in Url or as a API. If it is possible to do as API kindly guide on the same.
When python interpreter finds imports with same name it takes the latest one into account. In your urls.py you have imported views module from two distinct packages. Python interpreter will treat the name views from the package restframework.authtoken as the views module not the one from django because the import from the first one is the latest. Apart from that, you have imported consol_overall_view directly from App.views but referring it as a value from views that you have imported before. Change views.consol_overall_view to consol_overall_view in your urlpatterns. Also, use aliases in your imports.
from django.contrib import admin
from django.urls import path,include
from django.urls import re_path
# import django.views with alias
from django import views as django_views
from App.views import CustomAuthToken
from.router import router
from rest_framework.authtoken import views
from django.views.generic import TemplateView
from App.views import consol_overall_view
urlpatterns = [
path('', TemplateView.as_view(template_name="social_app/index.html")),
path('admin/', admin.site.urls),
path('api/',include(router.urls)),
path('accounts/', include('allauth.urls')),
re_path('rest-auth/', include('rest_auth.urls')),
path('api-auth/', include('rest_framework.urls')),
re_path('rest-auth/registration/', include('rest_auth.registration.urls')),
path('api-token-auth/', views.obtain_auth_token),
path('api-token-auth/', CustomAuthToken.as_view()),
path('over', consol_overall_view),
]
in my main project's urls.py :
from django.contrib import admin
from django.urls import path
from .settings.base import APP_NAME
from django.conf.urls import url,include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
urlpatterns = [
url(r'^api/user/', include('user.urls', namespace="user")),
]
in user app's urls.py :
from django.conf import settings
from django.urls import path
from . import views
app_name="user"
urlpatterns = [
path('password_reset/', views.ResetPasswordRequestToken.as_view(), name="reset_password_request")
]
Route is working on local very well. But on the production, route page is opening and I post email via api page, and then I get error below:
How can I solve it ?
namespace should replaced by name. That can solve your problem.
from django.contrib import admin
from django.urls import path
from .settings.base import APP_NAME
from django.conf.urls import url,include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
urlpatterns = [
path('api/user/', include('user.urls', name="user")),
]
I have some error with Rest API when started Django project.
The error is
"raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
django.core.exceptions.ImproperlyConfigured: The included URLconf '<module 'api.urls' from '/Users/luba/code/library/library_project/api/urls.py'>' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import."
My code:
api/views.py
from rest_framework import generics
from books.models import Book
from .serializers import BookSerializer
class BookAPIView(generics.ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
api/urls.py
from django.urls import path
from .views import BookAPIView
urlpattens = [
path('', BookAPIView.as_view()),
]
api/serializers.py
from rest_framework import serializers
from books.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('title', 'subtitle', 'author', 'isbn')
books/views.py
from django.urls import path
from .views import BookListView
urlpatterns = [
path('', BookListView.as_view(), name='home'),
]
books/views.py
from django.views.generic import ListView
from .models import Book
class BookListView(ListView):
model = Book
template_name = 'book_list.html'
Somebody can explain, in which staff problem with my code.Will be appreciate!!!!
It seems like you didn't include your api urls to main urls.py
You can find it at same folder where your settings.py is located.
from django.urls import path, include
from api import urls
urlpatterns = [
path('api/', include(urls.urlpatterns)),
]
Django-Oscar has apparently been updated to Django 2.0. I am new to Django, I am not sure how I would update the URLs that are mentioned in the Oscar Tutorial:
from django.conf.urls import include, url
from django.contrib import admin
from oscar.app import application
urlpatterns = [
url(r'^i18n/', include('django.conf.urls.i18n')),
# The Django admin is not officially supported; expect breakage.
# Nonetheless, it's often useful for debugging.
url(r'^admin/', include(admin.site.urls)),
url(r'', include(application.urls)),
]
This is the url that is currently available:
urlpatterns = [
path('admin/', admin.site.urls),
]
So, do this mean that I would change the django-oscar URls to?:
path(r'^i18n/', include('django.conf.urls.i18n')),
The documentation on readthedocs is out of date for some reason - here's the most recent version on Github which provides configuration for Django 2.
To use path you need to remove the regular expression syntax in the URLs. The use of include() also has been dropped for url configs passed directly, so you end up with:
from django.urls import include, path
from django.contrib import admin
from oscar.app import application
urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
path('admin/', admin.site.urls),
path('', application.urls),
]
Django oscar always put their URLs in their app directory's apps.py file and then include that URL's to project level urls.py file, that's the design decision for Django oscar. But I would recommend you use path() than url() as this will help you to avoid the complexity.
##django-oscar/src/oscar/apps/basket/apps.py
from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext_lazy as _
from oscar.core.application import OscarConfig
from oscar.core.loading import get_class
class BasketConfig(OscarConfig):
label = 'basket'
name = 'oscar.apps.basket'
verbose_name = _('Basket')
namespace = 'basket'
def ready(self):
self.summary_view = get_class('basket.views', 'BasketView')
self.saved_view = get_class('basket.views', 'SavedView')
self.add_view = get_class('basket.views', 'BasketAddView')
self.add_voucher_view = get_class('basket.views', 'VoucherAddView')
self.remove_voucher_view = get_class('basket.views', 'VoucherRemoveView')
def get_urls(self):
urls = [
url(r'^$', self.summary_view.as_view(), name='summary'),
url(r'^add/(?P<pk>\d+)/$', self.add_view.as_view(), name='add'),
url(r'^vouchers/add/$', self.add_voucher_view.as_view(),
name='vouchers-add'),
url(r'^vouchers/(?P<pk>\d+)/remove/$',
self.remove_voucher_view.as_view(), name='vouchers-remove'),
url(r'^saved/$', login_required(self.saved_view.as_view()),
name='saved'),
]
return self.post_process_urls(urls)
then imported by project level config.py file
##django-oscar/src/oscar/config.py
# flake8: noqa, because URL syntax is more readable with long lines
from django.apps import apps
from django.conf import settings
from django.conf.urls import url
from django.urls import reverse_lazy
from django.views.generic.base import RedirectView
from oscar.core.application import OscarConfig
from oscar.core.loading import get_class
class Shop(OscarConfig):
name = 'oscar'
def ready(self):
from django.contrib.auth.forms import SetPasswordForm
self.catalogue_app = apps.get_app_config('catalogue')
self.customer_app = apps.get_app_config('customer')
self.basket_app = apps.get_app_config('basket')
self.checkout_app = apps.get_app_config('checkout')
self.search_app = apps.get_app_config('search')
self.dashboard_app = apps.get_app_config('dashboard')
self.offer_app = apps.get_app_config('offer')
self.password_reset_form = get_class('customer.forms', 'PasswordResetForm')
self.set_password_form = SetPasswordForm
def get_urls(self):
from django.contrib.auth import views as auth_views
from oscar.views.decorators import login_forbidden
urls = [
url(r'^$', RedirectView.as_view(url=reverse_lazy('catalogue:index')), name='home'),
url(r'^catalogue/', self.catalogue_app.urls),
url(r'^basket/', self.basket_app.urls),
url(r'^checkout/', self.checkout_app.urls),
url(r'^accounts/', self.customer_app.urls),
url(r'^search/', self.search_app.urls),
url(r'^dashboard/', self.dashboard_app.urls),
url(r'^offers/', self.offer_app.urls),
# Password reset - as we're using Django's default view functions,
# we can't namespace these urls as that prevents
# the reverse function from working.
url(r'^password-reset/$',
login_forbidden(
auth_views.PasswordResetView.as_view(
form_class=self.password_reset_form,
success_url=reverse_lazy('password-reset-done'),
template_name='oscar/registration/password_reset_form.html'
)
),
name='password-reset'),
url(r'^password-reset/done/$',
login_forbidden(auth_views.PasswordResetDoneView.as_view(
template_name='oscar/registration/password_reset_done.html'
)),
name='password-reset-done'),
url(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
login_forbidden(
auth_views.PasswordResetConfirmView.as_view(
form_class=self.set_password_form,
success_url=reverse_lazy('password-reset-complete'),
template_name='oscar/registration/password_reset_confirm.html'
)
),
name='password-reset-confirm'),
url(r'^password-reset/complete/$',
login_forbidden(auth_views.PasswordResetCompleteView.as_view(
template_name='oscar/registration/password_reset_complete.html'
)),
name='password-reset-complete'),
]
return urls
Oscar's idea is to modularize every app. That's why it stores app's all url to apps.py in every app folder and include that to project level config.py file.
I use django 2.0.7 in my project with django-decorator-include app (version 2.0).
My urls.py:
from django.conf import settings
from django.contrib import admin
from django.urls import path, re_path, include
from django.conf.urls.static import static
from django.conf.urls.i18n import i18n_patterns
from django.contrib.auth.decorators import login_required
from decorator_include import decorator_include
urlpatterns = i18n_patterns(
path('', include('web.urls', namespace='web')),
path('backoffice/', decorator_include([login_required,], 'backoffice.urls', namespace='backoffice')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
My backoffice.urls:
from django.urls import path, re_path
from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import gettext_lazy as _
from backoffice import views
app_name = 'backoffice'
urlpatterns = (
path('', views.DashboardView.as_view(), name='dashboard'),
)
backoffice is added to INSTALLED_APPS.
In my views (in app web for example) I am able to do reverse URL, for example in my login view I do return redirect('backoffice:dashboard') and it works just perfectly - its redirecting to /backoffice/.
Problem is when I try to do reverse urls in my templates. In one of my templates, when I add code:
<li class="featured">{% trans 'Open dashboard' %}</li>
I get django error:
NoReverseMatch at /
'backoffice' is not a registered namespace
I suppose that problem is related to django-decorator-include, because if I change my include to standard django url include:
path('backoffice/', include('backoffice.urls', namespace='backoffice')),
it works just fine, and I am able to get reverse urls in templates again.
What should I do? Maybe its a bug in django-decorator-include? Any ideas how can I solve that?