Not understanding how Python Class works - python

I am in need of some help understanding how Python and Django work based on some code I'm looking at.
Say my urls.py file has the following
router.register(r'testing', SomeClass)
and then in my views.py file, it is set up like this:
class SomeClass():
database = DatabaseValues.objects.all()
def first_def(self):
# do some filtering and such on db results
return database
def second_def(self):
a = 20
b = 40
return b - a
def third_def(self):
z = 200
y = 400
return y - z
When the SomeClass is called in UI by hitting the http://localhost/testing url, what is returned??

I would recommend making some changes to urls.py I think this method below is easier to understand.
when you run python3 manage.py runserver
you can open 127.0.0.1/example.
the reason you are not understanding is because Django has a lot of boilerplate code. I would recommend reading more into how views work.
every class in views.py should inherit a django class in this example I use TemplateView. your app name is the folder that is created when a new django "app" is added to the project.
from django.urls import path
from .views import exampleView
app_name = "example"
urlpatterns = [
path('/example', exampleView.as_view(), name='example'),
]
in views.py you cannot create arbitrary function names. when a website loads
www.baseurl/example you are making a get request. therefore you must have a get method inside of your class.
template_name refers to an html page that will be rendered...
this template name must point at an html file which is located inside project_root/templates/html_file.html
views.py
from django.views.generic import TemplateView, ListView
class exampleView(TemplateView):
template_name = 'test.html'
def get(self, request):
print("hello")
return render(request, self.template_name, {})
if you wish to have arbitrary functions inside your class cool. Add them below the get function and call them when a user makes a get request.

Related

Customize django admin. Problem with no-model views

Im trying to create a extra view in django admin, on the left navbar. This view will be responsible for uploading a file, which will be parsed in some function (in future i would like to render result of this parsing in admin page). This file wont be saved in database, so there wont be a model. Is there any possibility to add a view to django admin (left navbar) which dont have a model? I was reading a lot, and could find a solution. What i have done for now:
Created a class which inherits from AdminSite. I tried to implement get_app_list method, but variable self._build_app_dict(request) was empty array, and this means, method couldn't find a installed aps. I wanted to add new object to app_list variable, to render it on website.
Tried to override a admin templates, but couldnt render it. I tried to override app_index.html which i put on folder: app_name/templates/admin/app_index.html
Here is my code, which ofc doesnt work:
class MyCustomAdmin(AdminSite):
def get_app_list(self, request):
"""
Return a sorted list of all the installed apps that have been
registered in this site.
"""
app_dict = self._build_app_dict(request)
breakpoint()
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
for app in app_list:
app['models'].sort(key=lambda x: x['name'])
return app_list
def get_urls(self):
from django.conf.urls import url
urls = super(MyCustomAdmin, self).get_urls()
urls += [
url(r'^my_custom_view/$', self.admin_view(MyCustomView.as_view()))
]
return urls
class MyCustomView(View):
template_name = 'admin/app_index.html'
def get(self, request):
print('fefef')
return render(request, self.template_name, {})
def post(self, request):
pass
admin_site = MyCustomAdmin()
admin_site.get_app_list(AdminSite.get_app_list)

Django : Several paths, one ListView, different templates?

Please help me. I want to have multiple path in urls.py (lets say a, and b). But I want to ONLY have one ListView, and this ListView need to channel me to different html file when I access the url (a.html when access 'a/', b.html when access 'b/').
Currently I use different ListView for each path (aListView and bListView), even though the model is the same. But it seems that it violate the Don't Repeat Yourself rule. And the code looks bad.
So the question is how can I define several different templates in one ListView?
Below is my current mind map. Thank you
My mind route
Here is an example of how you can define multiple paths that points to one ListView within multiple templates:
Let's suppose my app name is example and my project name is test_project; my setup is like this:
test_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
..., # my project urls
path('', include('example.urls'))
]
example/urls.py
from django.urls import path
from example import views
app_name = 'example'
urlpatterns = [
path('a/', views.GenericListView.as_view(), name='a-url'),
path('b/', views.GenericListView.as_view(), name='b-url')
]
templates/a.html
This is A file
templates/b.html
This is B file
example/views.py
from django.views.generic.list import ListView
from django.urls import reverse
class GenericListView(ListView):
a_template = 'a.html'
b_template = 'b.html'
def get_template_names(self, *args, **kwargs):
# Check if the request path is the path for a-url in example app
if self.request.path == reverse('example:a-url'):
return [self.a_template] # Return a list that contains "a.html" template name
return [self.b_template] # else return "b.html" template name
def get_queryset(self, **kwargs):
# For this example i'm returning [] as queryset for both a/ and b/ routes
if self.request.path == reverse('example:a-url'):
return [] # Return whatever queryset for a/ route
return [] # Return whatever queryset for b/ route
For more informations you can visit ListView: get_template_names() Documentation
It seems to me that having 2 separate ListViews is the right approach in your situation. You have 2 different URLs and 2 different templates, so you have 2 different views. I don't think that it violates DRY principles because the common logic is abstracted by the reusable ListView class.

