Django Rest Framework: Disable format extensions - django-rest-framework

I would like to do something like this:
from rest_framework import routers
router = routers.DefaultRouter(suffix_required=False)
When I look at the definition of DefaultRouter:
class DefaultRouter(SimpleRouter):
"""
The default router extends the SimpleRouter, but also adds in a default
API root view, and adds format suffix patterns to the URLs.
"""
include_root_view = True
include_format_suffixes = True
Notice include_format_suffixes is hardcoded to True.
I must be missing something, but how to I turn off format extensions preferabley for the whole project, or at least for a certain router? I always use JSON, and do not wish to have these .json extensions in the urls created from ViewSets.
I realize I could use Simple router, but I would the " default API root view, that returns a response containing hyperlinks to all the list views" that the DefaultRouter provides.

Related

Enforcing use of format suffix patterns in DRF with ViewSets

I'm using Django Rest Framework to make a read-only API from an existing Django website. I'd like to require API URLs to include a format suffix (either .json, or .api for the browsable API) but I can't see how to do this when using ViewSets and Routers.
In my main site urls.py I have:
from django.urls import include
# ...
urlpatterns += [
path("api/v1/", include("api.urls", namespace="v1")),
]
And api/urls.py contains:
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from . import views
app_name = "api"
router = DefaultRouter(trailing_slash=False)
router.register(r"people", views.PersonViewSet)
urlpatterns = [
path("", include(router.urls)),
]
Two issues:
I can get a browsable API page by going to either /api/v1/people or /api/v1/people.api – I'd like to enforce the use of the latter.
The api-root view is visible at /api/v1/ or /api/v1/.api. That last looks ugly! But I can't see how to make it /api/v1.api, given I use a trailing slash on all URLs on the site, apart from the API.
Because I feel like I'm fighting DRF on this, I also feel I'm missing what the common best practice is.
At Andrew Backer's suggestion I tried using my own version of DefaultRouter and have, I think, solved point (1).
If I copy DefaultRouter, give it a new name, and make a single change, it enforces the use of format extensions. The only change is in the get_urls() method, where I change this:
if self.include_format_suffixes:
urls = format_suffix_patterns(urls)
To this:
if self.include_format_suffixes:
urls = format_suffix_patterns(urls, suffix_required=True, allowed=["api", "json"])
The suffix_required argument is the trick. It's a shame there's no way to pass an argument into DefaultRouter in order to toggle this on or off.
I tried subclassing DefaultRouter and only overriding the get_urls() method (rather than entirely copying and replacing the class) but that generated ImproperlyConfigured exceptions, "…is not a valid regular expression: redefinition of group name 'format' as group 2; was group 1 at position 42". I think that results in format_suffix_patterns() getting called twice, which is similar to an Issue here.

How to instruct AEM to look for a specific resource bundle translations

I have two websites and code base is same.
SiteA
SiteB
apps/company/components
How to pick different resource bundle translations for SiteA, SiteB in i18n ?
Thanks,
Sri
Can you please be specific, is this for server side translations or client side translations? For client-side translations, I had an issue with OTB ResourceBundleExportServlet detailed here.
sling:basename way:
Add a property sling:basename to mix:language node. Say sling:basename="siteA"
Pass the basename during bundle lookup. request.getResourceBundle("siteA", locale);
This will return keys from the specific basename only.
Client-side custom bundle exporter:
Keep separate dictionaries for SiteA and SiteB. For example: /apps/company/sitea/i18n, /apps/company/siteb/i18n.
If splitting dictionary is not possible, keep a nomenclature in your labels to identify site. For example all labels should be prefixed with siteA/siteA. Like siteA.clickhere, siteB.clickhere
Create custom servlet similar to ResourceBundleExportServlet. Keep the path as /libs/company/i18n/dict.
The custom servlet will check siteA or siteB from slingrequest and return respective labels only. Filtering the labels based of dictionary path(step 1) or prefix(step 2)
Create overlay to /libs/clientlibs/granite/utils/source/I18n.js. Change the urlPrefix to
var urlPrefix = "/libs/company/i18n/dict.";
Now the client side i18n lookup will pull entries from the custom exporter rather than OTB exporter
Server-side Resolver:
To differentiate sitea or siteb labels we need step 1 or 2 from above.
Once we know to identify site specific labels, we need only a helper util that checks site from request and resolves from specific dictionary or prefix
Hope this helps.

Default specific option checked in ParentalManyToManyField wagtail, using django-form

