Thousand separator not applied in Django admin - python

I registered my model in the Django Admin, but the Integer fields (they are read-only) show up without thousand separators; this happens in the admins list view and also in the admins model form.
I am using Django 1.11.9, with Python 3.6.
In my 'settings.py' I have the following:
USE_I18N = False
USE_L10N = False
DECIMAL_SEPARATOR = ','
THOUSAND_SEPARATOR = '.'
USE_THOUSAND_SEPARATOR = True
NUMBER_GROUPING = 3
Is there a way for the django-admin to apply thousand separators to my read-only fields?
-- EDIT --
This similar question (from sep 2015) does not have a simple answer that applies to all fields automaticly.

I did NOT get it working properly in the django-admin. Since I do not use the admin for user-facing sites, I'll let the numbers be formatted with commas instead of dots for now.
However, in other templates I resorted to using a custom template tag, based on the django documentation.
from django import template
from django.utils.encoding import force_text
register = template.Library()
#register.filter
def intdot(val_orig):
"""
Similar to 'django.contrib.humanize.intcomma', but with dots.
"""
val_text = force_text(val_orig)
try:
val_new = int(val_text)
except ValueError:
return ''
val_new = '{:,d}'.format(val_new)
val_new = val_new.replace(',', '.')
return val_new

Related

Django Admin Custom View URL not being recognized

I am using Django 1.8 on Python 3.4.3
I have a Model called FormUpload and I am adding a ModelAdmin for the same in admins.py in the same application "mca".
#admin.register(FormUpload)
class FormUploadAdmin(admin.ModelAdmin):
def upload_form(self, request):
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else we want in the context...
)
return TemplateResponse(request, "admin/formupload.html", context)
def get_urls(self):
urls = super(FormUploadAdmin, self).get_urls()
upload_admin_urls = [
url(r'^upload/$', self.admin_site.admin_view(self.upload_form)),
]
logger.debug(upload_admin_urls)
return upload_admin_urls + urls
This should have been available at /admin/mca/upload/ . However when I go the URL I get a 404 saying the current URL doesn't match anything
Here is the output of the debug
RegexURLPattern None ^upload/$
(Removed few things that will make the display weird for the debug).
Please notice the None. If the other URLs are listed out there is a method name where the None is.
What am I doing wrong here ? I am following the approach suggested in django documentation - https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#modeladmin-methods

Django-rest-framework: set default renderer not working?

I'm trying to build a Django-rest-framework REST API that outputs JSON by default, but has XML available too.
I have read the Renderers chapter of the documentation section on default ordering, and have put this in my settings file:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework_xml.renderers.XMLRenderer',
)
}
However, this outputs XML by default. Switching the order makes no difference.
I do get JSON if I append format=json to the URL, and if I remove the XMLRenderer line altogether.
How can I set JSON to be the default?
I'm using v1.7 of Django and v3.1.1 of Django-rest-framework.
UPDATE: As requested here is the code for my views:
class CountyViewSet(viewsets.ModelViewSet):
queryset = County.objects.all()
serializer_class = CountySerializer
And the serializer:
from rest_framework import serializers
class CountySerializer(serializers.ModelSerializer):
class Meta:
model = County
fields = ('id', 'name', 'name_slug', 'ordering')
And then finally from my urls file:
router = routers.DefaultRouter()
router.register(r'county', CountyViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
]
my solution: file renderers.py
from rest_framework.negotiation import DefaultContentNegotiation
class IgnoreClientContentNegotiation(DefaultContentNegotiation):
logger = logging.getLogger(__name__)
def select_renderer(self, request, renderers, format_suffix):
"""
Select the first renderer in the `.renderer_classes` list.
"""
# Allow URL style format override. eg. "?format=json
format_query_param = self.settings.URL_FORMAT_OVERRIDE
format = format_suffix or request.query_params.get(format_query_param)
request.query_params.get(format_query_param), format))
if format is None:
return (renderers[0], renderers[0].media_type)
else:
return DefaultContentNegotiation.select_renderer(self, request, renderers, format_suffix)
Now just need add to settings.py in
REST_FRAMEWORK = {
(...)
'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.renderers.IgnoreClientContentNegotiation',
}
Can you post your code for the actual views?
Have you defined renderer_classes in your views? as this would override the default settings.
class YourView(APIView):
renderer_classes = (XMLRenderer, JSONRenderer, )
Most likely the issue you are hitting, especially if you are testing with a browser, is that XML comes before JSON in the Accepts header. Because of this, Django REST framework is rendering XML because you specifically requested it, even though its not what you are expecting.
By giving DRF a list of default renderers, you are telling it "use these if I don't tell you to use other ones in my view". DRF will then compare the media types of these to the ones in your Accepts header to determine the best renderer to use in the response. The order doesn't matter unless you don't include a specific media type in your Accepts header, at which point it should default to the first one in the list.
Sérgio's answer is correct.
Just to add some more details for anyone in the future that comes across this.
Add djangorestframework-xml to pipfile
Update
RENDERER_CLASSES = (
'rest_framework.renderers.JSONRenderer',
'rest_framework_xml.renderers.XMLRenderer',
)
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': RENDERER_CLASSES,
}
add rest_framework_xml to INSTALLED_APPS
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework_xml',
]
Follow Sérgio's advice about creating 'renderers.py'

