how create a view class include all function in django view - django

For example i have a admin app in a django project. I have 2 view function in views.py like as
views.py
from django.shortcuts import render, redirect
from .models import Manager
def admin_home(request):
manager = 'manager'
context ={
'manager':manager,
}
return render(request, 'home/index.html', context)
def admin_show(request):
manager = Manager.objects.all()
context ={
'manager':manager,
}
return render(request, 'home/index.html', context)
But i want to write both function in a class. like as
from django.shortcuts import render, redirect
from .models import Manager
from django.views import View
class AdminPart(View):
def admin_home(request):
manager = 'manager'
context ={
'manager':manager,
}
return render(request, 'home/index.html', context)
def admin_show(request):
manager = Manager.objects.all()
context ={
'manager':manager,
}
return render(request, 'home/index.html', context)
Isn't it possible in django like as python class. please help me....

There are class based views in Django.
Here read the docs:
https://docs.djangoproject.com/en/3.1/topics/class-based-views/
or maybe try this tut:
https://www.youtube.com/watch?v=-tqhhT3R6VY
Hope this helps! (:

You can also use Django rest framework, it provides many feature-rich types of class-based views like generic api view, viewset
https://www.django-rest-framework.org/tutorial/3-class-based-views/

Related

How to render the Form (in a template tag) automatically created by CreateView

How do I render a Form automatically created by CreateView CBV?
Setup
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from .models import Journal
from django.urls import reverse
class CreateJournal(LoginRequiredMixin, CreateView):
model = Journal
template_name = 'journals/journal_list.html'
fields = ('journal_name',)
def get_success_url(self):
return reverse('home')
def form_valid(self, form):
form.instance.journal_user = self.request.user
return super(CreateJournal, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(CreateJournal, self).get_context_data(**kwargs)
context['Journals'] = Journal.objects.filter(journal_user=self.request.user)
return context
urls.py
urlpatterns = [
path('', CreateJournal.as_view(), name='journals'),
path('<slug:slug>', JournalEntriesList.as_view(), name='to-journal-entries'),
]
As you can see I do not have a specific form mentioned, here, that is because I don't have one. CreateView creates one automatically. As you can see, this view (which does two jobs right now, help user create an object and at the same time displays all the objects) is now rendering to 'to-journals/journal_list.html`.
I want to display the same thing (both the View and the Form) on the "home" page or any other page.
Current template tag only gets the data from the database (context)
My current attempt looks like this:
journal_tags.py
register = template.Library()
#register.inclusion_tag('template_tags/journal_list.html', takes_context=True)
def get_journals(context):
journals = Journal.objects.filter(journal_user=context['request'].user)
return {'journals': journals}
This successfully renders all the existing journals to any page I want. Now, how do I also render the form, that CreateView created for me.
Failed Approach
One approach I tried is to add the for argument to the function like so:
journal_tags.py
#register.inclusion_tag('template_tags/journal_list.html', takes_context=True)
def get_journals(context):
journals = Journal.objects.filter(journal_user=context['request'].user)
return {
'journals': journals,
'form': CreateJournal,
}
This doesn't work because CreateJournal is a view and not the form. My question is how do I render the form created by class CreateJournal(LoginRequiredMixin, CreateView)?
Thanks for taking the time to look at this. I really appreciate the help of our community! Have a great day!
journal_tags.py
register = template.Library()
#register.inclusion_tag('template_tags/journal_list.html', takes_context=True)
def get_journals(context, self):
journals = to_journal.objects.filter(journal_user=context['request'].user)
return {
'journals': journals,
'form': JournalForm
}
Where JournalForm is as ModelForm created in models.py
class JournalForm(ModelForm):
class Meta:
model = to_journal
fields = ['journal_name']

How to use different views for a certain url base on authentication?

When a request come for /page-one url, I'd like to use view_a if the user is authenticated and view_b for the guest visitors.
The code should be like this:
def dummy(request):
if request.user.is_authenticated():
print 'authuser'
return view_a(request)
else:
print 'unauth user'
return view_b(request)
How can I achieve this in django?
I've looked at the docs but could not find any relevant guides about this.
You can use is_authenticated
Use this in views
if user.is_authenticated:
return render(request, 'polls/detail.html', {'poll': p})
else:
return render(request, 'polls/another-detail.html', {'poll': p})
To redirect to different views (not just render different templates)
from django.urls import reverse
from django.http import HttpResponseRedirect
...
if user.is_authenticated:
return HttpResponseRedirect(reverse('some_detail', kwargs={'pk': pk}))
else:
return HttpResponseRedirect(reverse('another_detail', kwargs={'pk': pk}))
and in your urls you would have to 'name' the view
path('another_detail/<int:pk>/', views.another_detail, name='another_detail'),

Custom error pages using django 1.10

Hello I'm newbie in Django,
I'm looking to creating custom error pages to my app and found this site: http://blog.eliacontini.info/post/118617321553/django-custom-error-pages
However the 'render_to_response' is not used in Django 1.10
How do I transcript this code to Django 1.10
With best regards.
render_to_response() still works in Django 1.10, but if you want to use the more classical approach, you can use render(). Example:
from django.shortcuts import render
def myview(request):
if request.METHOD == 'GET':
context = {}
return render(request, 'index.html', context, status=404)
Django 1.10 passes three parameters to the page_not_found (https://docs.djangoproject.com/en/1.10/ref/views/#django.views.defaults.page_not_found)
create a function in your custom exceptions view
from django.shortcuts import render
def page_not_found(request, exception, template_name='404.html'):
return render(request, "page-not-found.html", context=None, status=404)
then add this line to your urls.py
handler404 = 'path_to_exceptions_view.page_not_found'

Django : how to include a view.py file inside a view from another app?

I've made a "paginator" app, that add such SEO optimisation for all my pages.
So I need to pass all visible page url through paginator.view
But, I want to keep my apps as structured as possible.
For an example here is a view for my gallery app:
gallery.views
from django.shortcuts import render
from gallery.models import GalleryItem
def home(request):
img_to_display = GalleryItem.objects.filter(published=True
).order_by('-date')
return render(request, 'gallery/all.html', locals())
...
Now I'm doing like that form my view in paginator :
My current paginator.views
from django.shortcuts import render, get_object_or_404, redirect
from gallery.models import GalleryItem
from paginator.models import Page
import gallery
def custom_page(request, url):
current_page = url
# just for the gallery page :
if url == 'gallery':
img_to_display = GalleryItem.objects.filter(published=True
).order_by('-date')
# for all my page
page_to_load = get_object_or_404(Page, name=url)
template_to_load = "paginator/" + page_to_load.template_name
return render(request, template_to_load, locals())
So I copy/paste my view and all dependencies, but that is really ugly, and not at all DRY, worth it's not maintainable. I try something like that but it doesn't work :
paginator.views : option1
from django.shortcuts import render
import gallery
def custom_page(request, url):
if url == 'gallery':
gallery.views.home(request)
if url == 'anotherpage':
anotherapp.views.home(request)
...
Or something like that :
paginator.views : option 2
from django.shortcuts import render
def custom_page(request, url):
if url == 'gallery':
include("gallery.views.py")
if url == 'anotherpage':
include("anotherapp.views.py")
...
Note: I prefer the last style option because it minimize the import at the start of the paginator.views file.
Thanks a lot for helping ! :)
If you need a mechanism which is executed before the request is dispatched to a view, I would recommend using a middleware class. You can read more about it in the Django docs.
Another option is to use class based views to create a SEOView which can be inherited by every custom page view of yours. Some example of how it could look like:
from django.views.generic.base import View
class MySeoView(View):
def dispatch(self, request, *args, **kwargs):
# some logic for SEO
return super().dispatch(request, *args, **kwargs)
class CustomView1(MySeoView):
def get(self, request, *args, **kwargs):
# do normal stuff for this page
return HttpResponse(...)
def post(self, request, *args, **kwargs):
# maybe some other logic for posts
return HttpResponse(...)
To come back to your own options:
If you want to make #1 work, I guess you have to return the result of the view:
...
if url == 'someUrl':
return gallery.views.home(request)
...
Firstly I want to thanks Gocht to have sended me on a good way. So that's what I've done :
paginator.views
def custom_page(request, url):
"""
Vue d'une page statique.
"""
if url == 'gallery':
import gallery
gal = gallery.views.render_gallery(request)
gal.render()
gallery_html = gal.rendered_content
if url == 'xxx':
...
page_to_load = get_object_or_404(Page, url=url)
template_to_load = "paginator/" + page_to_load.template_name
return render(request, template_to_load, locals())
gallery.views
from django.template.response import TemplateResponse
from gallery.models import GalleryItem
def render_gallery(request):
img_to_display = GalleryItem.objects.filter(published=True
).order_by('-date')
return TemplateResponse(request, 'gallery/gallery.html', locals())
But yes, now, I understand that something like simP will be more clean. Thanks !

Django: set auth_login as homepage

I'm new to django. Problem: to see my homepage (that shows the default django login form)
i have to write the addess:
x.x.x.xxx:8001/login
I would like to access it directly through that:
x.x.x.xxx:8001
What i can see now if i digit x.x.x.xxx:8001, is the login page without the form.
I have:
in my urls.py:
urlpatterns = patterns('',
url(r'^$', 'license.views.index', name='auth_login'),
in my views.py
from django import template
from django.shortcuts import render_to_response
from django.views.decorators.vary import vary_on_cookie
#vary_on_cookie
def index(request):
return render_to_response('login.html', {
}, context_instance = template.RequestContext(request))
That is because you are not passing a login form instance to your form.
Unless you want to perform some custom stuff in your view, your best bet is to use Django's built-in login view. You can set a custom template for it:
url(r'^$', 'django.contrib.auth.views.login', {'template_name': 'login.html'})
See this page for more info: django.contrib.auth.views.login (v1.5) docs
Now, I see that you are using a decorator on your view, which implies that you do indeed want to perform custom stuff. In that case, I believe you'll want to use the django.contrib.auth.forms.AuthenticationForm. Try doing something like this in your view:
from django.contrib.auth.forms import AuthenticationForm
from django.shortcuts import render
from django.views.decorators.vary import vary_on_cookie
#vary_on_cookie
def index(request):
form = AuthenticationForm(data=request.POST or None)
return render(request, 'login.html', {
'form': form
})