Django: Accessing OneToOneField in template - python

Hi I have to following Models.py
class Question(models.Model):
user = models.ForeignKey(User)
article = models.ForeignKey(Article)
number = models.CharField("문제번호", max_length=10, null=True, blank=True)
q_type = models.CharField("문제유형", max_length=15)
question = models.TextField("문제내용")
answer = models.TextField("답안", null=True, blank=True)
reference = models.TextField("참고사항", null=True, blank=True)
def __str__(self):
return "%s번: %s" % (self.number, self.question)
class Professor(models.Model):
question = models.OneToOneField(Question, null=True, blank=True, related_name="related_professor")
articles = models.ManyToManyField(Article, null=True, blank=True)
name = models.CharField("교수이름", max_length=20)
def __str__(self):
return "%s" % (self.name,)
Views.py:
def read_q_table(request, board_id, article_id):
article = get_object_or_404(Article, id=article_id)
context = {
"boards" : Board.objects.all(),
"board_id" : board_id,
"questions" : Question.objects.all().order_by("number"),
"article" : article,
"professor" : Professor.objects.all()
}
return render(request, "q_table.html", context)
Template:
{% if questions %}
{% for question in questions %}
<div class="list-group-item">
<div class="row text-center">
<div class="col-xs-2 col-md-2">{{ question.related_professor.name }}</div>
</div>
</div>
{% endfor %}
{% else %}
What I want is to access professor name field in template. I have passed in context the list of "question" class objects to template, and I would like to use OneToOneField attribute somehow to access related professor name in template.
According to Accessing Django OneToOneField in templates?, {{ question. related_professor.name }} should work, but it doesn't. Can anyone help?
Thanks.
Or, it could be a problem with saving the professor data in the first place. The following code takes form input and submit them to save them.
Professor.objects.get(name=professor).question = question_instance
Professor.objects.get(name=professor).save()
These two lines in def submit_question may raise an eyebrow but I am not sure. Here I am trying to get the related professor instance and update its question field(a OneToOneField that relates to Question class).
def submit_question(request, board_id, article_id):
article = get_object_or_404(Article, id= article_id)
try:
professor = request.POST["professor"].strip()
q_type = request.POST["q_type"].strip()
question = request.POST["question"].strip()
number = request.POST["number"].strip()
reference = request.POST["reference"].strip()
if request.POST['q_type']== "주관식":
answer = request.POST['d_answer'].strip()
else:
answer = request.POST['m_answer'].strip()
except KeyError:
request.session["error"] = "올바른 요청이 아닙니다."
return redirect("read_article", board_id, article_id)
if professor and q_type and question:
question_instance = article.question_set.create(q_type = q_type, question = question, user_id = request.user.id)
Professor.objects.get(name=professor).question = question_instance
Professor.objects.get(name=professor).save()
if number:
question_instance.number = number
if answer:
question_instance.answer = answer
if reference:
question_instance.reference = reference
question_instance.save()
else:
request.session["error"] = "출제교수, 문제유형 및 문제는 필수 입력 항목입니다."
return redirect("read_article", board_id, article_id)
return redirect("read_q_table", board_id, article_id)

These two lines are suspect:
Professor.objects.get(name=professor).question = question_instance
Professor.objects.get(name=professor).save()
The second line will get the Professor from the database again, and it won't have your question instance attached anymore when you save it. Try this instead:
prof = Professor.objects.get(name=professor)
prof.question = question_instance
prof.save()

Related

getting error ..................The QuerySet value for an exact lookup must be limited to one result using slicing

