Just following the tutorial for django autocomplete and I'm a little worried because I already can't seem to figure out how to see the view for autocomplete despite writing the view and url for it. I'm trying to use autocomplete-light on
admin for a model called KeywordInContext
urls.py:
url(r'^keywordincontext-autocomplete/$', views.KeywordInContextAutocomplete.as_view(), name='keywordincontext-autocomplete',),
views.py:
class KeywordInContextAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.user.is_authenticated():
return KeywordInContext.objects.none()
qs = KeywordInContext.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
So I'm trying to just perform the "test view" part of the tutorial where I can see my autocomplete view and either I didn't configure something correctly or I didn't type in the url.
the url I attempt to use for the test is /admin/gtr_site/keywordincontext/?q=7 the only part of tht url that I actually type in is ?q=7 for a random primary key... but any variant of this just loads the "KeywordsInContext" admin page.
What am I missing?
Related
I have this function-based view with django-rest-swagger decorated. However, I can't find place in UI that allow me to post the payload (request.body).
I saw a couple solutions about doing it with class-based view, but I was wondering if there is a way to do it with function-based view.
Thank you in advance!
#renderer_classes([JSONRender])
#api_view(['POST'])
def some_method(request):
body = json.loads(request.body)
return JsonResponse({'status': 'ok'})
I am gonna answer my question since the django-rest-swagger was deprecated in June 2019 and I just found out 2 feasible solutions.
First one will change the UI globally.
In ping.views (or any other location you wish) add following class.
from rest_framework.schema import AutoSchema
class CustomSchema(AutoSchema):
def __init__(self):
super(CustomSchema, self).__init__()
def get_manual_fields(self, path, method):
extra_fields = [
coreapi.Field('command', required=True, location='form', schema=String(), description='', type='', example='',
coreapi.Field('params', required=False, location='form', schema=String(), description='', type='', example='',
]
manual_fields = super().get_manual_fields(path, method)
return manual_fields + extra_fields
Add following settings in settings.py of your Django project.
REST_FRAMEWORK = {
# Corresponding path to where you added the class
'DEFAULT_SCHEMA_CLASS': 'ping.views.CustomSchema',
}
Second solution can be applied on a per-view basis. You may check here for official guide
Use #schema from rest_framework.decorators.schema to overwrite DEFAULT_SCHEMA_CLASS.
#api_view(['POST'])
#schema(CustomSchema())
def your_view(request):
print(request.body)
return JsonResponse({'task_status': 200'})
Basically, the idea is to overwrite DEFAULT_SCHEMA_CLASS. The word schema is the term that they used to refer to swagger UI for each view in rest_framework.
When you use #api_view() to decorate your function-based view, it will assign your function an attribute schema with value APIView.schema from rest_framework.views.APIView.
rest_framework.views.APIView will in further call DefaultSchema() to load the DEFAULT_SCHEMA_CLASS from your REST_FRAMEWORK configuration in settings.py.
Without other specifying, DEFAULT_SCHEMA_CLASS is rest_framework.schemas.openapi.AutoSchema by this official announcement. You might want to change it to rest_framework.schemas.coreapi.AutoSchema since it is the one that compatible with django_rest_swagger.
Hope this tutorial helps people who use django-rest-swagger (2.2.0) with function-based views for their Django project.
Please leave comments if there are anything I can help on this issue.
i have followed this tutorial https://books.agiliq.com/projects/django-admin-cookbook/en/latest/action_buttons.html
This is the relevant part of my code:
#admin.register(Partner)
class PartnerAdmin(admin.ModelAdmin):
change_list_template = 'change_list.html'
model = Partner
.
.
.
def get_urls(self):
return super().get_urls() + [path('sync/', self.sync_partners, name='partners_sync_partners')]
#staff_member_required
def sync_partners(self, request):
#TODO: Sync code should go here
self.message_user(request, "Partners sync complete")
return HttpResponseRedirect("../")
The url on template is referenced with {% url 'admin:partners_sync_partners' %} which is pointing to /admin/partners/partner/sync/ and i think it should be /admin/partners/sync/
When i click the button, i am getting this error:
Partner with ID "sync" doesn't exist. Perhaps it was deleted?
I guess the problem is related with the url generated.
My code is inside my app 'partners' in partners/admin.py and my template is under partners/templates/change_list.html
PS: I'm using Django 2.1.1 and Python 3.6.5
Here is an example of custom user which i have created where i have to show all fields in django admin site for custom user .
so you can add that button in list display
list_display = ('email', 'phone','account_name','account_number','bank_name','bsb_number','account_summary')
now make that button a method and give url where you want to render it.
def account_summary(self,obj):
ow_tags = True
return format_html(
'<a class="button" href="{}">Account</a> ',reverse('all_accounts_view', args=[obj.pk]))
account_summary.allow_tags = True
dont forget to add
from django.urls import reverse
I have a model like this:
from wagtail.wagtailcore.models import Page
class Blog(Page):
created = models.DateTimeField(auto_now_add=True)
...
..
Right Now, my default, if my slug is hi-there, the blog post is accessible on site_url:/hi-there/ but I want it accessible via site:url/2014/02/05/hi-there/ The page has various methods like url, url_path which one should I override and what's the best practice to achieve something like this in wagtail?
The RoutablePageMixin is the current (v2.0+) way to accomplish this.
Add the module to your installed apps:
INSTALLED_APPS = [
...
"wagtail.contrib.routable_page",
]
Inherit from both wagtail.contrib.routable_page.models.RoutablePageMixin and wagtail.core.models.Page, then define some view methods and decorate them with the wagtail.contrib.routable_page.models.route decorator:
from wagtail.core.models import Page
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
class EventPage(RoutablePageMixin, Page):
...
#route(r'^$') # will override the default Page serving mechanism
def current_events(self, request):
"""
View function for the current events page
"""
...
#route(r'^past/$')
def past_events(self, request):
"""
View function for the past events page
"""
...
# Multiple routes!
#route(r'^year/(\d+)/$')
#route(r'^year/current/$')
def events_for_year(self, request, year=None):
"""
View function for the events for year page
"""
...
New in Wagtail v0.5 is a mechanism that directly addresses this sort of thing:
Embedding URL configuration in Pages or RoutablePage in v1.3.1
(the docs even have an Blog example!)
I was looking into migrating my blog to a wagtail version and wanted to support my previous url schema and had to solve this exact problem. Luckily I just found a solution and want to share it, hopefully this will be helpful for someone else in the future.
The solution is a 2 Step process.
change the url of a blog page to contain the date as well.
class Blog(Page):
created = models.DateTimeField(auto_now_add=True)
def get_url_parts(self, request=None):
super_response = super().get_url_parts(request)
# handle the cases of the original implementation
if super_response is None:
return None
(site_id, root_url, page_path) = super_response
if page_path == None:
return super_response
# In the happy case, add the date fields
# split prefix and slug to support blogs that are nested
prefix, slug, _ = page_path.rsplit("/", 2)
return (
site_id,
root_url,
f"{prefix}/{self.created.year}/{self.created.month}/{self.created.day}/{slug}/",
)
And now we need to make those posts also route-able.
class BlogIndexPage(RoutablePageMixin, Page):
...
def route(self, request, path_components):
if len(path_components) >= 4:
year, month, day, slug, *rest = path_components
try:
subpage = self.get_children().get(slug=slug)
return subpage.specific.route(request, rest)
except Page.DoesNotExist:
...
return super().route(request, path_components)
This solution ignores the date and just use the slug to locate a blog post as the original solution. This should also work when you don't use the RoutablePageMixin.
Hope this is still helpful for someone.
i want to display additional sidebar in my django admin index. I have created templates/admin/index.html and it show up. Now i need some data from model. To do this I have created index function in the file admin/views.py
def index(request):
var = 'var'
return render_to_response('admin/index.html', {'var': var})
Without this function I have error ViewDoesNotExist.
However template not react for this sample variable 'var'. Moreover my app doesn't display in the index. I have only auth app.
I think that I'm overwriting index function form admin view. How to properly overwrite this function?
Instead of overwriting the view entirely, you can add logic to the views in your ModelAdmin (admin.py) class:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#other-methods
so for example:
class MyAdmin(admin.ModelAdmin)
...
def add_view(self, request, form_url='', extra_context=None):
# Do some extra queries that will get passed to the template
c = {'x':SomeModel.objects.all()}
super(MyAdmin, self).add_view(request, extra_context=c)
Consider using django admin tools https://bitbucket.org/izi/django-admin-tools/wiki/Home
then you get commands like manage.py customdashboard, manage.py custommenu etc.
It even has a nice bookmark-functionality to quickliy jump to certain objects or list pages.
I have a purchase page, it can take an optional argument as a gift, if it is a gift, the view passes a gift form to the template and if not, a regular purchase form.
my old regular url, which redirects to two seperate views:
(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view'),
(r'^(?P<item>[-\w]+)/purchase/gift$', 'gift_view'),
and the views was like this:
def purchase_view(request,item):
....use purchase form
def gift_view(request,item):
....use giftform
It is a bad design indeed, as both views having are almost everything same but the forms used.
I have also thougt about using GET and giving gift as a GET param however it wasnt a good idea as I am using POST method for these pages, especially would cause issue after validation.
How can I make this a single url and a single view?
Thanks
urls.py
url(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view', name='purchase_view'),
url(r'^(?P<item>[-\w]+)/purchase/(?P<gift>gift)/$', 'purchase_view', name='gift_view'),
views.py
def purchase_view(request, item, gift=False):
if gift:
form = GiftForm
else:
form = PurchaseForm
...