i'm a beginner in Django and i have a problem ….
I created an application(name :PQR) with 3 models (Patient / Question / Reply)
I want to see a views with the name of the patient at the top, under this, all questions availables and if applicable, the answers next to the question (some patient may have empty reply / no reply).
I know how to display the answers for a patient but I would like to display EVERY questions and if available, I want to provide the reply but I don't know how to write this in my view?
This is my model :
Class Patient(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
def listReply(self):
replies = Reply.objects.filter(patient= self.id)
return replies
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question_text
class Reply(models.Model):
question = models.ForeignKey(Question)
patient = models.ForeignKey(Patient)
reply_text = models.CharField(max_length=200)
def __unicode__(self):
return str(self.reply_text)
This is my view :
from django.shortcuts import render, get_object_or_404
from django.template import RequestContext
from .models import Patient, Question, Reply
def list(request):
list_patient = Patient.objects.order_by('name') context = RequestContext(request, {'list_patient':list_patient,'welcome': 'Welcome on my page Django !',
})
return render(request, 'PQR/list.html', context)
def detail(request, patient_id):
patient = get_object_or_404(Patient, pk=patient_id)
list_question = Question.objects.all()
Replies4MyPatient = Reply.objects.filter(patient=patient_id)
return render(request, 'PQR/detail.html', locals())
And this is my urls :
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.list, name ='list_patient'),
url(r'^(?P<patient_id>[0-9]+)/patient/$', views.detail, name ='detail_patient'),
And this is my template :
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'Forum/style.css' %}" />
<div>
<h1>Patient details : {{ patient }}</h1>
</div>
<fieldset>
{% csrf_token %}
{% for reply in Replies4MyPatient %}
</br><abcd>{{ reply.question }}</abcd></br>
</br>
<li>{{ reply }}</li>
{% endfor %}
</fieldset></br>
<a href="{% url 'list_patient' %}"/> <input type="button" value="Look Back"/>
Thanks you for your help !
The function render builds the html to return with a template and a context. In your template PQR/detail.html, you use {{ patient }} and Replies4MyPatient. You need to build a context with these values and to pass it to render
def detail(request, patient_id):
patient = get_object_or_404(Patient, pk=patient_id)
list_question = Question.objects.all()
Replies4MyPatient = Reply.objects.filter(patient=patient_id)
context = {'patient' : patient, 'Replies4MyPatient' : Replies4MyPatient}
return render(request, 'PQR/detail.html', context=context)
Related
I'm learning Django and I am currently building blog app. I have a problem. I built functionalities to add new posts and to comment to new posts. Now I struggle with creating the possibility to delete comments by users.
I assigned an id (primary key) of given comment to button "delete" which is present in all comments fields in purpose to know which comment I want to delete. But now I don't know how to access to this HTML elements in backend and fetch this id's.
Part of my html file:
{% for comment in comments %}
{% if comment.post == object %}
<div class="article-metadata">
<small>{{ comment.add_date|date:"M/d/Y" }} <b>{{ comment.author }}</b></small>
{% if comment.author == user %}
Delete
{% endif %}
<p>{{ comment.comm_content }}</p>
</div>
{% endif %}
{% endfor %}
My class based view in views.py where I want to touch this id:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comments'] = Comment.objects.all()[::-1]
return context
# In this function I want to access my comment id and remove this comment from database
def delete_comment(self):
post_to_delete = Post.objects.get(id=my_comment_id)
del post_to_delete
I know this can be solved somehow using jquery but I don't know javascript and for now I would like to know how to do it using python only. Thanks for any hints.
My models.py file:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
comm_content = models.TextField()
add_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
def __str__(self):
return f"Comment of post {self.post} posted at {self.add_date}."
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.post.pk})
First, add a URL pattern like:
# urls.py
path('comments/delete/<int:pk>/', views.CommentDeleteView.as_view(), name='delete_comment'),
next, you need a view to handle the logic:
# views.py
from django.urls import reverse_lazy
class CommentDeleteView(DeleteView):
model = Comment
def get_success_url(self):
return reverse_lazy('post-detail', kwargs={'pk': self.object.post.pk})
# if you don't want to send POST request, you can use:
def get(self, request, *args, **kwargs):
return self.post(request, *args, **kwargs)
Django's generic DeleteView will delete the object only if you send a POST request to it, so we will call the post method in get, to make it work with a GET request; Although, generally speaking, it's not a good idea; you should add a confirmation form (like a modal) and send a POST from there.
and finally, for your template:
{% for comment in comments %}
{% if comment.post == object %}
<div class="article-metadata">
<small>{{ comment.add_date|date:"M/d/Y" }} <b>{{ comment.author }}</b></small>
{% if comment.author == user %}
Delete
{% endif %}
<p>{{ comment.comm_content }}</p>
</div>
{% endif %}
{% endfor %}
I am very new to Django (and definitely rusty with HTML) and basically went through the official tutorial a couple of times. I am planning on creating a simple questionnaire with a list of questions, these questions can have several answers and each answer has a specific score for various categories. In the end the points for each category are added and depending on the score a message is displayed.
I am a bit stuck on how to display the answers for each question in a template however. I am also unsure how to calculate the final score: should I create a new class in my models to store the score? Or should I just do it in views.py (I would prefer this solution for now, I don't need to store the score in the DB and I don't need to login a user)?
Here is what I have so far:
models.py
from django.db import models
from django.contrib.auth.models import User
class Questionnaire(models.Model):
questionnaire_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.questionnaire_text
class Question(models.Model):
questionnaire = models.ForeignKey(Questionnaire, on_delete = models.CASCADE)
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete = models.CASCADE)
choice_text = models.CharField(max_length=200)
C1 = models.IntegerField(default=0)
C2 = models.IntegerField(default=0)
N1 = models.IntegerField(default=0)
N2 = models.IntegerField(default=0)
N3 = models.IntegerField(default=0)
N4 = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class QuestionnaireInstance(models.Model):
taker = models.ForeignKey(User, on_delete = models.CASCADE)
questionnaire_taken = models.ForeignKey(Questionnaire, on_delete = models.CASCADE)
C1_score = models.IntegerField(default=0)
C2_score = models.IntegerField(default=0)
N1_score = models.IntegerField(default=0)
N2_score = models.IntegerField(default=0)
N3_score = models.IntegerField(default=0)
N4_score = models.IntegerField(default=0)
def __str__(self):
return str(self.taker)
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from .models import Question, Questionnaire, Choice
def index(request):
latest_questionnaire_list = Questionnaire.objects.order_by('-pub_date')[:5]
template = loader.get_template('test/index.html')
context = {
'latest_questionnaire_list': latest_questionnaire_list
}
return HttpResponse(template.render(context,request))
def detail (request):
latest_question_list = Question.objects.all()
template = loader.get_template('test/detail.html')
context = {
'latest_question_list': latest_question_list
}
return HttpResponse(template.render(context, request))
def results (request):
questionnaire_instance = QuestionnaireInstance.objects.get(taker=request.user)
answer_instance = Choice.objects.all()
if request.method == 'POST':
questionnaire_instance.C1_score=+ answer_instance.values_list('C1',flat=True)[selected answer] #No clue how to call on the score of the specifically selected answer here
urls.py
from django.urls import path
from . import views
app_name = 'test'
urlpatterns = [
path('', views.index, name='index'),
path('detail/', views.detail, name='detail'),
path('results/', views.results, name='results'),
]
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
{% if latest_question_list %}
{% for item in latest_question_list %}
<h1>{{ item.question_text}}</h1>
{% for answer in item.choice_set.all %}
<form action="{% url 'oritest:results'%}" method="post">
<p>
{% csrf_token %}
<input type="checkbox" name="answer" id="answer"
value="{{ answer.id }}">
<label for="answer">{{ answer.choice_text }}
</label><br>
</p>
{% endfor %}
{% endfor %}
<input type="submit" value="Confirm">
<input type="button" onclick="history.back();" value="Back">
</form>
{% else %}
<p>No polls are available.</p>
{% endif %}
</body>
</html>
I would like to:
1) Have detail.html displaying each question and its answers with radio button.
2) Add the score (probably in my function results in views.py and display it in results.html) and do something based on that score.
Edit: I have solved the first issue by myself (see the code for detail.html). I might play around with crispy forms later to make it nicer but so far it looks like I wanted it to. I still have to figure out the scoring system though.
I have added the QuestionnaireInstance class to models.py to store the scores of Choice. I assume I have to:
1) Instantiate (for example )C1_score and C1 in results within my views.
2) Have something like C1_score =+ C1 also in results.
3) Display something (for example the user score and a picture) in results.html depending on C1_score.
I am uncertain of the syntax for instantiating C1_score depending on the User though.
Edit2: Is there any piece of information I have to add to get a nudge?
For the form itself I would highly recommend crispy forms. They look nice and will save a bit of work.
I would suggest that you store the correct answers in the database to make it easier to score and also create a response model to store the submitted answers. Then after each question you would pass the response pk through the success_url to the results view that renders the results template.
I have a problem where I can't use my Django variables inside Html
This is my code :
models.py
from django.db import models
from django.urls import reverse
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
created = models.DateTimeField(auto_now_add=True)
content = models.TextField(default="---")
H_price = models.IntegerField(default=0)
L_price = models.IntegerField(default=0)
remaining = models.IntegerField(default=0)
original_price = models.IntegerField(default=0)
Ended = models.BooleanField(default=False)
Published = models.BooleanField(default=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.title
def get_absolute_url(self):
return reverse('Products.views.post', args=[self.slug])
Views.py
from django.shortcuts import render
from .models import Post
# Create your views here.
def index(request):
posts=Post.objects.all()
return render(request, 'Index.html', {"Posts": posts})
def post(request):
return
Index.html
<h1>This is just a title </h1>
{% for post in posts %}
<div>
<h3> {{ post.title }}</h3>
<h3> {{ post.content }}</h3>
</div>
{% endfor %}
I know this isn't the best way to do Html but the goal is just to get it to work then I will style it with css and make everything Look Clean When i run the server i only get "this is just a title"
Any suggestions to help me fix it will be apreciated
Note that I am a begginer in django
Variables in the Django template language are case sensitive. You use {% for post in posts %} in your template, therefore you need to use posts not Posts in your view.
return render(request, 'Index.html', {"posts": posts})
I am very new to Django and have been following through the blog tutorial from the book: "Django by Example."
The code below should return all blog posts with a status of "published" but it refuses to work. What appears to be the correct page loads up using the list.html code but there are no posts showing. I have double checked and I am creating posts with the admin site with the status set to "published." I am not sure if the problem is with the template, model, views or URLs so I am including it all here:
Models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from django.core.urlresolvers import reverse
#Data model class for creating posts table enrties in database
#Custom manager. Limits returned querysets to ones with published status
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset()\
.filter(status='published') #super used to call get_queryset method from parent class as it is currently being
#overridden here.
class Post(models.Model):
STATUS_CHOICES = (('draft', 'Draft'), ('published', 'Published'),)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish') #A field for use in building urls
#slug = models.SlugField(slugify(title))
author = models.ForeignKey(User, related_name='blog_posts') #Each post written by a user and a user can write many posts
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager() #The default manager
published = PublishedManager() #Custom manager
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.publish.year, self.publish.strftime('%m'),self.publish.strftime('%d'), self.slug])
views.py:
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post/list.html', {'Posts': 'posts'})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day)
return render(request, 'blog/post/detail.html', {'post':post})
URLs.py
from django.conf.urls import url
from . import views
urlpatterns = [
# post views
url(r'^$', views.post_list, name='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/'\
r'(?P<post>[-\w]+)/$', views.post_detail, name='post_detail'),
Templates base.html:
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>My Site site</h2>
<p>This site is all about me</p>
</div>
</body>
</html>
detail.html:
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="date">Published{{ post.publish }} by {{ post.author }}</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
You need to use Post.published.all() to use your custom manager then in your dict you are doing 'Posts' with a capital P you might want to try lowercase as your view is using posts. Then also the value for it was a string instead of the variable posts. So something like this should work
def post_list(request):
posts = Post.published.all()
return render(request, 'blog/post/list.html', {'posts': posts})
You are passing in a string as your context object data:
return render(request, 'blog/post/list.html', {'Posts': 'posts'})
Needs to be
return render(request, 'blog/post/list.html', {'Posts': posts})
It also still isn't going to work since you have in your view and aren't calling the manager method. You have:
posts = Post.objects.all()
You need to use your customer manager.
I found the answer - all posts in the database are in the "draft" status, and status='published' is registered in the PublishedManager. Change status=''draft" and everything will be OK!
I want to know how to retrieve answers already made in my text fields because there is no ways to retrieve the answers already registered!
This is my models :
class Patient(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name + ' [' + str(self.id) + ']'
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question_text
class Reply(models.Model):
question = models.ForeignKey(Question)
patient = models.ForeignKey(Patient)
reply_text = models.CharField(max_length=200)
def __unicode__(self):
return self.reply_text
This is my template (formDynamic.html) :
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'Forum/style.css' %}" />
<div>
<h1>Patient details : {{ patient }}</h1>
</div>
form-included-into-question-template -->
<form action="success" method="post">
{% csrf_token %}
<fieldset>
{% block content %}
{% for question in questions %}
<h2><abcd>{{ question }}</abcd> <h6>{{ question.pub_date }}</h6></h2>
{% for reply in form %}
{{ form }}
{% endfor %}
{% endfor %}
{% endblock %}
</fieldset>
<input type="submit" value="Submit"/>
</form>
<a href="{% url 'list_patient' %}"/> <input type="button" value="Look Back"/>
This is my urls :
from django.conf.urls import url
from .import views
urlpatterns = [
url(r'^$', views.list, name ='list_patient'),
url(r'^(?P<patient_id>[0-9]+)/patient/$', views.save_reply, name ='detail_patient'),
#url(r'^(?P<patient_id>[0-9]+)/patient/success$', 'success', name ='success'),
]
This is my forms.py :
from django.forms import ModelForm
from django import forms
from .models import Reply
class ReplyForm(ModelForm):
class Meta:
model = Reply
fields = ['reply_text']
This is my views.py :
def save_reply(request, patient_id):
patient = get_object_or_404(Patient, pk=patient_id)
questions = Question.objects.all()
if request.method == 'POST':
form = Replyform(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
u = Question.objects.get(pk=id)
new_obj.reply_to = u
new_obj.save()
return HttpResponseRedirect('/success')
else:
form = ReplyForm()
return render_to_response('PQR/formDynamic.html', {'form': form, 'questions': questions, 'patient': patient,}, context_instance=RequestContext(request))
def success(request):
return HttpResponse ('<p>Success</p>')
I can not retrieve the answers already registered and run my post method to save my answers and return me the URL /success.
My post method does not work as well as my redirect to my url / success. Thanks you for your help !
I don't understand your question, but the reason you can't submit your form is that it is posting to a non-existent destination: the action attribute in the form HTML tag needs to be an actual URL. If you want to use a view name then do so via the {% url %} tag:
<form action="{% url "success" patient_id=patient.id %}" method="post">