Django - Paginator.get_page() in ListViews - django-views

I am using django 3.2
ListView uses "Paginator.page(number)" for pagination. I would like to use "Paginator.get_page(number)".
If this is my views what should I do to use "Paginator.get_page(number)"?
class MyList(ListView):
model = MyModel
template_name = "template.html"
paginate_by = 5
and as an extra I would like to use "Paginator.get_elided_page_range(number, *, on_each_side=3, on_ends=2)"
Thanks.

Related

Missing filterset object in context using django-tables2 and django-filter

I have been trying to create a view with filter-bar and a table of users.
I am using django-tables2 and django-filter libraries and I have this view:
class UserListView(SingleTableView, FilterView):
model = User
template_name = 'admin/users.html'
table_class = AdminUserTable
filterset_class = UserFilter
paginate_by = 10
However the problem is that there is no filterset object in data-context sent to template, nor there is no filterset object in self of UserListView.
I was trying to replace SingleTableView, FilterView to FilterView, SingleTableView and then it passes filterset object under filter key in context to the template, however in this case when I visit a page with no filter parameters in url it shows empty list. But If I put a ?search= in url it shows all users and filtering works fine.
I've found a solution:
def get_table_data(self):
return self.filterset.qs
I don't like it, but it works. I believe that there is a better solution.
I had the same issue and found in the doc the "strict" attribute:
https://django-filter.readthedocs.io/en/stable/ref/filterset.html#strict
but this is valid only for version 1.11.
Change for version 2 is documented in:
https://github.com/carltongibson/django-filter/pull/788
so adding strict=False to your View should help:
class UserListView(SingleTableView, FilterView):
model = User
template_name = 'admin/users.html'
table_class = AdminUserTable
filterset_class = UserFilter
paginate_by = 10
strict=False

Get date selection widget in generic form view django

I have a model task for which I've written the following generic form to give facility to add a new task:
class AddTask(generic.CreateView):
model = task
fields = ['project','task_name','expected_date']
success_url = reverse_lazy('home')
template_name = 'st_web/addtask.html'
This is working pretty fine. The only problem is that date field is an text type field. I read solutions for similiar questions, one of which proposed writing a date widget in my view like:
from django import forms
........................
class DateInput(forms.DateInput):
input_type = 'date'
.........................
.........................
class AddTask(generic.CreateView):
model = task
fields = ['project','task_name','expected_date']
widgets = {
'expected_date': DateInput()
}
success_url = reverse_lazy('home')
template_name = 'st_web/addtask.html'
However this doesn't work for me. Can please anyone suggest a simple answer(some of them were suggesting adding some i8j.js or something like that but it'd really be helpful if there is a shorter solution available) to this problem? Thanks.
In your forms.py :
from django import forms
class AddTask(forms.ModelForm):
class Meta:
model = task
fields = ('project','task_name','expected_date', )
expected_date = forms.DateField(
widget = forms.DateInput(
attrs= {
'type':'date',
}
)
)

GeoDjango: Can I use OSMGeoAdmin in an Inline in the User Admin?

