I have a really weird problem. my index page shows image. There isn't any error, codes are here:
def index(request):
post = Post.objects.get(id=1)
return render_to_response("index.html", {"post":post}, context_instance=RequestContext(request))
but my detail page doesnt display image. codes here:
class PostDetailView(DetailView):
context_object_name = "post"
model = Post
template_name = "post_detail.html"
def get(self, request, *args, **kwargs):
self.next = self.request.get_full_path()
return super(PostDetailView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
context["form"] = CommentForm()
context["next"] = self.next
context["object_id"] = context['post'].id
context["comments"] = Comment.objects.filter(
content_type=ContentType.objects.get_for_model(self.model),
object_id=context['post'].id, is_published=True)
return context
my post_detail.html page:
{{ post.title }} -----here ok!
{{ post.content }} ------here ok!
<div class="img">
{% if post.image %}
<img src="media/{{post.image_thumb}}" /> -----but here not ok.Why?
{% endif %}
</div>
my index.html
{{ post.title }}
{{ post.content }}
<div class="img">
{% if post.image %}
<img src="media/{{post.image_thumb}}" />
{% endif %}
</div>
So what is my problem, thanks for time.
firstly,make sure you have set the media dir in file settings.py conrrectly and then change your image url to:
<img src="/media/{{post.image_thumb}}" />
you missing a slash
You should use {{ post.image_thumb.url }} instead of {{ post.image_thumb }}.
{{ post.image_thumb }} implicitly calls __unicode__ method of post, but what you want is the url attribute of image, you can get the absolute url of image with this.
Related
I need to iterate through a list of checkboxes and add a link to each of them. However I am not able to do so.
The template shows the complete form as a link istead of an individual checkbox being a list.
Below given is my code:
Here is my forms.py:
class GetTaskDescription(forms.Form):
get_tasks = forms.ModelMultipleChoiceField(
queryset=Task.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=True
)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(GetTaskDescription, self).__init__(*args, **kwargs)
self.fields['get_tasks'].queryset = self.user.task_set.all()
def get_task_description(self):
tasks = self.cleaned_data['get_tasks']
return tasks
Here is my html:
{% extends 'todoapp/base.html' %}
{% block title %}Select a Task{% endblock %}
{% block content %}
<h2>Select tasks to view description</h2>
<form method="get" action="{% url 'view_task_description' %}" name="view_task_description">
{% for tasks in view_tasks %}
{{ tasks }}
{% endfor %}
<br/>
<input type="submit" value="View Description">
<button onclick="location.href='{%url 'dashboard' %}?name=Go back'" type="button">Go back</button>
</form>
{% endblock %}
Here is my views.py:
#login_required(login_url='/login/')
def view_task_description(request):
task_description = GetTaskDescription(data=request.GET, user=request.user)
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
print obj
return render(request, 'todoapp/task_desc.html', context={'description': obj})
return render(request, 'todoapp/select_task_description.html', context={'view_tasks': GetTaskDescription(user=request.user)})
You're trying to iterate over a form instance:
'view_tasks': GetTaskDescription(user=request.user)
{% for tasks in view_tasks %}
To access field choices you should use view_tasks.fields.get_tasks.choices in template.
I am trying to display data from a model inside my post.html which worked before but now dosen't for some reason I can't figure out.
urls.py
urlpatterns = [
path('', ListView.as_view(
queryset=Tutorials.objects.all().order_by("-date")[:25],
template_name="tutorials/blog.html"
)),
path('<int:pk>', DetailView.as_view(
model=Tutorials,
template_name="tutorials/post.html")),
]
blog.html
{% block python %}
{% for Tutorials in object_list %}
{% if Tutorials.categories == "pythonbasics" %}
<h1>{{ Tutorials.title }}</h1>
<br>
Created On : {{ Tutorials.date|date:"Y-m-d" }}
{% endif %}
{% endfor %}
{% endblock %}
post.html
{% block content %}
<h3>{{ Tutorials.title }}</h3>
<h6> on {{ Tutorials.datetime }}</h6>
<div class = "code">
{{ Tutorials.content|linebreaks }}
</div>
{% endblock %}
You should use object name in template:
{% block content %}
<h3>{{ object.title }}</h3>
<h6> on {{ object.datetime }}</h6>
<div class = "code">
{{ object.content|linebreaks }}
</div>
{% endblock %}
Or if you want to use Tutorial variable, you need to pass context_object_name=Tutorials to the view:
path('<int:pk>', DetailView.as_view(
model=Tutorials,
template_name="tutorials/post.html",
context_object_name='Tutorials')),
plus for #neverwalkaloner's answer.
The reason why you can use object or context_object_name is cause you inherit DetailView.
In DetailView, it has get_object() method.
def get_object(self, queryset=None):
"""
Return the object the view is displaying.
Require `self.queryset` and a `pk` or `slug` argument in the URLconf.
Subclasses can override this to return any object.
"""
# Use a custom queryset if provided; this is required for subclasses
# like DateDetailView
if queryset is None:
queryset = self.get_queryset()
# Next, try looking up by primary key.
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
if pk is not None:
queryset = queryset.filter(pk=pk)
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
# If none of those are defined, it's an error.
if pk is None and slug is None:
raise AttributeError("Generic detail view %s must be called with "
"either an object pk or a slug."
% self.__class__.__name__)
try:
# Get the single item from the filtered queryset
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
return obj
It will return model object, and also you can override this method.
And in get() method in DetailView,
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
As you see, it define self.object to self.get_object() so you can use self.object inside DetailView.
Finally, you can use object in your template because of get_context_data().
DetailView basically add 'object' to context, so you can use it.
def get_context_data(self, **kwargs):
"""Insert the single object into the context dict."""
context = {}
if self.object:
context['object'] = self.object
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
context[context_object_name] = self.object
context.update(kwargs)
return super().get_context_data(**context)
It's true that CBV has little bit learning curve, but when you see django source code and read about docs, it's easy to follow.
+I highly recommend ccbv.co.kr - you can see which view and mixin that CBV inherit, and it's methods too.
{% block content %}
{{ object.title }}
<h6> on {{ object.datetime }}</h6>
<div class = "code">
{{ object.content|linebreak }}
</div>
{% endblock %}
Not sure what I did wrong. I'm making a commenting system that users can post comment on a post and be able to reply to that comment. Every thing works fine except when user reply to some comment that reply is being shown as a single comment.(and the it's shown as a reply as well) so if I reply to comment "how are you" with a message "good", then I have created two "good". one as the reply. one as the single comment. I've looked around my code, but I have no idea why this is happening. Any help would be highly appreciated. Thank you/.Here's my code.
views.py
def post(request, slug):
user = get_object_or_404(User,username__iexact=request.user)
try:
profile = MyProfile.objects.get(user_id=request.user.id)
# if it's a OneToOne field, you can do:
# profile = request.user.myprofile
except MyProfile.DoesNotExist:
profile = None
post = get_object_or_404(Post, slug=slug)
post.views += 1 # increment the number of views
post.save() # and save it
path = request.get_full_path()
comments = Comment.objects.filter(path=path)
#comments = post.comment_set.all()
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
parent_id = request.POST.get('parent_id')
parent_comment = None
if parent_id is not None:
try:
parent_comment = Comment.objects.get(id=parent_id)
except:
parent_comment = None
comment_text = comment_form.cleaned_data['comment']
new_comment = Comment.objects.create_comment(
user=MyProfile.objects.get(user=request.user),
path=request.get_full_path(),
text=comment_text,
post = post,
parent = parent_comment
)
comment_form = CommentForm()
return HttpResponseRedirect(post.get_absolute_url())
for c in comments:
c.get_children()
context_dict = {
'post' :post,
'profile' :profile,
'comments' : comments,
'comment_form':comment_form
}
return render(request, 'main/post.html', context_dict)
models.py
class Comment(models.Model):
def get_children(self):
if self.is_child:
return None
else:
return Comment.objects.filter(parent=self)
post.html
<h1>Comments/Questions</h1>
<form method="POST" action=''>{% csrf_token %}
{{ comment_form.as_p }}
<input type='submit' class='btn btn-default' value='Add comment'/>
</form>
<br/>
<hr/>
<table class='table'>
{% for comment in comments %}
<tr><td>{{ comment.get_comment }}
<br/><small>via {{ comment.user }} | {{ comment.timestamp|timesince }} ago </small>
{% if not comment.is_child %}
<ul>
{% for child in comment.get_children %}
<li>{{ child.get_comment }}
<small>via {{ child.user }}</small>
</li>
{% endfor %}
</ul>
<a href='#' class='reply_btn'>Reply</a>
<div class='reply_comment'>
<form method="POST" action=''>{% csrf_token %}
<input type='hidden' name='parent_id' value='{{ comment.id }}' />
{{ comment_form.as_p }}
<input type='submit' class='btn btn-default' value='Add reply'/>
</form>
</div>
{% endif %}
</td></tr>
{% endfor %}
</table>
</div>
And the comment is displayed in post.html and for that page, view is
def post(request, slug):
user = get_object_or_404(User,username__iexact=request.user)
try:
profile = MyProfile.objects.get(user_id=request.user.id)
# if it's a OneToOne field, you can do:
# profile = request.user.myprofile
except MyProfile.DoesNotExist:
profile = None
post = get_object_or_404(Post, slug=slug)
post.views += 1 # increment the number of views
post.save() # and save it
path = request.get_full_path()
comments = Comment.objects.filter(path=path)
#comments = post.comment_set.all()
comment_form = CommentForm(request.POST or None)
for c in comments:
c.get_children()
context_dict = {
'post' :post,
'profile' :profile,
'comments' : comments,
'comment_form':comment_form
}
return render(request, 'main/post.html', context_dict)
The duplicate comments are just a result of your template.
It is happening because when you loop through all comments, the newly made comment is included in the comments too.
Besides acting as a comment child, it is also a comment object and that is why it is included in commments when you filter() comments with a supplied path and then it is rendered in template as a normal comment object.
For fixing this, you need to use recursive tree. There are available django apps like django-mptt which comes handy in this type of issues.
After integration it into your comments model, you can simply use the {% recursetree %} templatetag to render comments without duplication.
I am trying to get AreYouAHuman capcha on my website,
I mostly got it working the problem is nothing shows up.
this is part of the render'd html
<label for="id_session_secret">Are You Human</label>
<br>
<div id="AYAH"></div><script type="text/javascript" src="https://ws.areyouahuman.com/ws/script/87e31f12336132203bdde2da8c93269fccdd5f52"></script>
<p></p>
and this is what i see in the browser
> Are You Human <div id="AYAH"></div><script type="text/javascript"
> src="https://ws.areyouahuman.com/ws/script/87e31f12336132203bdde2da8c93269fccdd5f52"></script>
This is my Implementation
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# turtle.forms.py
#
# Copyright 2013 Brian Scott Carpenter <talisman#talisman-Pangolin-Performance>
from django import forms
from django.conf import settings
import ayah
ayah.configure(
settings.AREYOUHUMAN_PUBLISHER_KEY,
settings.AREYOUHUMAN_SCORING_KEY,
)
from django.forms import Field, ValidationError, Form
from django.forms.widgets import Widget
#Create a wdiget that renders the AreYouHuman html
class AreYouHumanWidget(Widget):
def render(self, name, value, attrs=None):
return ayah.get_publisher_html()
#AreYouHuman uses a test field (session_secret) for validation
class AreYouHumanField(Field):
#Use the AreYouHuman HTML
widget = AreYouHumanWidget
#Validate agianst AreYouHuman
def validate(self, value):
if not ayah.score_result(value):
raise ValidationError("You may not be human.")
class Turtle_Form(forms.ModelForm):
''' This is code to make sure the User automatically saves the
user to the database in context.
'''
session_secret = AreYouHumanField(label="Are You Human")
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(Turtle_Form, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
return obj #<--- Return saved object to caller.
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(Turtle_Form, self).__init__(*args, **kwargs)
the template looks like
{% extends "base.html" %}
{% load i18n zinnia_tags %}
{% load url from future %}
{% block title %}tempilo.org{% endblock %}
{% block content %}
<form action="" method="post">{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}
<br>
{{ field | safe }}
<p></p>
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
{% endblock %}
You might need to wrap the call to ayah.get_publisher_html() in the widget render method with a call to django.utils.safestring.mark_safe() to prevent it being autoescaped.
I wrote a simple app that is a custom DateField widget for mezzanine. Afaik it's, it's a simple case and besides overextending a template it would be the same in pure django or django-cms (feel free to correct me if I'm wrong).
The widget:
class DatePickerInput(forms.DateInput):
def __init__(self, attrs = None, format = None):
super(DatePickerInput, self).__init__(attrs, format)
self.attrs["class"] = "datepicker"
class Media:
css = { "all": ('css/ui-lightness/jquery-ui-1.10.3.custom.min.css',) }
js = (
"mezzanine/js/" + getattr(settings, "JQUERY_UI_FILENAME", "jquery-ui-1.9.1.custom.min.js"),
"js/datepicker_setup.js",)
I overextend base.html template to insert form.media:
{% overextends "base.html" %}
{% load pages_tags mezzanine_tags i18n future staticfiles %}
{% block extra_head %}{{ block.super }}
{{ form.media }}
{% endblock %}
Now, I create a form for my model class.
Here's the class:
class PlayerProfile(models.Model):
user = models.OneToOneField("auth.User")
# Can be later changed to use a setting variable instead of a fixed date
date_of_birth = models.DateField(default=date(1990, 1, 1))
Here's the model form:
from DateWidgets.widgets import DatePickerInput
from PlayerProfiles.models import PlayerProfile
class EditPlayerProfileForm(Html5Mixin, forms.ModelForm):
class Meta:
model = PlayerProfile
fields = ("date_of_birth", )
widgets = { 'date_of_birth': DatePickerInput }
def __init__(self, *args, **kwargs):
super(EditPlayerProfileForm, self).__init__(*args, **kwargs)
Here's the view:
#login_required
def profile_update(request, template="accounts/account_profile_update.html"):
"""
Profile update form.
"""
pform = forms.EditPlayerProfileForm
player_form = pform(request.POST or None, request.FILES or None, instance=request.user.playerprofile)
context = {"pform": player_form, "title": _("Update Profile"), "profile_user": request.user}
return render(request, template, context)
Here's the template:
{% overextends "accounts/account_profile_update.html" %}
{% load i18n mezzanine_tags %}
{% block main %}
<fieldset>
<legend>{{ title }}</legend>
<form method="post"{% if pform.is_multipart %} enctype="multipart/form-data"{% endif %}>
{% fields_for pform %}
<div class="form-actions">
<input class="btn btn-primary btn-large" type="submit" value="{{ title }}">
</div>
</form>
</fieldset>
{% endblock %}
Now if I view the form in a browser, the custom widget is there (I can tell because the input html tag has my custom class attribute value) but it doesn't inject the form media, it's missing. Any idea what's going on here? Thanks in advance! Cheers :-)
form isn't available in the template, because you've called your form variable pform.
Try {{ pform.media }}.
I was googled here with the same problem under different conditions and spotted another error that may appear under other conditions (my case is extending change_form.html in Django 2.1): I had to use extrahead instead of extra_head
{% block extrahead %}{{ block.super }}
{{ form.media }}
{% endblock %}