Where to implement python classes in Django? - python

I'm learning Django on my own and I can't seem to get a clue of where I implement a regular Python class. What I mean is, I don't know where do the Python classes I write go. Like they go in a separate file and then are imported to the views.py or are the classes implemented inside the views.py file?
Example I want to implement a Class Alphabet, should I do this in a separate file inside the module or just implement the functions inside the views.py file?

I don't know where do the Python classes I write go. Like they go in
a separate file and then are imported to the views.py.
Example I want to implement a Class Alphabet.
It's just a matter of getting your import statement correct:
django_proj1/
django_proj1/
myapp/
myclasses.py
views.py
Then in your view:
#myapp/views.py:
from myapp.myclasses import Alphabet
Or, you could do it like this:
django_proj1/
django_proj1/
myclasses.py
myapp/
views.py
And in your view:
#myapp/views.py:
from django_proj1.myclasses import Alphabet
Response to comment:
And after I successfully imported my class, how do I pass the
attributes to an HTML template?
The following is straight from the official django tutorial.
myapp/views.py:
from django.shortcuts import render
from django.http import HttpResponse
from myapp.myclasses import Alphabet #<*** Import your class.
from django.template import RequestContext, loader #<*** Import stuff for the template.
# Create your views here.
def index(request):
alph = Alphabet()
result = alph.change('hello') #Your class produces some result here.
template = loader.get_template("myapp/index.html")
context = RequestContext(request, {
'x' : result #<*** Make a variable named x available in your template.
})
return HttpResponse(template.render(context))
The directory structure looks like this:
django_proj1/
django_proj1/
myapp/
myclasses.py
views.py
templates/ <***Create this directory
myapp/ <***Create this directory
index.html <***Create this file
myapp/templates/myapp/index.html:
{% if x %}
<div>The result you requested was: {{x}}</div>
{% else %}
<div>Sorry, couldn't get the result.</div>
{% endif %}
myapp/myclasses.py:
class Alphabet:
def change(self, word):
return word + 'Z'
Start the server:
.../my_django_projects/django_proj1$ python manage.py runserver
url in your browser:
http://localhost:8000/myapp/
You should see:
The result you requested was: helloZ
If you comment out the following line in myapp/views.py:
context = RequestContext(request, {
#'x' : result #<*** Make a variable named x available in your template.
})
Then the template will send the else portion of index.html to the browser:
Sorry, couldn't get the result.
django_proj1/django_proj1/urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from . import views
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'dj1.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^myapp/', include('myapp.urls')),
)
django_proj1/myapp/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]

Django is just Python at the end of the day.
You can create new modules anywhere in your project, and import them into your views, models, urls, etc. This is often how you'd organize general utils (utils.py).
You can deliver data to your views in a few ways, for instance:
from your_module import some_object
class MyView(TemplateView):
template_name = 'some_template.html'
def get_context_data(self, **kwargs):
context = super(MyView, self).get_context_data(**kwargs)
context['my_data'] = some_object.some_method()
return context
And in some_template.html: {{ my_data }}

It depends on the scope of the Alphabet class. If it is a utility class then I would suggest to put in a utils.py file, for example. But it is perfectly fine to have classes in the views.py file, mainly those dealing with UI processing. Up to you.

Distinct to similar frameworks, you can put your Python code anywhere in your project, provided you can reference them later by their import path (model classes are partially an exception, though):
Applications are referenced by their import path (or an AppConfig import path). Although there's some magic involving test.py and models.py, most of the times the import / reference is quite explicit.
Views are referenced by urls.py files, but imported as regular python import path.
Middlewares are referenced by strings which denote an import path ending with their class name.
Other settings you normally don't configure are also full import paths.
The exception to this explicitness is:
models.py, test.py, admin.py : They have special purposes and may not exist, providing:
You will not need any model in your app, and will provide an AppConfig (instead of just the app name) in your INSTALLED_APPS.
You will not rely on autodiscovery for admin classes in your app.
You don't want to make tests on your app, or will specify a non-default path for your app-specific test command run.
templates and static files: your project will rely on per-app loaders for your static files and for your templates files, and ultimately there's a brute-force search in each of your apps: their inner static/ and templates/ directories, if exist, are searched for those files.
Everything else is just normal python code and, if you need to import them from any view, you just do a normal import sentence for them (since view code is imported with the normal Python import mechanism).

Related

How can i test this url in django

