Multiple apps and views in a single html page in Django - html

I am relatively new to Django and do not understand it in depth. For some reason even though everyone says that Django documentation is amazing, I do not understand it what so ever.
For some reason, I am not able to integrate a model, model and a view from 2 different apps into my home.html page.
What I am trying to do is to get a newsletter sign up, as a form. It is inside jobs app Jobs also include "Jobs" which I display on the home page and blog posts which I also want to display on my HTML home page.
I do not see a need to create a new app as it's not a model which I will be reusing a lot and ready solutions are not to my liking due to limitations.
I have tried to solve what is the problem and I finally realised that it's in the url.py file under urlpatterns.
Here are my code snipets:
project url.py
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
import jobs.views
import blog.views
import compound.views
from django.conf.urls import url, include
from markdownx import urls as markdownx
urlpatterns = [
path('admin/', admin.site.urls),
path('', blog.views.all_blogs_on_home, name='home'),
path('blog/', include('blog.urls')),
path('', include('jobs.urls')),
path('compound/', compound.views.index),
url(r'^markdownx/', include(markdownx))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
blog urls.py
from django.urls import path
from . import views
from . import models
from django.conf.urls import url
urlpatterns = [
path('', views.allblogs, name='allblogs'),
path('<int:blog_title>/', views.detail, name='detail'),
]
This is how I combined 2 apps together before:
blog/views.py :
def all_blogs_on_home(request, template='jobs/home.html'):
context = {
'blogs': Blog.objects.all().order_by('-pub_date'),
'jobs': Job.objects.all(),
'get_email': get_email,
}
return render(request, template, context)
And this what I have for my views (the only way I found to integrate newsletter without creating a new app):
jobs/views.py :
def home(request):
jobs = Job.objects
return render(request, 'jobs/home.html', {'jobs': jobs})
def get_email(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = SignupForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/email-field/')
# if a GET (or any other method) we'll create a blank form
else:
form = SignupForm()
return render(request, 'jobs/home.html', {'form': form})
In home.html I simply add this:
{{ form }}

If I understand it correctly, you want to render two lists of models and a form using all_blogs_on_home view and jobs/home.html template.
To achieve that you should have something like this:
def all_blogs_on_home(request, template='jobs/home.html'):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# Put form handling code here
return HttpResponseRedirect('/email-field/')
# if a GET (or any other method) we'll create a blank form
else:
form = SignupForm()
context = {
'blogs': Blog.objects.all().order_by('-pub_date'),
'jobs': Job.objects.all(),
'form': form,
}
return render(request, template, context)
In your template jobs/home.html just render blogs and jobs as before. And you can use {{ form.as_p }} or {{ form }} to render your form. Don't forget to add /email-field/ url to one of your urls.py files.

Related

Form with post doesn't reach my function in django

I'm stuck with a st*pid question and problem.
I'm working with a form(html) on django, this form will be used to update information on my database regarding the page it's one.
So my problem is : django terminal tell me he receive the post correctly
app_1 | [10/Jan/2023 17:44:50] "GET /nb_database/49/ HTTP/1.1" 200 11810
app_1 | [10/Jan/2023 17:44:54] "POST /nb_database/49/ HTTP/1.1" 200 11810
However , i made a quick function to know my information from the form are coming to the function and here is the problem.
The function never print anything, i supposed the request never reach the function
Here is the function (located on the app named 'nb_database' :
def adding_address_to_db(request):
print("OK REQUETE RECEIVE")
the urls.py (on the same app):
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('nb_database', views.nb_database, name='nb_database'),
path('nb_database/<int:annonce_id>/', views.detail, name='detail'),
path('nb_database/<int:annonce_id>/', views.adding_address_to_db, name='adding_address_to_db'),
]
And here is the form in HTML , for this example let's say it's on page mysite.com/nb_database/49/
<form action="" method="post">
{% csrf_token %}
<input type="text" name="adding_address_to_db" placeholder="Entrez l'adresse" style="color: black;">
</form>
Basically i want to be able to answer the form on the generated page (mysite.com/nb_database/49/) and stay on it once answered.
Any help will be welcome !
Thank's everyone, enjoy your day
You have 2 identical paths in urls.py. When you access mysite.com/nb_database/49/, only the function from the first path runs, not the second.
Remove this line and your function should run:
path('nb_database/<int:annonce_id>/', views.detail, name='detail'),
OK so , i resolved my problem.
As said previously you can't have 2 urls pointing to 2 differents function on view.
I had to use the class Form provided by django.
Working with the post method and the form class i manage to add my function in the function who was generating the page and handle when a post method is send to catch the POST request and execute the code.
Here is a link to Django form documentation :
Django Documentation
And this is the kind of code i have to add to my rendering function :
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})

Calling view name that belongs to a different app