Django Admin without Authentication

Is there a ready way to use the Django admin page without any form of authentication? I know I can use this method, but that was for Django 1.3. Are there any changes that would let me do this more easily in Django 1.6?
My main motivation for this is that I want to have as few database tables as possible, and I am using this only locally, so there is no need for any sort of authentication (I'm only ever running the server on localhost anyways).
The accepted answer is already super simple however after messing around with this I found that in recent versions of Django (since admin.site.has_permission became a thing... >= 1.8?) you can do it without middleware.
In your project's urls.py:
from django.contrib import admin
class AccessUser:
has_module_perms = has_perm = __getattr__ = lambda s,*a,**kw: True
admin.site.has_permission = lambda r: setattr(r, 'user', AccessUser()) or True
# Register the admin views or call admin.autodiscover()
urlpatterns = [
# Your url configs then...
url(r'^admin/', admin.site.urls),
]
If you have AccessUser extend User you can leave out the __getattr__ portion which is a hacky way to return something when user.pk or similar is called.
Create a module auto_auth.py:
from django.contrib.auth.models import User
from django.utils.deprecation import MiddlewareMixin
class AutoAuthMiddleware(MiddlewareMixin):
def process_request(self, request):
request.user = User.objects.filter()[0]
Edit MIDDLEWARE in your settings.py:
Remove 'django.contrib.auth.middleware.AuthenticationMiddleware'
Add 'auto_auth.AutoAuthMiddleware'
You can change User.objects.filter()[0] to something else if you want a particular user.
In response to your comment: yes. To run the Django admin without users at all, try this:
class User:
is_superuser = True
is_active = True
is_staff = True
id = 1
def return_true(*args, **kwargs):
return True
User.has_module_perms = return_true
User.has_perm = return_true
class AutoAuthMiddleware(MiddlewareMixin):
def process_request(self, request):
request.user = User()
And remove 'django.contrib.auth' from INSTALLED_APPS
But if you use any apps that depend on the auth app, you're going to have a bad time.
The accepted answer adapted for Django version >= 1.10
/[yourapp]/middleware.py:
from django.contrib.auth.models import User
class AuthenticationMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.user = User.objects.filter()[0]
return self.get_response(request)
In [yourproject]/settings.py for the MIDDLEWARE list:
Comment or remove: 'django.contrib.auth.middleware.AuthenticationMiddleware',
Append: '[yourapp].middleware.AuthenticationMiddleware',
Probably obvious to most people but note that the solution still requires one user to exist. Create one manually python manage.py createsuperuser or automatically with a script:
How to automate createsuperuser on django?
Autocreate superuser with each schema django
Create django super user in a docker container without inputting password
Another Option allows access from anyone: get the first user to bypass authentication
# app/admin.py
from django.contrib.auth.models import User
anonymous_user = User.objects.all().first()
admin.site.has_permission = lambda r: setattr(r, 'user', anonymous_user) or True
For the newer versions of django >=2.1 you need to do something like this:
auto_auth.py
class User:
is_superuser = True
is_active = True
is_staff = True
id = 1
pk = 1
User.has_module_perms = True
User.has_perm = True
class Middleware(object):
def __init__(self, get_response):
self.response = get_response
def __call__(self, request):
request.user = User()
return self.response(request)
And also don't forget to modify your settings middleware and deactivate django.contrib.auth and add auto_auth
For all using Django 3.0,
comment out this code AUTH_USER_MODEL = 'customUser' in your settings.py and create a superuser (python manage.py createsuperuser) with the default user model first.
After creating the superuser then uncomment this code AUTH_USER_MODEL = 'customUser'.
This happened to me and that's what I did with Django 3.0
You should be good to go. Hope it helps

templatetags don't refresh

I have two templatetags in my app which contain forms which show entries in db. When I alter data or add new entry to db, the forms show the old data. While in admin panel everything is correct (updated). When I restart the server (I mean manage.py runserver) forms show updated db entries. How to make the forms show updated data?
regards
chriss
EDIT:
file: templatetags/oceny_tags.py:
from django import template
from oceny.formularze import StudentFormularz, PrzeniesStudentaFormularz
def dodajStudenta(req):
formularz = StudentFormularz(req)
return {'formularz': formularz}
def przeniesStudenta(req):
formularz = PrzeniesStudentaFormularz(req)
return {'formularz': formularz}
register = template.Library()
register.inclusion_tag('oceny/formularz_studenta.html', takes_context = False)(dodajStudenta)
register.inclusion_tag('oceny/formularz_przenies_studenta.html', takes_context = False)(przeniesStudenta)
file: views.py view responsible for handling forms:
def zarzadzajStudentami(request):
formularze = ['dodaj_studenta', 'przenies_studenta']
req = {}
for e in formularze:
req[e] = None
if request.POST:
req[request.POST['formularz']] = request.POST
if request.POST['formularz'] == 'dodaj_studenta':
formularz = StudentFormularz(request.POST)
if formularz.is_valid():
formularz.save()
return HttpResponseRedirect(reverse('zarzadzaj_studentami'))
elif request.POST['formularz'] == 'przenies_studenta':
formularz = PrzeniesStudentaFormularz(request.POST)
if formularz.is_valid():
student = Student.objects.get(id = request.POST['student'])
grupa = Grupa.objects.get(id = request.POST['grupa'])
student.grupa = grupa
student.save()
return HttpResponseRedirect(reverse('zarzadzaj_studentami'))
return render_to_response('oceny/zarzadzaj_studentami.html', {'req': req}, context_instance = RequestContext(request))
I realize that the code may be lame in some cases. I would appreciate any other hints how to write things better.
I have too low rep to comment, but takes_context defaults to False, making your assignment redundant. Also, but now I am guessing, but it might be related to your problem.
Look for "CACHE_BACKEND= ????" in your settings.py file. The value will change as a function of which caching mechanism you are using. Comment this out and restart the server. If your values are now showing correctly, then it was a caching problem.
Are you using some kind of cache system? It could be that.

Django Admin's "view on site" points to example.com instead of my domain

I added a get_absolute_url function to one of my models.
def get_absolute_url(self):
return '/foo/bar'
The admin site picks it up and adds a "view on site" link to the detail page for that object (when I put a real URL there instead of "/foo/bar").
The problem is instead of going to http://localhost:8000/foo/bar, it goes to http://example.com/foo/bar.
What am I doing wrong?
You have to change default site domain value.
The funniest thing is that "example.com" appears in an obvious place. Yet, I was looking for in in an hour or so.
Just use your admin interface -> Sites -> ... there it is :)
You can change this in /admin/sites if you have admin enabled.
As others have mentioned, this is to do with the default sites framework.
If you're using South for database migrations (probably a good
idea in general), you can use a data migration to avoid having to make this same database change everywhere you deploy your application, along the lines of
from south.v2 import DataMigration
from django.conf import settings
class Migration(DataMigration):
def forwards(self, orm):
Site = orm['sites.Site']
site = Site.objects.get(id=settings.SITE_ID)
site.domain = 'yoursite.com'
site.name = 'yoursite'
site.save()
If you are on newer versions of django. the data migration is like this:
from django.conf import settings
from django.db import migrations
def change_site_name(apps, schema_editor):
Site = apps.get_model('sites', 'Site')
site = Site.objects.get(id=settings.SITE_ID)
site.domain = 'yourdomain.com'
site.name = 'Your Site'
site.save()
class Migration(migrations.Migration):
dependencies = [
('app', '0001_initial'),
]
operations = [
migrations.RunPython(change_site_name),
]
When you have edited a Site instance thought the admin, you need to restart your web server for the change to take effect. I guess this must mean that the database is only read when the web server first starts.

Categories