Hi friends i'm trying to test this urls but i don't how do that, i have the following code but it doesn't work
# Method of the test
def testViewDeleteUserIsResolved(self):
url = reverse('inventory:viewDeleteUser', args={'idUser': tbUser.objects.first().id})
self.assertEquals(resolve(url).func,viewDeleteUser)
# Url to try
path('viewDeleteUser/?P<idUser>[0-9a-f-]+', views.viewDeleteUser, name='viewDeleteUser'),
I don't know what reverse('inventory:viewDeleteUser') stands for. I am also a newbie to Django, but I think it will work if you change it to reverse('viewDeleteUser').
tests.py
from django.urls import reverse
from .views import viewDeleteUser
def testViewDeleteUserIsResolved(self):
url = reverse('viewDeleteUser', args={'idUser': tbUser.objects.first().id})
self.assertEquals(resolve(url).func,viewDeleteUser)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('viewDeleteUser/?P<idUser>[0-9a-f-]+', views.viewDeleteUser, name='viewDeleteUser'),
]
In a Django app you have to create a url.py file where all your urls live, you have to put that path() instruction you have in that file.
Then your function needs to be in the views.py file, also take in count the name of the function has to be the same you're declaring in the path() as far I see you you're using views.viewDeleteUser so in the views.py file you need a function like this:
def viewDeleteUser:

ModuleNotFoundError: No module named 'src'

I'm changing view of homepage with app names pages.
I've added pages to settings. this is how directory look like:
- trydjango
- src/
- pages/
- __init__
- views
- products
- trydjango/
- __init__
- settings
- urls
- manage
views' code:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def home_view(*args, **kwargs):
return HttpResponse("<h1>Hello Again</h1>")
urls code
from django.contrib import admin
from django.urls import path
from src.pages.views import home_view
urlpatterns = [
path('admin/', admin.site.urls),
path('', home_view, name='home'),
]
and I see this error when I run server
ModuleNotFoundError: No module named 'src'
First you need to understand what an app in Django is compared to a project.
When you register an app django will look in the project root folder when you try to import it.
Your project root is where your manage.py file is. In your case the src folder.
So when you want to import your views module you need to state
from pages.views
rather than
from src.pages.views
I suggest that you read through and follow (by coding it yourself) the Django tutorial to learn more about project structure and creating your own apps with models, urls etc.
I got the same problem, IDE may use red underline but this code is still correct:
from pages.views

Django TemplateDoesNotExist, but traceback reaches views.py

I have a begin.html file that I'm trying to access at localhost:8000/begin, but I get the DjangoTemplateDoesNotExist error when trying to access it.
The only thing in that template is
<h1>welcome to my app !</h1>
and it's in the app/template directory.
In the same app directory is my views.py file, which contains
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
# Create your views here.
def begin(request):
print("DEBUG STATEMENT")
return render(request, "template/begin.html", {})
The return statement in begin is reached, as both the print statement and the traceback tell me, but Django can't find the template after.
If it's relevant, my urls.py file is
from django.conf.urls import url
from django.contrib import admin
from app.views import begin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^begin/$', begin, name = 'begin')
]
in the project directory.
Since you have not provided the information, i take it as you mean urls.py inside your app. If you have two urls.py you need to redirect from the first urls where django looks to the other one.
from django.conf.urls import include
urlpatterns = [
url(r'^', include('YOURAPPNAME.urls'))
]
In your appdirectory in urls.py write
from . import views //importing views from current directory
urlpatterns = [
url(r'^begin/$' views.begin, name=begin)
]
Another tip, consider using render_to_response when you are using a http response, i know render is newer but since you're using a response i would go with render_to_response in your case, and skip the context.
return render_to_response('YOURAPPNAME'/begin.html)
Check if your template structure like this,
your_app_name
--> **templates**
--> **your_app_name**
--> **'begin.html'**
--> static
--> models.py
--> ........
Then, change your views, like this,
return render(request, "your_app_name/begin.html", {})
Django as default check for the directory under the name "templates", in your app_directory.
When accommodating multiple apps, for easiness ​templates are kept under the directory with app_name.
From the docs,
It’s possible – and preferable – to organize templates in subdirectories inside each directory containing templates. The convention is to make a subdirectory for each Django app, with subdirectories within those subdirectories as needed.
Do this for your own sanity. Storing all templates in the root level of a single directory gets messy.
When APP_DIRS is True, DjangoTemplates engines look for templates in the templates subdirectory of installed applications. This generic name was kept for backwards-compatibility.

Django - Import views from separate apps

