I am super new to python programming and django and i got the basics out of the way. I created a project with two apps, home and video. In my video models.py i have the following data:
class Video(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(blank=True, null=True)
I want to do something with this in my home app in the views.py, such as display the data in an html page and currently it is set up as followed:
from video.models import Video
def display_video(request):
video_list = Video.objects.all()
context = {'video_list': video_list}
return render(request, 'home/home.html', context)
in my home.html
{% if video_list %}
{% for video in video_list %}
<p>{{ video.name }}</p>
<p>{{ video.description }}</p>
{% endfor %}
{% else %}
<p>no videos to display</p>
{% endif %}
my home.html always returns "no videos to display"
But when i query Video.objects.all() in my video app it finds 2 objects. any help is appreciated.
I decided to delete the project and started over brand new but this time I used class views instead of function views. I'm not exactly sure why it didn't run but using class views it worked like a charm. So the equivalent in class views as simple as possible is.
from video.models import Video
class IndexView(generic.ListView):
template_name = 'home/index.html'
context_object_name = 'top_three'
def get_queryset(self):
return Video.objects.all()[:3]
In settings, check the following is there.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
It worked for me without using class. I just did what we normally do.
from django.shortcuts import render
from AllBlogs.models import Post # getting this post form AllBlogs app
# Create your views here.
def home (request):
# sort posts according to date in descending order
# only a single query is generated and then hit the database that's how this will not affect the performance of database
latest_blogs = Post.objects.all().order_by("-date")[:3]
return render(request,'Home/home.html',{'blog':latest_blogs})
And this is my template
<!--separated it from the home.html because we can use it in AllBlogs.html
and it save our work and time by just including without copying the same data several times-->
{% load static %}
<li>
<!--add field name which we used in models-->
<article class="blog">
<a href="{% url 'blogDetails_page' blog.slug %}"> <!--Different slug for different blog as slug will create a different url-->
<!--dtl filter to add back or url dynamic url creation-->
<image src="{% static 'images/'|add:blog.image_name %}" alt="{{blog.title}}">
<div class="blog__content">
<h3>{{blog.title}}</h3>
<p>{{blog.excerpt}}</P>
</div>
</a>
</article>
</li>
And this is the Post model
# having post data
class Post(models.Model):
title = models.CharField(max_length=150)
date = models.DateField(auto_now=True) # put the date in the field at which time we are saving the data
image_name = models.CharField(max_length=50) # later on we upload files right now we get images from static folder
excerpt = models.CharField(max_length=200)
content = models.TextField(validators=[MinLengthValidator(10)]) # TextFields same like CharField
slug = models.SlugField(unique=True, db_index=True) # set it as unique because we are going to use it as a primary key
author = models.ForeignKey(Author,on_delete=models.SET_NULL,related_name='posts',null=True) # one to many relation
tags = models.ManyToManyField(Tag) # ManyToManyRelation with tag
# represent post entry by it post title
def __str__(self):
return self.title
Related
based on multiple choice field i want to show result in template but I have no idea how to do as you can see in this model i give lunch choice to students base on lunch choice i want to show result but it is not working for ex if he select sandwich the result after submit will you sandwich will be ready and same for others
from multiselectfield import MultiSelectField
class student(models.Model):
lunch_choice = [
('Sandwich', 'Sandwich'),
('Salad', 'Salad'),
('omlete', 'omlete'),
]
name = models.CharField(max_length=70, blank=False)
classs = models.CharField(max_length70, blank=True)
lunch = MultiSelectField(choices=lunch_choice, blank=True)
def __str__(self):
return self.name
i tried in my HTML and it didn't work
{% if student.classs %}
{% if student.lunch == 'Sandwich' %}
<p> your sandwich will be ready</p>
{% endif %}
{%endif%}
and in form.py using widget
widgets = {
'lunch':forms.CheckboxSelectMultiple(attrs={'id':'lunch'}),
}
my views.py
def preview(request):
student = student.objects.all()
return render(request, 'preview.html',{'student':student})
OP can create a model for lunches (it would enable to create new lunches, edit and delete). Then, in the Student model create a lunch with a ManyToManyField, like
lunch = models.ManyToManyField(Lunch, blank=True)
Note the usage of blank=True to not require the field in the forms.
Then, when one generates a form based on that model, it'll create an experience just like the one in Django Admin where one can select multiple ones.
One can then show it to the user in a template.
If one doesn't like the experience of the form and want to make it more user friendly, there are some articles out there explaining that
Django Forms for Many-to-Many Fields
How To Add Tags To Your Blog (A Django ManyToManyField Example)
acc to me there is no such way by which u can show the result base on selected option because i also tried to use that and look for answers on internet but didn't find anything and creator of that repo is also not responding although I would recommend you to use models many to many field It will allow user to select more than one option like multiselectfield like this
first, create models
class Lunch(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
then add this in student models
lunch = models.ManyToManyField(Lunch, blank=True, related_name="lunch")
then add your option in lunch model
and it in your template to show result base on selected option
{% if student.classs %}
{% for Lunch in student.lunch.all %}
{% if Lunch.title == 'Sandwich' %}
<p> your sandwich will be ready</p>
{% endif %}
{% endfor %}
{%endif%}
it will work
This happens because the string is being compared to type: type(aaa[0].lunch) <class 'multiselectfield.db.fields.MSFList'>. Printed the data type 'type(aaa[0].lunch)' of the first value from the database in the view. Used stringformat:'s' to convert data to string in template. Here you can read about the conversion:
conversion
transformation type:
replace 'samplesite' with the name of your application.
urls.py
urlpatterns = [
path("Test/", Test, name = 'Test'),
]
views.py
def Test(request):
aaa = student.objects.all()
print('type(aaa[0].lunch)', type(aaa[0].lunch))
context = {'fff': aaa}
return render(request, 'samplesite/lunch.html', context)
lunch.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
{% for aa in fff %}
{% if aa.lunch|stringformat:'s' == 'Sandwich' %}
<p>{{aa.lunch}}</p>
<p>{{aa.name}}</p>
{% endif %}
{% endfor %}
</body>
</html>
settings in settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
django version 4.1
I've posted something similar earlier without being able to find a suitable solution. One of the things I am struggling with is the ability to serve static path / file references within DJANGO html templates. Hopefully, by posting another question I will be able to understand how this works. Done quite some research and read through the DJANGO documentation without being able to find something covering my scenario.
Here we go:
Within my model I use a path reference field
class Product_images(models.Model):
product = models.ForeignKey(Products, on_delete=models.SET_NULL, blank=True, null=True)
path_to_image = models.CharField(max_length=150,null=True, blank=True)
name = models.CharField(max_length=50,unique=False,blank=True)
class Meta:
verbose_name = 'Product Image'
verbose_name_plural = 'Product Images'
def __str__(self):
return '{} - {} - {}'.format(self.pk, self.product, self.name)
The value of this field is set to (example):
static\images\Product\PowerBI\Receivables\Receivables 6.png
The files are physically stored within the app Main/static/....
My setting file contains:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
MEDIA_ROOT = os.path.join(BASE_DIR, 'Main/')
MEDIA_URL = '/Main/'
Then I have two templates within the app where I want to serve these images. One page uses a custom context processor in the following way:
{{ product_section }}
Which returns html including:
html_value += u'<img class="d-block w-100" src="{}" width="400px" height="250x" alt="{}">'.format(productimages_obj.path_to_image,productimages_obj.name)
This context processor tag is used within a template returned by the products_view view function.
Now, I want to use the same images within another view gallery_view:
def gallery_view(request, requestid, *arg, **kwargs):
productimages = Product_images.objects.filter(product=requestid)
if productimages.exists() != True:
return HttpResponseNotFound('<h1>Page not found</h1>')
context = {
'productimages': productimages
}
return render(request, "gallery.html", context)
When using the following template tag {{ productimages.path_to_image }} I am getting 404 "GET /Gallery/static/images/Product/PowerBI/Finance/Finance%207.png HTTP/1.1" 404 3485.
The template is coded as following:
<section id="gallery" class="bg-light">
<div class="container-fluid">
<div class="row">
{% for productimages in productimages %}
<div class="col-md">
<img src="{{ productimages.path_to_image }}" onclick="openModal();currentSlide({{ forloop.counter }})" class="hover-shadow">
</div>
{% endfor %}
</div>
</div>
Last but not least Urls.py:
urlpatterns = [
path('', views.home_view, name='home'),
path('Home', views.home_view, name='home'),
path('PowerBI', views.products_view, name='power bi'),
path('Services', views.services_view, name='services'),
path('About', views.about_view, name='about'),
path('Contact', views.contact_view, name='contact'),
path('Gallery/<int:requestid>', views.gallery_view, name='gallery'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
What mistake am I making here? Why does the GET include /Gallery/ within the URL? How do I circumvent this?
Thanks everyone.
I would set an image field and in the templates I would use its URL property:
models.py:
image = models.ImageField(null=True, blank=True)
.html file:
<img src="{{object.image.url}}" alt="" class="img-fluid">
I am trying to create a Django web app that accepts text in a form/textbox, processes it and redirects to a webpage showing the processed text . I have written a half-functioning app and find de-bugging quite challenging because I don't understand most of what I've done. I'm hoping you will help me understand a few concepts, Linking to resources, also appreciated.
Consider this simple model:
class ThanksModel(models.Model):
thanks_text = models.CharField(max_length=200)
Is the only way to set the text of thanks_text through the manage.py shell? This feels like a pain if I just have one piece of text that I want to display. If I want to display a webpage that just says 'hi', do I still need to create a model?
Consider the view and template below:
views.py
class TestView(generic.FormView):
template_name = 'vader/test.html'
form_class = TestForm
success_url = '/thanks/'
test.html
<form action = "{% url 'vader:thanks'%}" method="post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit">
</form>
I need to create another model, view and html template and update urls.py for '/thanks/' in order for the success_url to redirect correctly? (That's what I've done.) Do I need to use reverse() or reverse_lazy() the success_url in this situation?
Models are used when you are dealing with Objects and Data and DataBases that can contain a lot of information.
For Example A Person would be a model. their attributes would be age, name, nationality etc.
models.py
class Person(models.Model):
Name = models.CharField(max_length=50)
age = models.IntegerField()
nationality = models.CharField(max_length=50)
Thi deals with multiple bits of information for one object. (the object being the person)
A Thank you message would not need this? so scrap the model for the thank you message. just have views where you create the view using a templates and setting the view to a url.
views.py
class TestView(generic.FormView):
template_name = 'vader/test.html' # self explantory
form_class = TestForm # grabs the test form object
success_url = reverse_lazy('vader:thanks') # this makes sure you can use the name of the url instead of the path
def ThanksView(request): # its simple so you don't even need a class base view. a function view will do just fine.
return render(request,"thanks.html")
test.html
<form action = "{% url 'vader:thanks'%}" method="post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit">
</form>
thanks.html
<h1>Thank you for Submitting</h1>
<h2> Come Again </h2>
url.py
from django.urls import path
from djangoapp5 import views
urlpatterns = [
path('', TestView.as_view(), name='test_form'),
path('thanks/', views.ThanksView, name='vader:thanks'),
]
I haven't tested this but hopefully it helps and guide you in the right direction
I have a model that stores a PDF file. On the DetailView of that Model I would like to have a link to view the PDF in a new tab. There are similar questions on here that I've used to get this far, but it looks like they're for local PDFs. My PDFs are stored as Media on AWS.
This is what I have right now:
plans/models.py
class PlanSet(PlanModel):
...
class PlanSetPDF(models.Model):
planset = models.ForeignKey(PlanSet)
PDF = models.FileField(upload_to='planPDFs')
created = models.DateField(auto_now_add=True)
added_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
plans/views.py
class PlanSetDetailView(DetailView):
model = PlanSet
template_name = "plan_detail.html"
def get_context_data(self, **kwargs):
context = super(PlanSetDetailView, self).get_context_data(**kwargs)
context['now'] = timezone.now()
return context
def view_pdf(request, pk):
pdf = get_object_or_404(PlanSetPDF, pk=pk)
image_data = open(pdf.PDF.url, "rb").read()
return HttpResponse(image_data, contenttype='application/pdf')
plans/urls.py
urlpatterns = [
url(r'^(?P<pk>\d+)/$', plan_detail, name='detail'),
url(r'^(?P<pk>\d+)/pdf/$', view_pdf, name='view_pdf'),
]
urls.py:
url(r'^plans/', include(plan_sets.urls, namespace='plans')),
template:
{% for pdf in object.plansetpdf_set.all %}
<a href="{% url 'plans:view_pdf' pdf.pk %}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>PDF</a>
{% endfor %}
I'm recieving a builtin.OSError:[Errno 22] Invalid Argument: 'https://link_to_PDF_file_on_amazon'
It looks like Python can't open the file. I've looked around and I can't find any answers. Can one of you show me where I'm going wrong? Thanks.
I can't see the point of your view_pdf view at all. All it does is open the PDF via its URL, download it, and then re-send it to the browser. Why bother? You should just link directly to the PDF's url; and when you do so you can tell the browser to open it in a new tab:
<a href="{{ pdf.PDF.url }}" target="_new">
I'm just trying to list my blog posts for a certain month in a certain year, but none of my posts are showing. When I type in the correct url: 2011/nov, no posts show up and I have Nov. 2011 posts saved in my admin.
Also, for some reason, my css file isn't being taken into account. When I go to the url, 2011/nov, I just get html with no styling and none of my posts. What am I doing wrong here?
#models.py
class Post(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=120, unique = True)
body = models.TextField()
published = models.DateTimeField(default=datetime.now)
categories = models.ManyToManyField(Category)
def __unicode__(self):
return self.title
#urls.py
info_dict = {
'queryset': Post.objects.all(),
'date_field': 'published',
}
urlpatterns = patterns('',
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
date_based.archive_month,
dict(info_dict, template_name='blog/archive.html',)),
#blog/archive.html
<link href="../static/style.css" rel="stylesheet" type="text/css" media="screen" />
.
.
.
{% for post in post_list %}
<h3 class="title">{{post.title}}
</h3>
{% endfor %}
The CSS is not showing because you define it relatively to be ../static/style.css. When the address is /2011/jan the browser tries to get the css from /2011/static/style.css. Fix: Set the path to be absolute: /static/style.css.
You should be looping through object called object_list instead of post_list.
{% for post in object_list %}
The context variable that holds the post is called object_list not post_list so you should have:
{% for post in object_list %}
...
{% endfor %}
https://docs.djangoproject.com/en/dev/ref/generic-views/?from=olddocs#django-views-generic-date-based-archive-month
Your css file should be:
and if you are developing locally you need to set up the development server to server your media for you:
https://docs.djangoproject.com/en/dev/howto/static-files/#using-django-contrib-staticfiles
In addition to what pastylegs wrote above, you should also change this line
published = models.DateTimeField(default=datetime.now)
to this:
published = models.DateTimeField(auto_now_add=True)
In Python, named arguments are only evaluated once. This means that the default published value is the time your server last compiled the models.py file. Django offers a solution to this: setting the parameter auto_now_add=True, makes django use the actual current time for the field, when it's first created. Similarly, setting auto_now=True makes django set the current time for the field whenever it's saved.