I am trying to a similar task as in this thread here : calling a view when a button is clicked. However, the view name that the button is calling belongs to a different app.
<button class="button table_mgt" >
Table Mgt
</button>
This button sits in a template called dashboard.html which belongs to an app called account. But the view named table_view belongs to another app called table. Both apps belong to the same root.
What do I need to set up for the above code to work?
Update more details:
Here is the error I received:
Request URL: http://127.0.0.1:8000/table/tables/
Django Version: 3.0.7
Exception Type: TemplateDoesNotExist
Exception Value: table_view.html
In my table app:
File urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('tables/', views.table_view, name='table_view'),
]
File view.py
from django.shortcuts import render
from .models import Table
def table_view(request):
table_num = Table.objects.count()
return render(request,
'table_view.html',
{'table_num': table_num})
The template table_view.html sits in this folder \table\templates\table\
File urls.py of the project root:
from django.urls import path, include
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('account/', include('account.urls')),
path('table/', include('table.urls')),
]
In my root project, there is also a folder \templates where I keep the base.html for all apps to use.
If both apps belong to the same project, you do not need to change anything. The fact that these belong to different apps doesn't matter.
If you however have an app_name in the urls.py of the table_view, you need to prefix it with the namespace. For example if the urls.py where the table_view is defined looks like:
# account/urls.py
app_name = 'account'
urlpatterns = [
# …,
path('some-path', table_view, name='table_view')
]
then you prefix it with the app_name in the urls.py:
<button class="button table_mgt" >
Table Mgt
</button>
The same happens when you defined a namespace=… when you included the urls, for example:
# urls.py
urlpatterns = [
# …,
path('', include('account.urls', namespace='account')),
]
For more information, see the URL namespaces section of the documentation.
The template table_view.html sits in this folder \table\templates\table\.
Then the name of the template is table/table_view.html, so:
def table_view(request):
table_num = Table.objects.count()
return render(
request,
'table/table_view.html',
{'table_num': table_num}
)
With the default configuration, Django will see all the templates directories of all apps as "roots", so, the roots are:
app1/templates/
app2/templates/
&vellip;
appn/templates/
you defined in the templates directory an extra directory tables, so that means that in order to access the table_view.html, the path relative to the root is tables/table_view.html.

SQLite django download not showing file

I am having trouble downloading a file from my sqlite database using django.
I have created a db model. i then went into my django admin and uploaded the file.
Then in the index.html I set a download link. However when i press the download link my page just seems to refresh and nothing downloads. The app i have created is called chartsapp. maybe it is something to do with my line of code {{ chartsapp.the_file.url }}. i have played around with it trying the_file.url but that didn't seem to do anything either. any advice?
MODELS.PY
from django.db import models
class Datahere(models.Model):
text = models.FileField(upload_to='Uploaded')
ADMIN.PY
from django.contrib import admin
from .models import Datahere
admin.site.register(Datahere)
INDEX.HTML
Download the file
URLS.PY
urlpatterns = [
path('', views.index, name="index"),
]
VIEWS.PY
from django.shortcuts import render
from .models import Datahere
def index(request):
model = Datahere
return render(request, "index.html", {})
Well I am still a beginner at django , but if you want your url working , you must add the url to urls.py file , then editing in views.py .
I hope this will help .
First of all you don't download a file from your sqlite database. Instead your model saves any file/image/etc. to MEDIA_ROOT/Uploaded with MEDIA_ROOT defined in your settings.py like so:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
The database itself doesn't store media files (and static) at all. It just stores the location of the file as path relative to MEDIA_ROOT.
So to render the link to the file in your template as desired, you can go ahead like so:
{% load static %}
<body data-media-url="{% get_media_prefix as MEDIA_PREFIX %}">
<img src="{{ MEDIA_PREFIX }}images/your_image.png">
or
Download the file
As long as in development, you will also need to add the urls to yoururls.py like so:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Also you should consider to rename your Model field into something different than text when storing files, for me it is quiet misleading and uncertain.
For further reference about FileField and ImageField check out the official documentation.

How to implement two QuerySets in .html

I'm new to Django and trying to understand how it works.
Basically, I'm building this simple Blog and I have one Question regarding the implementation of the QuerySets in my .html file.
This is how my code looks like:
Models.py
class Post(models.Model):
[...]
class Highlight(models.Model):
[...]
Views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post
from .models import Highlight
def post_list(request):
posts = Post.objects.all
return render(request, 'blog/post_list.html', {'posts': posts})
def highlight_list(request):
highlights = Highlight.objects.all
return render(request, 'blog/post_list.html', {'highlights': highlights})
Urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('', views.highlight_list, name='highlight_list'),
]
post_list.html
{% for post in posts %}
{{ post }}
{% endfor %}
{% for highlight in highlights %}
{{ highlight }}
{% endfor %}
The problem is, it only shows the objects from the class Post.
Is it somehow possible to include both QuerySets from both classes?
If yes, what am I doing wrong?
Thank you!
There is so many approaches to achieve this. I mention one
def post_list(request):
posts = Post.objects.all()
highlights = Highlight.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts, 'highlights':highlights})
Then you can access both highlights and posts in post_list.html
When you're hitting the url 127.0.0.1:8000, the first url that is getting matched is path('', views.post_list, name='post_list') this one because in your urls.py this is your first url. When there's a multiple match, always the first one will always be called.
Therefore, the view function, that is getting called is the post_list.
In your post_list you are only retrieving Post objects and that's why when you're returning to your html only the post objects are getting rendered and there are no highlight objects.
That's why you can't find any highlight objects in your front end.
You can do the following:
def post_response_with_highlight(request):
posts = Post.objects.all
highlights = Highlight.objects.all
context = {
'posts': posts,
'highlights': highlights
}
return render(request, 'blog/post_list.html', {'context': context})
And now in your 'html' you can get both the posts and the highlights
Already managed it, thanks!
If anyone else has the problem, here is the solution:
Views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post
from .models import Highlight
def post_list(request):
posts = Post.objects.all
highlights = Highlight.objects.all
return render(request, 'blog/post_list.html', {'posts': posts, 'highlights': highlights})

How to create a link between two html files in local server using django

I have a project "something". In something/shop/templates/shop I have HTML files.
I want to have a link between 'main' and 'about' html files, but I do not know how. I tried to do it as in usual HTML file, but it is not working.
About
Also I tried this way, but it is not working too.
About
It is in urls.py:
urlpatterns = [
path('', views.main, name='main'),
path('about/', views.about, name='about'),]
views.py:
def main(request):
return render(request, 'shop/main.html')
def about(request):
return render(request, 'shop/about.html')
What should I write to get a normal link between them?