I'm new to Django and working my way through "The Django Book" by Holovaty and Kaplan-Moss. I have a project called "mysite" that contains two applications called "books" and "contact." Each has its own view.py file. In my urls.py file I have the following:
from books import views
from contact import views
...
urlpatterns = patterns('',
...
(r'^search/$', views.search),
(r'^contact/$', views.contact),
...
When I run my code I get this error:
NameError at /search/
...
Exception value: 'module' object has no attribute 'search'
What I believe is happening is that since views from contact was imported last, Django is looking at contact's view which does not contain search (search is in books' view).
What is the proper way to import the views.py file from two distinct applications within a Django urls file?
Thanks for your help!
Disclaimer: Not a Django answer
The problem is with these two lines:
from books import views
from contact import views
The second import is shadowing the first one, so when you use views later you're only using the views from contact.
One solution might be to just:
import books
import contact
urlpatterns = patterns('',
...
(r'^search/$', books.views.search),
(r'^contact/$', contact.views.contact),
...
I'm not sure, but I also think that you don't actually need to import anything and can just use strings in your pattern, something like: 'books.views.search'.
Another possiblity is to follow Simon Visser suggestion:
from books.views import search
from contact.views import contact
from books import views
from contact import views
You are overwriting the name views. You need to import them as different names or as absolute names.
import books.views
import contact.views
... or ...
from books import views as books_views
from contact import views as contact_views
Then use the correct name when defining your URLs. (books.views.search or books_views.search depending on the method you choose)
The reason I’m answering this question is because it was answered years ago and those answers are not correct or useful anymore for newer Django versions, or there is a better practice you should know about.
So, if you have more than one app in your Django project then you should use a new urls.py file for every one of your apps. It means that if you start a new app then you have to manually create a new file called urls.py in the subfolder of your new app. Many beginners first do not understand why this is good, but this is a good practice if you plan creating more apps in one Django project.
When you start a project, the urls.py file automatically created in your project folder, but if you create/start a new app in Django, then it is a good practice if you create a separate urls.py for that app in its own folder. (And that way you will never have the "importing different app's views into urls.py" problem in the first place).
After you created the urls.py file for your app, then you have to include that app’s urls.py file in your project’s urls.py file in the following way:
Let’s see an example when you create a new app called ‘my_new_app’.
This is how your project’s main urls.py file should look like:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^my_new_app/', include('my_new_app.urls')),
]
In your project’s urls.py file you have to import the ‘include’ method, then you can include your my_new_app urls.py file in your project’s main urls.py file. In your my_new_app folder you have to manually create a urls.py file as I stated above. Then you have to use that file for all of your urlpatterns of your my_new_app. Then of course this way it’s going to be automatically included in your project’s main urls.py file.
So this is then how your my_new_app own urls.py file should look like:
from django.conf.urls import url
from my_new_app import views
urlpatterns = [
url(r'^$', views.index, name = "index"),
]
Assuming that you also created a first view called ‘index’ in your ‘my_new_app/views.py file.
my_new_app/views.py file look like this:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello World!")
And you can check your my_new_app in your browser at:
http://localhost:8000/my_new_app
(Of course you can give any url to your my_new_app in your project's urls.py file.)
Now, you can create another app, in your Django project, called my_second_app and you should repeat the above steps for that app too. This way you will not have any problem importing views from different apps into urls.py files. This would be a very basic “good practice solution” for this problem in 2017 in Django 1.11.
The URLconfs documentation gives an example of the same situation
You can skip the imports and separate the urls by app as such:
urlpatterns = patterns('books.views',
(r'^/book/search/$', 'search'), #calls books.views.search
)
urlpatterns += patterns('contact.views', #make note of the '+='
(r'^/contact/search/$', 'search'), #calls contact.views.search
)
Heres the approach i took for different view/API versions:
from django.urls import path
from my_app import views as api_v1
from my_app import views_v2 as api_v2
urlpatterns = [
path('view_one', api_v1.ViewOne.as_view()),
path('view_two', api_v2.ViewTwo.as_view()),
]

Views and models as python package cannot be resolved

I'm fairly new to Django, and I try to get the hang of using modules for views and models. Strangely enough, the URls work fine.
My app structure is
templatetags/
urls/
views/
models.py
tests.py
The views-dir has an __init__.py, and animals.py, containing one view.
from myapp.models import Animal
from django.shortcuts import render_to_response
def overview(request):
objects = Animal.objects.all()
return render_to_response('myapp/animal_list.html', {'objects': objects})
There's an animals.py in urls/, containing
from myapp.views.animals import *
urlpatterns = patterns('',
url(r'^$', 'views.animals.overview', {}, 'myapp_animal_overview'),
)
The result:
Caught ViewDoesNotExist while rendering: Could not import views.animals. Error was: No module named animals
But it's there! Can anyone see where I go wrong here? My app consists of about 10 models, hence the need for splitting.
Thank you very much in advance.
Well, generally, you don't need to import myapp.views.animals. The URL dispatcher imports the required view as necessary when the regex matches a requested URL, as per: https://docs.djangoproject.com/en/dev/topics/http/urls/#how-django-processes-a-request.
Generally speaking, I would expect your urls.py to look something like:
from django.conf import settings
from django.conf.urls.defaults import patterns, include, url # for example ...
urlpatterns = patterns('',
url(r'^$', 'views.animals.overview'),
)
You were right, I didn't need that extra import.
What did work, was
urlpatterns = patterns('',
url(r'^$', 'myapp.views.animals.overview'),
)
I needed to specify the app where the views were. Problem solved!

Categories

Resources