I'm building a social media website in Django. While I tried to list all the comments on the index page, I am getting this error, The QuerySet value for an exact lookup must be limited to one result using slicing and when I am using.... comments = PostComment.objects.filter(post__in=allPost)... instead of comments = PostComment.objects.filter(post=allPost) the QuerySet is not getting filtered and I am getting the same comments in all the post, basically, I want to show comments under all the post and that comment should be referred to as that post
things I have tried instead of comments = PostComment.objects.filter(post=allPost)
comments = PostComment.objects.filter(post__in=allPost)
comments = PostComment.objects.get(post__in=allPost)
comments = PostComment.objects.get(post=allPost)
comments = PostComment.objects.filter(post_id__in=allPost)
comments = PostComment.objects.filter(post__id__in=allPost)
comments = PostComment.objects.filter(post_id=allPost)
but none of them are working............................................please help me
what should I do in this case?
views.py...
def index(request):
if request.user.is_authenticated:
allPost = Post.objects.all().order_by('-created_on').filter(creater = request.user)
allBlog = Blogpost.objects.all()
comments = PostComment.objects.filter(post=allPost)
context = {'allPost' : allPost, 'allBlog' : allBlog, 'comments' : comments}
return render(request, 'index.html', context)
else:
return render(request, "signoption.html")
models.py....
class Post(models.Model):
sno = models.AutoField(primary_key=True)
caption = models.CharField(max_length=500)
hashtag = models.CharField(max_length=500)
image = models.ImageField(upload_to='socialmedia/images', default="")
created_on = models.DateTimeField(default=timezone.now)
creater = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return str(self.sno) + '.....Post By.....' + str(self.creater)
class PostComment(models.Model):
sno = models.AutoField(primary_key=True)
comment = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)
created_on = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.sno) + '.....comment By.....' + str(self.user)
index.html....
{% for comment in comments %}
<div class="comment">
<div class="comment-user">
<div class="comment-usr-dp">
<img src="{%static 'img/profile/profile.png'%}" alt="">
</div>
</div>
<div class="comments-usr-usrname">
<b><h1>{{comment.user.username}}</h1></b>
</div>
<div class="comment-text">
<h1>{{comment.comment}}</h1>
</div>
<div class="comment-time">
<h1>{{comment.created_on | naturaltime}}</h1>
</div>
</div>
{%endfor%}
how i cam see in this question The QuerySet value for an exact lookup must be limited to one result using slicing. Filter error
the trouble is there
comments = PostComment.objects.filter(post=allPost)
so i think you need to write like that
comments = PostComment.objects.filter(post__in=allPost)

__in filter only returning one value, show query through intermediate table

Noob at coding and need help. I am trying to render the view article by filtering through the model Spots. I have an intermediate table ArticleSpots to link the 2 tables Spots and Articles. In the views article I want to show only the spots that are linked to that specific article. My problem is that Spots.objects.filter(id__in=articleSpots) only shows the first one value and not all of the spots that are linked. What am I doing wrong here?
views.py
def article(request, slug):
articles = get_object_or_404(Articles, slug=slug)
article_id = articles.id
articleSpots = ArticleSpots.objects.filter(article__id=article_id)
spots = Spots.objects.filter(id__in=articleSpots)
context = {"spots": spots, "articles": articles}
template_name = "articletemplate.html"
return render(request, template_name, context)
models.py
class ArticleSpots(models.Model):
article = models.ForeignKey('Articles', models.DO_NOTHING)
spot = models.ForeignKey('Spots', models.DO_NOTHING)
class Meta:
managed = True
db_table = 'article_spots'
verbose_name_plural = 'ArticleSpots'
def __str__(self):
return str(self.article) + ": " + str(self.spot)
class Articles(models.Model):
title = models.CharField(max_length=155)
metatitle = models.CharField(max_length=155)
slug = models.SlugField(unique=True, max_length=155)
summary = models.TextField(blank=True, null=True)
field_created = models.DateTimeField(db_column='_created', blank=True, null=True)
field_updated = models.DateTimeField(db_column='_updated', blank=True, null=True)
cover = models.ImageField(upload_to="cover", blank=True, default='logo-00-06.png')
class Meta:
managed = True
db_table = 'articles'
verbose_name_plural = 'Articles'
def __str__(self):
return str(self.id) + ": " + str(self.title)
class Spots(models.Model):
title = models.CharField(max_length=155)
metatitle = models.CharField(max_length=155)
slug = models.SlugField(unique=True, max_length=155)
author = models.ForeignKey(Authors, models.DO_NOTHING)
field_created = models.DateTimeField(db_column='_created', blank=True, null=True)
field_updated = models.DateTimeField(db_column='_updated', blank=True, null=True)
cover = models.ImageField(upload_to="cover", blank=True, default='logo-00-06.png')
summary = models.TextField(blank=True, null=True)
content1 = models.TextField(blank=True, null=True)
content2 = models.TextField(blank=True, null=True)
class Meta:
managed = True
db_table = 'spots'
verbose_name_plural = 'Spots'
def __str__(self):
return str(self.id) + ": " + str(self.title)
html
<!-- START MAIN -->
<main class="page"></main>
<p>
{{ spots.title }} <br />
{{ spots.content1 }} <br />
{{ articles.title }}
</p>
{% for spots in spots %} {{ spots.title}} {% endfor %}
<!-- END MAIN -->
You are currently retrieving Spots that have the same primary key as the ArticleSpots object, but that does not make much sense: it is possible that this is the case, but even if that happens, the returned Spots does not per se is linked to a relevant ArticleSpots with the given article.
You can retrieve the relevant Spots with:
def article(request, slug):
article = get_object_or_404(Articles, slug=slug)
spots = Spots.objects.filter(articlespots__article=article)
context = {'spots': spots, 'article': article}
return render(request, 'articletemplate.html', context)
I would strongly advise to name you Article object article since it is a single Article, not a collection of Articles. spots on the other hand is a collection of spots.
It makes no sense to render {{ spots.content1 }} and {{ spots.title }}, since spots is a collection of Spots that can contain zero, one or more items.
The template thus should look like:
<p>
{{ article.title }}
</p>
{% for spot in spots %} {{ spot.title}} {% endfor %}
Note: normally a Django model is given a singular name, so Articles instead of Article.