How to set globally-accessible context variables in django template tags?

There is a template tag which returns a random element from the list. I also need to save all the elements that were in the list and the one that had been picked in context, and later depict that information in django-debug-toolbar panel.
from django import template
import random
register = template.Library()
#register.simple_tag(takes_context=True, name='pickrandomelementtag')
def pickrandomelementtag(context, list_of_random_elements):
context.dicts[0]["key18"] = "value19"
return random.choice(list_of_random_elements)
So I test setting the variables functionality with given line:
context.dicts[0]["key18"] = "value19"
I am able to access the {{key18}} within the template, but my aim is set this variable in a manner that it would be accessible later on (globally?) from django-debug-toolbar panel. That's where i'm stuck.
Here is my django-debug-toolbar panels.py file:
from debug_toolbar.panels import Panel
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from django.template.response import SimpleTemplateResponse
class RandomPanel(Panel):
name = "RandomPanel;"
has_content = True
template = 'panels/randompanel.html'
def title(self):
return _('Random Panel')
def generate_stats(self, request, response):
print('that is where I need to access key18')
self.record_stats(
{
"request": request
}
)
How would I access context variable key18 in generate_stats method of RandomPanel class object? Or maybe context is a wrong place to set custom cariables within template tags and you'd advise other approaches? Many thanks!
You can actually store the information in the request itself. Assuming that the context_processor has django.template.context_processors.request (which is there in default settings)
#register.simple_tag(takes_context=True, name='pickrandomelementtag')
def pickrandomelementtag(context, list_of_random_elements):
context['request'].META['MY_INFO'] = "value19"
return random.choice(list_of_random_elements)
Then you have the request object in the Panel where you can use this information.

Django 1.9 : Passing arguments from urls.py to a class view

I am creating a small web application as a mini project of mine to learn the Django framework. I'm on Version 1.9.4, on OS X. I'm trying to pass a string in the URL that will be sent to a class-based view, and it will return a different template based on the URL. To my knowledge, doing (?P) will allow the input of dynamic text. \w is for characters, and writing <name> will pass it as a variable. Is this configured right, or is this is not the correct way to do it?
The reason I'm concerned is that the Django documentation uses method views, while I am using class-based views.
urls.py
from django.conf.urls import url
from . import views
app_name = 'xyz'
urlpatterns = [
url(r'^create/(?P<ty>\w+)$', views.ArticleView.as_view(), name='article-form'), #.as_view() to turn Class into View
]
views.py
class ArticleCreate(View):
l = {
'weapon': WeaponForm,
'map': MapForm,
'operator': OperatorForm,
'gadget': GadgetForm,
'skin': SkinForm
}
ty = ty.lower()
template_name = 'xyz/create_article_form.html'
def get(self, request):
return render(request, self.template_name)
def post(self, request):
pass
The arguments that are being passed to the url should be "catched" within the view inside the relevant function, for example:
def get(self, request, ty):
ty = ty.lower()
return render(request, self.template_name)

Django Admin Custom Pages and Features

I'm (new to) working in Django and would like to create two features that do not rely upon models/database tables. The basis of this app is as a web-based wrapper to a Python application.
The features are:
I would like to be able to load a ConfigObj text file into a page and edit it's configuration prior to saving again.
I would like to be able to call command line python/bash scripts and display their output on a page - like exec in PHP.
At the moment I'm working on simple custom admin pages without model as described here:
Django admin, section without "model"?
Would this be the right direction to go in? I'm not sure proxy tables apply as the features I desire have nothing to do with any data.
So far I have looked at is it possible to create a custom admin view without a model behind it and a few other links. At the moment I have:
main/urls.py
url(r'^admin/weectrl', include('weectrl.urls')),
which links with weectrl/urls.py
from weectrl import views
urlpatterns = patterns('',
(r'^admin/weectrl/manage/$', weectrl_manage_view),
(r'^admin/weectrl/config/$', weectrl_config_view),
)
which points to weectrl/views.py
def weectrl_manage_view(request):
r = render_to_response('admin/weectrl/manage.html', context, RequestContext(request))
return HttpResponse(r)
def weectrl_config_view(request):
r = render_to_response('admin/weectrl/config.html', context, RequestContext(request))
return HttpResponse(r)
The current error message is name 'weectrl_manage_view' is not defined
Ok, found something that works.
In the main url.py
url(r'^admin/weectrl/', include('weectrl.urls')),
In app/urls.py
urlpatterns = patterns('',
url(r'^config/$', views.config, name='config'),
url(r'^manage/$', views.manage, name='manage'),
)
and in app/views.py
def config(request):
context = ""
return render(request, 'weectrl/config.html', context)
def manage(request):
context = ""
return render(request, 'weectrl/manage.html', context)
html files are in app/templates/app/...

Categories