Profile contains a PointField. I've used OSMGeoAdmin in the ProfileAdmin, here:
class ProfileAdmin(admin.OSMGeoAdmin):
model = Profile
But can't figure out how to use it in an inline for display in the UserAdmin. I currently have this set up as below:
# User Admin, with Profile attached
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile' # As only one is displayed in this view
class UserAdmin(UserAdmin):
inlines = (
ProfileInline,
)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Is it possible to use class OSMGeoAdmin in this situation?
This would be a good feature to request I guess.
As a workaround, you can take advantage of the fact that an InlineModelAdmin is quite similar to a ModelAdmin. Both extend BaseModelAdmin.
Inheriting from both StackedInline and ModelAdmin should not clash too much.
The only issue is that both __init__() methods take 2 positional arguments and call super().__init__() without arguments. So whatever the inheritance order, it will fail with TypeError: __init__() missing 2 required positional arguments: 'parent_model' and 'admin_site'
Fortunately, the InlineModelAdmin.__init__() method, the one we are interested in, is not really verbose nor complex (not too much super().__init__() calls in cascade).
Here is what it looks like in Django 1.9:
def __init__(self, parent_model, admin_site):
self.admin_site = admin_site
self.parent_model = parent_model
self.opts = self.model._meta
self.has_registered_model = admin_site.is_registered(self.model)
super(InlineModelAdmin, self).__init__()
if self.verbose_name is None:
self.verbose_name = self.model._meta.verbose_name
if self.verbose_name_plural is None:
self.verbose_name_plural = self.model._meta.verbose_name_plural
And here is what its parent (BaseModelAdmin) looks like in Django 1.9
def __init__(self):
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
overrides.update(self.formfield_overrides)
self.formfield_overrides = overrides
Now let's put it all together:
from django.contrib.admin.options import FORMFIELD_FOR_DBFIELD_DEFAULTS
# User Admin, with Profile attached
class ProfileInline(OSMGeoAdmin, admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile' # As only one is displayed in this view
def __init__(self, parent_model, admin_site):
self.admin_site = admin_site
self.parent_model = parent_model
self.opts = self.model._meta
self.has_registered_model = admin_site.is_registered(self.model)
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
overrides.update(self.formfield_overrides)
self.formfield_overrides = overrides
if self.verbose_name is None:
self.verbose_name = self.model._meta.verbose_name
if self.verbose_name_plural is None:
self.verbose_name_plural = self.model._meta.verbose_name_plural
class UserAdmin(UserAdmin):
inlines = (
ProfileInline,
)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
It's not really a satisfying solution as it requires to copy/paste some code from django, which may be different within the version of Django you use, and might be a pain to maintain when upgrading Django. However it should work until it is included in Django as a mix-in or as an InlineModelAdmin.
Note: the code snippets above are taken from Django 1.9, you should browse github tags to find the snippets corresponding to your version.
Since Django admin fields use widgets, you can override the widget that's automatically set for a PointField using formfield_overrides. In this case, you can override all PointField instances to use the OSMWidget class like so:
from django.contrib.gis.forms.widgets import OSMWidget
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile' # As only one is displayed in this view
formfield_overrides = {
PointField: {"widget": OSMWidget},
}

example template for django rest framework pagination

I am trying to use Django REST framework for the first time and looking at the tutorials there is no template examples, What can I use for template? I tried template_name = 'authorListAjax.html' but I get this response http://imgur.com/fMlyXDN
views.py
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ('subject', 'date', 'time_start')
class AuthorListAll1(ListAPIView):
template_name = 'authorListAjax.html'
queryset = Author.objects.all()
serializer_class = AccountSerializer
paginate_by = 2
paginate_by_param = 'page_size'
max_paginate_by = 100
urls.py
url(r'^ajax/list/$', AuthorListAll1.as_view(), name='ajax_list'),
You need to set a renderer: http://www.django-rest-framework.org/api-guide/renderers#templatehtmlrenderer
This means adding this line (which tells DRF that the response will be HTML, not JSON):
renderer_classes = (TemplateHTMLRenderer,)
Also, you can not set the template name on your view class; the template name belongs to the renderer class. You can either set it directly on the renderer, like this:
TemplateHTMLRenderer.template_name = 'authorListAjax.html'
or you can overwrite the get method and set it there, like this:
return Response({'user': self.object}, template_name='authorListAjax.html')
I recommend you the second way, because the first one sets the template name globally, and it might get you in troubles :)

change django-tinymce content css for various object

How can I change content_css option in django-tinymce for various objects? I mean that when I use tinymce for model1 then content_css is model1.css and when for model2 then model2.css.
I use
I found out that I can pass extra arguments for tiny_mce in Meta class:
class Meta:
model = MyModel
widgets = {
'field_name': TinyMCE(mce_attrs={'content_css': "style.css"}),
}
Thanks for the szaman's reply, I'll try to describe the process for beginners in new versions of Django (1.9), how to add custom css files to the field named 'text' in the Post model in the Django's admin
Change fields' type in models.py to HTMLField
from tinymce.models import HTMLField
class Post(models.Model):
title = models.TextField(default='')
subtitle = models.TextField(default='')
text = HTMLField(default='')
In the application with the required model, add to admin.py file:
#admin.register(Post) # decorator for adding Django admin for Post
class PostAdmin(admin.ModelAdmin):
form = PostForm # attach custom form
Add form's class
from tinymce.widgets import TinyMCE
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__' # required in Django (>=1.8)
widgets = {
'text': TinyMCE(mce_attrs={'content_css': ["path_to_css_file",]}),
}