Django view with get context not working

Have a quick question. Trying to use a relational model in one DetailView. However, no matter what I try the data does not display. I've tried a few versions of template tags to no avail.
html
{% for parts in relatedparts %}{{ parts.name }}
</div>{% endfor %}
views.py
class ErrorCodeView(DetailView):
context_object_name = 'error_code_details'
model = models.ErrorCodes
template_name = 'error_code_details.html'
def get_context_data(self, **kwargs):
# xxx will be available in the template as the related objects
context = super(ErrorCodeView, self).get_context_data(**kwargs)
context['relatedparts'] = RelatedParts.objects.filter(name=self.get_object())
return context
models.py
class ErrorCodes(models.Model):
name = models.CharField(max_length=256)
description = models.CharField(max_length=400)
instructions = models.CharField(max_length=256)
PartsNeeded = models.CharField(max_length=120, default='')
usercomments = models.CharField(max_length=400, default='', blank=True)
relpic = models.ImageField(upload_to='media/',blank=True)
relpictwo = models.ImageField(upload_to='media/',blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("errorcodes:errorcodeview",kwargs={'name':self.name})
class RelatedParts(models.Model):
name = models.CharField(max_length=256)
related_error_code = models.ForeignKey(ErrorCodes, on_delete=models.PROTECT)
def __str__(self):
return self.name
You don't need to do this at all. You can follow the relationship in the template.
{% for part in object.relatedparts_set.all %}{{ part.name }}{% endfor %}
You don't need any code in the view to enable this.
could it be that "name=self.get_object()" should be "name=self.get_object().name" ?
You currently have:
context['relatedparts'] = RelatedParts.objects.filter(name=self.get_object())
but that is probably producing an empty queryset.

Unable to automatically pick foreign key from modelform

I am working on a product app on Python 2.7 / Django 1.7.
I have a model for product namely 'product_profile' and I want to allow my customer (end user) to ask any thing regarding specific products using a form.
However I am unable to allow user to automatically select the product (foreign key) and the customer has to select from a drop-down which quite irrational. I have also assigned the foreign key in url-variable.
here is my code:
MODEL.PY
class ProductProfile(models.Model):
category = models.ForeignKey(Category)
brand = models.ForeignKey(Brand)
product_name = models.CharField(max_length=128)
model_name = models.CharField(max_length=128)
generation = models.CharField(max_length=128)
processor = models.CharField(max_length=128)
ram = models.DecimalField(max_digits=2, decimal_places=0)
hdd = models.DecimalField(max_digits=6, decimal_places=2)
optical_drive = models.CharField(max_length=128)
display = models.CharField(max_length=128)
card_reader = models.CharField(max_length=128)
blue_tooth = models.CharField(max_length=128)
web_cam = models.CharField(max_length=128)
warranty = models.CharField(max_length=128)
price = models.DecimalField(max_digits=9, decimal_places=2)
condition = models.TextField()
product_image = models.ImageField(upload_to=update_Product_image_filename)
post_date = models.DateTimeField(db_index=True, auto_now_add=True)
# Override th __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.product_name
class Customer_ps_contact(models.Model):
name = models.CharField(max_length=128)
email = models.EmailField(max_length=75)
subject = models.CharField(max_length=128 )
product = models.ForeignKey(ProductProfile)
message = models.TextField()
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format:
'+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], blank=True, max_length=15) # validators should be a
list
def __unicode__(self):
return self.name
FORM.PY
class Customer_ps_contactForm(forms.ModelForm):
class Meta:
model = Customer_ps_contact
product = forms.ModelChoiceField(queryset=ProductProfile.objects.all(),
widget=forms.HiddenInput())
fields = ('name','email', 'product','subject','message', 'phone_number')
VIEWS.PY
def product_inquiry(request, product_id):
product = ProductProfile.objects.get(pk=product_id)
if request.method == 'POST':
#form = Customer_ps_contactForm(request.POST, initial = {'product': product})
#form = Customer_ps_contactForm(initial = {'product': product.id})
form = Customer_ps_contactForm(request.POST)
if form.is_valid():
form_data_dict = form.cleaned_data
print form_data_dict['product']
mail_customer_enquriy(form_data_dict) # Function to send email to admin
thank_u_customer(form_data_dict) # Function to send email to customers
form = form.save(commit=False)
form.product = product
form.save()
return home(request)
else:
print ("form is not valid")
print (form.errors)
else:
form = Customer_ps_contactForm()
context_dict = {'form':form, 'product': product}
return render(request, 'product/product_inquiry2.html',context_dict)
URL Patterns
urlpatterns = patterns('',
url(r'^inquiry/(?P<product_id>\d+)/$', views.product_inquiry, name='price'), # Only relevent url given
)
Template : product_inquiry2.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block body_block %}
{% block title %}Product Inquiry{% endblock %}
<div class="row">
<div class="col-md-10 col-md-offset-1">
<h2 style="font-weight:bold">Enquiry regarding '{{product.product_name}}'</h2>
<hr>
<form id="contact_form" method="post" action=""/>
{% csrf_token %}
{{ form | crispy }}
<input class="btn btn-primary pull-right " type="submit" name="submit" value="Submit the Message" />
</form>
</div>
</div>
{% endblock %}
What should I do?
You know what the product is from the id in the url, so there's no need to include it in your form.
To check that the product exists in the database, you can use the get_object_or_404 shortcut.
def product_inquiry(request, product_id):
product = get_object_or_404(ProductProfile, pk=product_id)
Then leave out 'product' from your list of fields, and remove the ModelChoiceField with hidden input widget.
class Customer_ps_contactForm(forms.ModelForm):
class Meta:
model = Customer_ps_contact
fields = ('name','email','subject','message','phone_number')
You are already setting the product when you save it, but it would be clearer to use the variable name instance to make it clearer what's going on. If you change your mail_customer_enquriy and thank_u_customer methods to use the instance instead of cleaned_data, then you won't have to do anything with form.cleaned_data.
if form.is_valid():
instance = form.save(commit=False)
instance.product = product
instance.save()
mail_customer_enquriy(instance) # Function to send email to admin
thank_u_customer(instance) # Function to send email to customers
return home(request)