I am working with a multi-site wagtail project. And I want an event class which contains ParentalManyToManyField field called sites. The idea is that each event will be associated with multiple sites not necessarily all.
Two sites X and Y have lots of events and most of them are common. So I want to make default checkbox selected for two of the sites while resting unchecked in event content_panels.
My event class is as follows.
from django import forms
from wagtail.core.models import Orderable, Page, Site
from modelcluster.fields import ParentalKey, ParentalManyToManyField
class Event(Page):
....
sites = ParentalManyToManyField(Site)
...
Event.content_panels = [
...
FieldPanel('sites', widget=forms.CheckboxSelectMultiple),
...
]
I found following code somewhere and tried it but it makes all options checked.
Event.content_panels = [
...
FieldPanel('sites', widget=forms.CheckboxSelectMultiple(attrs={"checked":""}))
I want just two specific options to be checked and rest unchecked by default.

Django autocomplete Light in list filters for admin

I have successfully setup the Autocomplete Registry and have my django admin forms where if you go to the form, the auto completes works. I would like to be able to extend the autocompletes to work on the list_filter view as well. So when you are looking at the view generated by Admin.py -- that the list_filter inputs that are generated would also use the autocomplete jquery + service URL.
I didn't see anything listed in the documentation, anyone have any pointers?
If you are using Django version greater then 2.0, you can try using the built-in autocomplete fields for this purpose.
By default, the admin uses a select-box interface () for those fields. Sometimes you don’t want to incur the overhead of selecting all the related instances to display in the dropdown.
The Select2 input looks similar to the default input but comes with a search feature that loads the options asynchronously
There is a simple app which does this:
To install use: pip install django-admin-autocomplete-filter
Then add admin_auto_filters to your INSTALLED_APPS inside settings.py of your project.
Let's say we have following models:
class Artist(models.Model):
name = models.CharField(max_length=128)
class Album(models.Model):
name = models.CharField(max_length=64)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
cover = models.CharField(max_length=256, null=True, default=None)
And you would like to filter results in Album Admin on the basis of artist, then you can define search fields in Artist and then define filter as:
from admin_auto_filters.filters import AutocompleteFilter
class ArtistFilter(AutocompleteFilter):
title = 'Artist' # display title
field_name = 'artist' # name of the foreign key field
class ArtistAdmin(admin.ModelAdmin):
search_fields = ['name'] # this is required for django's autocomplete functionality
...
class AlbumAdmin(admin.ModelAdmin):
list_filter = [ArtistFilter]
'''
defining this class is required for AutocompleteFilter
it's a bug and I am working on it.
'''
class Media:
pass
After following these steps you may see the filter as:
You should define your own admin filter that inherits from django.contrib.admin.SimpleListFilter. Then should provide your own HTML template for this filter which will use one of django-autocomplete-light widgets. As a parameter for widget you should define required autocomplete URL. And do not forget to include proper JS and CSS for it.
All of this is done in special app for this: dal-admin-filters

How to generate web API docs from python docstrings

I have a Django website and I created a REST api. In the view functions I have documentation on the REST urls and I want to generate API docs for the REST urls. The view functions look like this:
def genres(request):
"""
Url: /api/genres/
Parameters: None
Returns: list of genres { { "id":1, "name":"action" }, {...} }
"""
pass
But when I run sphinx on myproject.api.views I get html docs for calling the api in python. Is there a way to configure sphinx to document it like a REST api?
Or am I better off writing a script to generate my docs from the docstrings myself?
Check sphinxcontrib-httpdomain
You can use autodoc in order to use the docstrings and the httpdomain extension in order to use .. http:get:: /users/ style directives. This solution has a problem, it will also show the functions' signatures. In order to get around the problem, I tinkered a bit with the Sphinx source code, making a copy of the original autodoc extension that wouldn't add the signatures to the final documentation.
The files can be found on https://gist.github.com/4589457
Instructions:
Replace application.py on sphinx path with the one on the gist (the path on my system is /Library/Frameworks/Python.framework/Versions/Current/lib/python2.7/site-packages/Sphinx-1.1.3-py2.7.egg/sphinx/)
Add simpleautodoc.py on the ext folder
Add the httpdomain extension on conf.py in order to use .. http:get:: /users/ style directives
Use simpleautodoc as you would use autodoc using the prefix autosimple instead of auto (eg autosimplemodule instead of automodule autosimpleclass instead of autoclass etc)
The example.py file shows a sample of how I format the docstrings

Resources