mirror of
				https://github.com/cookiecutter/cookiecutter-django.git
				synced 2025-11-04 01:47:28 +03:00 
			
		
		
		
	Option for DRF with extra fixes (#2410)
Option for DRF with extra fixes
This commit is contained in:
		
						commit
						2fb40f3f8c
					
				| 
						 | 
					@ -130,6 +130,7 @@ Listed in alphabetical order.
 | 
				
			||||||
  Ivan Khomutov            `@ikhomutov`_
 | 
					  Ivan Khomutov            `@ikhomutov`_
 | 
				
			||||||
  Jan Van Bruggen          `@jvanbrug`_
 | 
					  Jan Van Bruggen          `@jvanbrug`_
 | 
				
			||||||
  Jelmer Draaijer          `@foarsitter`_
 | 
					  Jelmer Draaijer          `@foarsitter`_
 | 
				
			||||||
 | 
					  Jerome Caisip            `@jeromecaisip`_
 | 
				
			||||||
  Jens Nilsson             `@phiberjenz`_
 | 
					  Jens Nilsson             `@phiberjenz`_
 | 
				
			||||||
  Jerome Leclanche         `@jleclanche`_                @Adys
 | 
					  Jerome Leclanche         `@jleclanche`_                @Adys
 | 
				
			||||||
  Jimmy Gitonga            `@afrowave`_                  @afrowave
 | 
					  Jimmy Gitonga            `@afrowave`_                  @afrowave
 | 
				
			||||||
| 
						 | 
					@ -299,6 +300,7 @@ Listed in alphabetical order.
 | 
				
			||||||
.. _@jangeador: https://github.com/jangeador
 | 
					.. _@jangeador: https://github.com/jangeador
 | 
				
			||||||
.. _@jazztpt: https://github.com/jazztpt
 | 
					.. _@jazztpt: https://github.com/jazztpt
 | 
				
			||||||
.. _@jcass77: https://github.com/jcass77
 | 
					.. _@jcass77: https://github.com/jcass77
 | 
				
			||||||
 | 
					.. _@jeromecaisip: https://github.com/jeromecaisip
 | 
				
			||||||
.. _@jleclanche: https://github.com/jleclanche
 | 
					.. _@jleclanche: https://github.com/jleclanche
 | 
				
			||||||
.. _@juliocc: https://github.com/juliocc
 | 
					.. _@juliocc: https://github.com/juliocc
 | 
				
			||||||
.. _@jvanbrug: https://github.com/jvanbrug
 | 
					.. _@jvanbrug: https://github.com/jvanbrug
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@
 | 
				
			||||||
    "GCP",
 | 
					    "GCP",
 | 
				
			||||||
    "None"
 | 
					    "None"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
 | 
					  "use_drf": "n",
 | 
				
			||||||
  "custom_bootstrap_compilation": "n",
 | 
					  "custom_bootstrap_compilation": "n",
 | 
				
			||||||
  "use_compressor": "n",
 | 
					  "use_compressor": "n",
 | 
				
			||||||
  "use_celery": "n",
 | 
					  "use_celery": "n",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -287,6 +287,11 @@ def remove_aws_dockerfile():
 | 
				
			||||||
    shutil.rmtree(os.path.join("compose", "production", "aws"))
 | 
					    shutil.rmtree(os.path.join("compose", "production", "aws"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove_drf_starter_files():
 | 
				
			||||||
 | 
					    os.remove(os.path.join("config", "api_router.py"))
 | 
				
			||||||
 | 
					    shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "users", "api"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
    debug = "{{ cookiecutter.debug }}".lower() == "y"
 | 
					    debug = "{{ cookiecutter.debug }}".lower() == "y"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -359,6 +364,9 @@ def main():
 | 
				
			||||||
    if "{{ cookiecutter.ci_tool }}".lower() != "gitlab":
 | 
					    if "{{ cookiecutter.ci_tool }}".lower() != "gitlab":
 | 
				
			||||||
        remove_dotgitlabciyml_file()
 | 
					        remove_dotgitlabciyml_file()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if "{{ cookiecutter.use_drf }}".lower() == "n":
 | 
				
			||||||
 | 
					        remove_drf_starter_files()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
 | 
					    print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ def context():
 | 
				
			||||||
@pytest.mark.parametrize("use_mailhog", ["y", "n"], ids=lambda yn: f"mailhog:{yn}")
 | 
					@pytest.mark.parametrize("use_mailhog", ["y", "n"], ids=lambda yn: f"mailhog:{yn}")
 | 
				
			||||||
@pytest.mark.parametrize("use_sentry", ["y", "n"], ids=lambda yn: f"sentry:{yn}")
 | 
					@pytest.mark.parametrize("use_sentry", ["y", "n"], ids=lambda yn: f"sentry:{yn}")
 | 
				
			||||||
@pytest.mark.parametrize("use_compressor", ["y", "n"], ids=lambda yn: f"cmpr:{yn}")
 | 
					@pytest.mark.parametrize("use_compressor", ["y", "n"], ids=lambda yn: f"cmpr:{yn}")
 | 
				
			||||||
 | 
					@pytest.mark.parametrize("use_drf", ["y", "n"], ids=lambda yn: f"drf:{yn}")
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "use_whitenoise,cloud_provider",
 | 
					    "use_whitenoise,cloud_provider",
 | 
				
			||||||
    [
 | 
					    [
 | 
				
			||||||
| 
						 | 
					@ -53,6 +54,7 @@ def context_combination(
 | 
				
			||||||
    use_sentry,
 | 
					    use_sentry,
 | 
				
			||||||
    use_compressor,
 | 
					    use_compressor,
 | 
				
			||||||
    use_whitenoise,
 | 
					    use_whitenoise,
 | 
				
			||||||
 | 
					    use_drf,
 | 
				
			||||||
    cloud_provider,
 | 
					    cloud_provider,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    """Fixture that parametrize the function where it's used."""
 | 
					    """Fixture that parametrize the function where it's used."""
 | 
				
			||||||
| 
						 | 
					@ -64,6 +66,7 @@ def context_combination(
 | 
				
			||||||
        "use_mailhog": use_mailhog,
 | 
					        "use_mailhog": use_mailhog,
 | 
				
			||||||
        "use_sentry": use_sentry,
 | 
					        "use_sentry": use_sentry,
 | 
				
			||||||
        "use_whitenoise": use_whitenoise,
 | 
					        "use_whitenoise": use_whitenoise,
 | 
				
			||||||
 | 
					        "use_drf": use_drf,
 | 
				
			||||||
        "cloud_provider": cloud_provider,
 | 
					        "cloud_provider": cloud_provider,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								{{cookiecutter.project_slug}}/config/api_router.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								{{cookiecutter.project_slug}}/config/api_router.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					from rest_framework.routers import DefaultRouter, SimpleRouter
 | 
				
			||||||
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					from {{ cookiecutter.project_slug }}.users.api.views import UserViewSet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if settings.DEBUG:
 | 
				
			||||||
 | 
					    router = DefaultRouter()
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    router = SimpleRouter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router.register("users", UserViewSet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_name = "api"
 | 
				
			||||||
 | 
					urlpatterns = router.urls
 | 
				
			||||||
| 
						 | 
					@ -301,14 +301,24 @@ ACCOUNT_EMAIL_VERIFICATION = "mandatory"
 | 
				
			||||||
ACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.AccountAdapter"
 | 
					ACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.AccountAdapter"
 | 
				
			||||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
 | 
					# https://django-allauth.readthedocs.io/en/latest/configuration.html
 | 
				
			||||||
SOCIALACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter"
 | 
					SOCIALACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter"
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% if cookiecutter.use_compressor == 'y' -%}
 | 
					{% if cookiecutter.use_compressor == 'y' -%}
 | 
				
			||||||
# django-compressor
 | 
					# django-compressor
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation
 | 
					# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation
 | 
				
			||||||
INSTALLED_APPS += ["compressor"]
 | 
					INSTALLED_APPS += ["compressor"]
 | 
				
			||||||
STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"]
 | 
					STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"]
 | 
				
			||||||
 | 
					{%- endif %}
 | 
				
			||||||
 | 
					{% if cookiecutter.use_drf == "y" -%}
 | 
				
			||||||
 | 
					# django-reset-framework
 | 
				
			||||||
 | 
					# -------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/
 | 
				
			||||||
 | 
					REST_FRAMEWORK = {
 | 
				
			||||||
 | 
					    "DEFAULT_AUTHENTICATION_CLASSES": (
 | 
				
			||||||
 | 
					        "rest_framework.authentication.SessionAuthentication",
 | 
				
			||||||
 | 
					        "rest_framework.authentication.TokenAuthentication",
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
{%- endif %}
 | 
					{%- endif %}
 | 
				
			||||||
# Your stuff...
 | 
					# Your stuff...
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,9 @@ from django.conf.urls.static import static
 | 
				
			||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
from django.views.generic import TemplateView
 | 
					from django.views.generic import TemplateView
 | 
				
			||||||
from django.views import defaults as default_views
 | 
					from django.views import defaults as default_views
 | 
				
			||||||
 | 
					{% if cookiecutter.use_drf == 'y' -%}
 | 
				
			||||||
 | 
					from rest_framework.authtoken.views import obtain_auth_token
 | 
				
			||||||
 | 
					{%- endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = [
 | 
					urlpatterns = [
 | 
				
			||||||
    path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
 | 
					    path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
 | 
				
			||||||
| 
						 | 
					@ -17,6 +20,15 @@ urlpatterns = [
 | 
				
			||||||
    path("accounts/", include("allauth.urls")),
 | 
					    path("accounts/", include("allauth.urls")),
 | 
				
			||||||
    # Your stuff: custom urls includes go here
 | 
					    # Your stuff: custom urls includes go here
 | 
				
			||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 | 
					] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 | 
				
			||||||
 | 
					{% if cookiecutter.use_drf == 'y' -%}
 | 
				
			||||||
 | 
					# API URLS
 | 
				
			||||||
 | 
					urlpatterns += [
 | 
				
			||||||
 | 
					    # API base url
 | 
				
			||||||
 | 
					    path("api/", include("config.api_router")),
 | 
				
			||||||
 | 
					    # DRF auth token
 | 
				
			||||||
 | 
					    path("auth-token/", obtain_auth_token),
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					{%- endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if settings.DEBUG:
 | 
					if settings.DEBUG:
 | 
				
			||||||
    # This allows the error pages to be debugged during development, just visit
 | 
					    # This allows the error pages to be debugged during development, just visit
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					from rest_framework import serializers
 | 
				
			||||||
 | 
					from {{ cookiecutter.project_slug }}.users.models import User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserSerializer(serializers.ModelSerializer):
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = User
 | 
				
			||||||
 | 
					        fields = ["username", "email", "name", "url"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        extra_kwargs = {
 | 
				
			||||||
 | 
					            "url": {"view_name": "api:user-detail", "lookup_field": "username"}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					from django.contrib.auth import get_user_model
 | 
				
			||||||
 | 
					from rest_framework import status
 | 
				
			||||||
 | 
					from rest_framework.decorators import action
 | 
				
			||||||
 | 
					from rest_framework.mixins import RetrieveModelMixin, ListModelMixin, UpdateModelMixin
 | 
				
			||||||
 | 
					from rest_framework.response import Response
 | 
				
			||||||
 | 
					from rest_framework.viewsets import GenericViewSet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .serializers import UserSerializer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					User = get_user_model()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserViewSet(RetrieveModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
 | 
				
			||||||
 | 
					    serializer_class = UserSerializer
 | 
				
			||||||
 | 
					    queryset = User.objects.all()
 | 
				
			||||||
 | 
					    lookup_field = "username"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_queryset(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        return self.queryset.filter(id=self.request.user.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @action(detail=False, methods=["GET"])
 | 
				
			||||||
 | 
					    def me(self, request):
 | 
				
			||||||
 | 
					        serializer = UserSerializer(request.user, context={"request": request})
 | 
				
			||||||
 | 
					        return Response(status=status.HTTP_200_OK, data=serializer.data)
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user