I can't display detail_page with absolute_url?

When I got this error I understood that I didn't learn URL -HTML- views-model relationship. First, let me show my codes.
This is my views.py:
def category_detail(request, category_name):
links = Link.objects.filter(category__name=category_name)
return render_to_response("category_detail.html", {"links":links}, context_instance=RequestContext(request))
This is models.py:
class Category(models.Model):
name = models.CharField(_("Category"), max_length=255)
user = models.ManyToManyField(User)
def __unicode__(self):
return "%s %s" %(self.user, self.name)
def admin_names(self):
return ', '.join([a.username for a in self.user.all()])
admin_names.short_description = "User Names"
def get_absolute_url(self):
return "/category/%s" % self.name
class Link(models.Model):
user = models.ForeignKey(User)
posted_at = models.DateTimeField(auto_now_add=True)
url = models.URLField()
title = models.CharField(max_length=255, null=True, blank=True)
category = models.ForeignKey(Category)
def __unicode__(self):
return "%s %s %s" %(self.url, self.title, self.category)
This is HTML page:
<div id="profilemenu">
index<p>
{% for category in categories %}
<p>{{category.name }}
{% endfor %}
<p>
</div>
and urls.py:
url(r'^category/(?P<category_name>.*)', 'link.views.category_detail', name="category_detail"),
When I click a category name to open category_detail.html, the URL in browser is like :
http://127.0.0.1:8000/category`/
I can't get categoryname. Please can you tell me my stupid mistake? :\ Thanks for time.
If you are using the namespace in your urls you would need to reference it without quotes in the template.
<p>{{category.name }}
Note: You'll want to ensure the namespace is fully qualified. If you have embedded namespaces you should separate them with :.
<p>{{category.name }}
Hopefully this solves your problem.
You should follow get_absolute_url reference:
def get_absolute_url(self):
from django.core.urlresolvers import reverse
return reverse('link.views.category_detail', args=[str(self.name)])
html
{{ category.name }}

Categories

Resources