I have a model Log and another model Solutions and I am using DetailView to display details of each log
Each log can have many solutions.
There is a log field in the Solutions model that is Foreign Key to Log model..
Now how do I access both Log model and Solutions of that particular log in the same html template if I want to display all the solutions of that particular log below the details of the log
models.py:
class Log(models.Model):
title = models.CharField(blank=False, max_length=500)
content = models.TextField(blank=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
image = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
super().save()
self.slug = self.slug or slugify(self.title + '-' + str(self.id))
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Log")
verbose_name_plural = ("Logs")
def __str__(self):
return f"{self.title}"
def get_absolute_url(self):
return reverse("log-detail", kwargs={"question": self.slug})
class Solutions(models.Model):
log = models.ForeignKey(
Log, on_delete=models.CASCADE, blank=True, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
solution = models.TextField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, blank=True)
image = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.solution)
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Solution")
verbose_name_plural = ("Solutions")
def __str__(self):
return f" {self.solution} "
views.py:
class LogDetailView(DetailView):
model = Log
slug_url_kwarg = 'question'
slug_field = 'slug'
log_detail.html:
{% extends 'log/base.html' %}
{%load crispy_forms_tags %}
{% block content %}
<title>Error Logger - {{object.title}}</title>
<div class="main container mt-4 p-3 mb-4">
<img style='display:inline;' class='rounded-circle account-img' src="{{ object.author.profile.avatar.url }}" alt="">
<h1 style='display:inline;'>
{{ object.title }}
</h1>
<p>Author: {{ object.author }}</p>
<p>Date and time of creation: {{ object.created }}</p>
<span> Details </span>:
<p class="big ml-4">{{ object.content }} <br />
{% if object.image %}
<img style="width: 20vw" class="mt-4" src="{{ object.image.url }}" alt="image" />
{% else %}
{% endif %}
</p>
</div>
<br />
<a
class="btn btn-outline btn-info button-solution"
href="#"
>Add solution</a
>
You can enumerate over these in the template by accessing the relation in reverse, this is normally modelname_set, unless you set a related_name=…. So in this case it is solutions_set:
{% for solution in object.solutions_set.all %}
{{ solution }}
{% endfor %}
If the ForeignKey has a related_name=… [Django-doc], for example with:
class Solutions(models.Model):
log = models.ForeignKey(
Log,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='solutions'
)
# …
Then we access this with:
{% for solution in object.solutions.all %}
{{ solution }}
{% endfor %}
Note: normally a Django model is given a singular name, so Solution instead of Solutions.
Related
I'm using the 'through' argument to connect Bot to Developer through Development team, in my html page (home.html), how would I render Developer's name in DevelopmentTeam? Also, I've tried to simply render the DevelopmentTeam name and was unsuccessful as well. I would greatly appreciate if someone could guide me in the right direction as I've read documentation everywhere and the issue persists.
thanks all in advance!
home.html
{% for bot in bot_list_slice|slice:":5" %}
<div class="col">
<a href="{% url 'bot_detail' bot.slug %}" class="text-decoration-none">
<div class="row-inside-content">
<div class="container">
<img src="#">
<h6 class="text-dark">{{ bot.bot_name|title }}</h6>
</div>
<div class="container">
<span class="badge bg-light text-dark">Software</span>
</div>
<div class="container">
<p>{{ bot.team_members.name **<here>** }}</p>
</div>
</div>
</a>
</div>
{% endfor %}
Models.py
class Developer(models.Model):
name = models.CharField(max_length=20, blank=False)
profile = models.ImageField(blank=True,null=True)
job_choices = [
('Backend Developer', 'Backend Developer'),
('Frontend Developer', 'Frontend Developer'),
('Lead Developer', 'Lead Developer'),
('Team Developer', 'Team Developer'),
('Designer', 'Designer'),
]
job = models.CharField(choices=job_choices, max_length=20)
team = models.ManyToManyField('DevelopmentTeam', blank=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Developer, self).save(*args, **kwargs)
def __str__(self):
return '{}'.format(self.name)
class DevelopmentTeam (models.Model):
team_name = models.CharField(max_length=20, null=True)
members = models.ForeignKey(Developer,on_delete=models.CASCADE, null=True)
bot = models.ForeignKey("Bot", on_delete=models.CASCADE, null=True)
def __str__(self):
return '{} '.format(self.team_name, self.members, self.bot)
class Bot(models.Model):
bot_name = models.CharField(max_length=20, blank=False, null=True)
company_logo = models.ImageField(blank=True, null=True)
team_members = models.ManyToManyField(Developer, through=DevelopmentTeam, blank=True)
slug = models.SlugField(max_length=50, null=True, blank=True, unique=True)
def __str__(self):
return '{}, {}'.format(self.bot_name, self.admin_approval)
def save(self, *args, **kwargs):
self.slug = slugify(self.bot_name)
super(Bot, self).save(*args, **kwargs)
{% for members in bot.team_members.all %}}
I ended up changing the model, but I also realized I was doing {{ bot.name }} instead of {{ members.name }} to get the developers name in template, so I doing it wrong.
I'm trying to get my three models working correctly on one DetailView. I have all of them loaded, but the model that contains the images keeps showing the first image. I know I need to filter it somehow, but I don't really know how to do it. Since I need the product info to filter the images. Here is my code:
views:
class VendorDetailView(DetailView):
context_object_name = 'vendor_detail'
model = Vendor
queryset = Vendor.objects.all()
template_name = 'vendor_details.html'
def get_context_data(self, **kwargs):
context = super(VendorDetailView, self).get_context_data(**kwargs)
context['products'] = Product.objects.filter(vendor=self.get_object())
context['image'] = ProductImage.objects.all()
return context
models:
class Product(models.Model):
product_model = models.CharField(max_length=100)
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)
slug = models.SlugField(max_length=200, unique=True, null=True)
length = models.CharField(max_length=50)
length_range = models.ForeignKey(LengthRange, on_delete=models.SET_NULL, null=True, blank=True)
hull_type = models.ForeignKey(Hull, on_delete=models.SET_NULL, null=True, blank=True)
max_beam = models.CharField(max_length=50, blank=True, default='0')
cockpit_length = models.CharField(max_length=50, blank=True, default='0')
cockpit_beam = models.CharField(max_length=50, blank=True, default='0')
price = models.DecimalField(decimal_places=2, max_digits=50)
power = models.ForeignKey(PowerConfiguration, on_delete=models.SET_NULL, null=True, blank=True)
average_bare_hull_weight = models.CharField(max_length=50, blank=True, default='0')
fuel_capacity = models.CharField(max_length=50, blank=True, default='0')
seating_capacity = models.ForeignKey(Seat, on_delete=models.SET_NULL, null=True, blank=True)
speed = models.ForeignKey(SpeedRange, on_delete=models.SET_NULL, null=True, blank=True)
warranty = models.CharField(max_length=256, default='None')
hull_only_available = models.BooleanField(blank=False, default=False)
description = models.TextField()
featured = models.BooleanField(blank=False, default=False)
class Meta:
ordering = ['product_model']
def __str__(self):
return '{} {}'.format(self.vendor, self.product_model)
def save(self, *args, **kwargs):
# just check if product_model or vendor.name has changed
self.slug = '-'.join((slugify(self.vendor.name), slugify(self.product_model)))
super(Product, self).save(*args, **kwargs)
class ProductImage(models.Model):
product = models.ForeignKey(Product, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='product_images', blank='img/92-thumb.jpg')
class Vendor(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=200, unique=True, null=True)
website = models.CharField(max_length=256)
vendor_email = models.CharField(max_length=100)
images = models.ImageField(upload_to='vendor_images', blank='img/92-thumb.jpg')
description = models.TextField()
def __str__(self):
return self.name
def save(self, *args, **kwargs):
# just check if product_model or vendor.name has changed
self.slug = slugify(self.name)
super(Vendor, self).save(*args, **kwargs)
Template:
<div class="preview col-md-4">
<div class="vendor-pic">
{% if vendor_detail.images %}
<div class="tab-pane">
<img class="vendor-preview" src="{{ vendor_detail.images.url }}"/></div>
{% endif %}
</div>
**[snipped for brevity]**
</div>
<div class="details col-md-6">
<h3 class="vendor-title">{{ vendor_detail.name }} Boats</h3>
<p class="vendor-description">{{ vendor_detail.description | linebreaksbr }}</p>
<h5 class="website">website: <span>{{ vendor_detail.website }}</span></h5>
</div>
</div>
{% for product in products %}
<div class="product-card">
<div class="product">
<div class="top">{% for product_image in image.all %}
{% if product_image.image %}
<img class="product-img" src="{{ product_image.image.url }}">
{% endif %}
{% endfor %}
</div>
<div class="bottom">
<div class="left">
<div class="details">
<h3>{{ product.vendor }} {{ product.product_model }}</h3>
<p>Starting at ${{ product.price|intcomma }}</p>
</div>
<div class="buy"><a
href="{% url 'boatsales:product_detail' product.slug %}"><i
class="material-icons">pageview</i></a></div>
</div>
</div>
</div>
<div class="inside">
<div class="icon"><i class="material-icons">info_outline</i></div>
<div class="contents">
<p style="text-align: justify">{{ product.description|linebreaksbr }}</p>
</div>
</div>
</div>
{% endfor %}
I've tried multiple ways to filter the product images, but the only thing I can get working is the ProductImages.objects.all() which of course is incorrect. Any help you can provide would be greatly appreciated. Thanks in advance.
You don't need a queryset for the images, you can access them through the Product instances using the related_name like this:
{% for product in products %}
<div class="product-card">
<div class="product">
<div class="top">
{% for product_image in product.images.all %}
<img class="product-img" src="{{ product_image.image.url }}">
{% endfor %}
</div>
...
</div>
{% endfor %}
Sorry for this title, I wasn't sure how to name it properly. I'm having problem with getting queryset of ManyToManyField that is in relation with other ManyToManyField. So it's look like this, there is model Company that has ManyToManyField with Person and Person model got ManyToManyField with Position, because logic behind it is that 1 company can have many persons and 1 person can have few positions and can be employed by few companies (which is clear I think). I'm getting the queryset for Person in Company by this way
{% for team in brand.team.all %}
<p>{{ team.first_name }} {{ team.last_name }}</p>
<img class="img-thumbnail" src="/media/{{ team.photo }}">
<p>{{ team.position }} </p>
<p>{{ team.about }} </p>
{% endfor %}
And I'm getting what I want, comparing this to template looks like this
but I'm not getting positions of person, only company.Position.None and I've no idea how to get this. From documentation so far I know that it works for single ManyToManyField but I couldn't find example similar to mine case and I'm not sure how I should get (person's position)
Below are my files
models.py
from django.db import models
...
TYPES = (
('Startup', 'Startup'),
... )
CITIES = (
('Warszawa', 'Warszawa'),
... )
STACK = (
('PHP', 'PHP'),
... )
STUDENTS = (
('No', 'No'),
('Yes', 'Yes')
)
STACK_ICONS = (
('/static/icons/stack/php.png', 'PHP'),
('/static/icons/stack/javascript.png', 'JavaScript'),
...
)
POSITIONS = (
('CEO', 'Chief Executive Officer'),
('CTO', 'Chief Technology Officer'),
...
)
# object position with relationship many to many to person
class Position(models.Model):
position = models.CharField(max_length=50, choices=POSITIONS)
def __str__(self):
return self.position
# object person relation many to one (many persons to one company)
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
about = models.TextField(max_length=500, default=None)
position = models.ManyToManyField('Position')
photo = models.ImageField(blank=True, null=True, default=None)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
# object company
class Company(models.Model):
# field person with relation many to one (many persons to 1 company)
team = models.ManyToManyField('Person')
name = models.CharField(max_length=100, blank=False)
technologies = models.ManyToManyField('Stack')
website = models.TextField(max_length=150, blank=True, null=True, validators=[URLValidator()])
...
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Company, self).save(*args, **kwargs)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.name
# object stack relation manytomany with Company
class Stack(models.Model):
name = models.CharField(max_length=30, choices=STACK)
icon = models.CharField(max_length=80, choices=STACK_ICONS)
def __str__(self):
return self.name
views.py
from django.shortcuts import render, get_object_or_404, redirect
...
def brands(request, slug):
brand = get_object_or_404(Company, slug=slug)
return render(request, 'company/comp_view.html', {'brand': brand})
def stacks(request):
stack = get_object_or_404(Stack)
return render(request, 'company/comp_view.html', {'stack': stack})
def positions(request):
position = get_object_or_404(Position)
return render(request, 'company/comp_view.html', {'position': position})
...
comp_view.html
{% extends 'company/base.html' %}
<div class="col col-md-1"></div>
<div class="col col-md-5 card-section">
<div class="team ">
<div class="card-title">
<span>Team</span>
</div>
<div class="row text-center">
<div class="col col-md-4">
{% for team in brand.team.all %}
<p>{{ team.first_name }} {{ team.last_name }}</p>
<img class="img-thumbnail" src="/media/{{ team.photo }}">
<p>{{ team.position }}</p>
<p>{{ team.about }} </p>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
There's no such thing as a "single ManyToManyField". You have an m2m relationship, you need to iterate through it just like you do for the team members.
{% for position in team.position.all %}
{{ position.name }}
{% endfor %}
This may be a simple answer but after days of searching I cannot seem to figure out the correct way to achieve this.
I have a template where I want to show all the questions that are related to an assessment that has been assigned to a user. I thought that I could use the results from:
ResponseDetails = AssessmentResponse.objects.prefetch_related('assessment').filter(id=response_id)
by looking into the object and grabbing the assessment_id which I could then pass into the next query-set as a filter but I couldn't get that to work.
Problem: Because the view doesn't filter based on the assessment_id found in the AssessmentResponse model, it gives me every question in the AssessmentQuestion model.
An answer would allow me to actually have a good nights sleep trying to figure it out.
Views
def UpdateAssessmentResponse(request, response_id):
ResponseDetails = AssessmentResponse.objects.prefetch_related('assessment').filter(id=response_id)
QuestionList = AssessmentQuestion.objects.all()
ChoiceList = AssessmentQuestionChoice.objects.all()
context = {
"ResponseDetails":ResponseDetails,
"QuestionList":QuestionList,
"ChoiceList": ChoiceList,
#"ID" : ID,
}
return render(request, "assessment/assessment_response_update.html", context)
Template
{% if QuestionList and ResponseDetails%}
{% csrf_token %}
{% for question in QuestionList %}
<p> {{ question.question_text }} </p>
{% for choice in ChoiceList %}
{% if choice.question_id == question.pk %}
<fieldset id="group1">
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" class="custom-control-input" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label class="custom-control-label" for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label>
</div>
<fieldset id="group1">
{% endif %}
{% endfor %}
{% endfor %}
<div class="card-footer">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
{% else %}
<p>There are currently no questions for this assessment.</p>
{% endif %}
Models:
class AssessmentForm(models.Model):
name = models.CharField(max_length=400)
description = models.TextField()
created = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField()
due_date = models.DateField(default=datetime.now, blank=True, null=True)
def __str__(self):
return self.name
class AssessmentResponse(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
assessment = models.ForeignKey('AssessmentForm', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
last_update = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
return reverse('assessment_response_detail', args=[str(self.id)])
#def get_assessment_id(self):
# return self.assessment
def __str__(self):
return self.user
class AssessmentQuestionType(models.Model):
type = models.CharField(max_length=30)
def __str__(self):
return self.type
class AssessmentQuestionCategory(models.Model):
name = models.CharField(max_length=200)
assessment = models.ForeignKey('AssessmentForm', on_delete=models.CASCADE)
def __str__(self):
return self.name
class AssessmentQuestionSubCategory(models.Model):
name = models.CharField(max_length=200)
parent_category = models.ForeignKey('AssessmentQuestionCategory', on_delete=models.CASCADE)
def __str__(self):
return self.name
#CHOICES_HELP_TEXT = _(u"""The choices field is only used if the question type if the question type is 'radio', 'select', or 'select multiple' provide a comma-separated list of options for this question .""")
class AssessmentQuestion(models.Model):
question_type = models.ForeignKey('AssessmentQuestionType', on_delete=models.PROTECT)
question_text = models.TextField()
is_required = models.BooleanField()
category = models.ForeignKey('AssessmentQuestionCategory', on_delete=models.PROTECT, blank=True, null=True)
subcategory = models.ForeignKey('AssessmentQuestionSubCategory', on_delete=models.PROTECT, blank=True, null=True)
assessment = models.ForeignKey('AssessmentForm', on_delete=models.CASCADE)
def __str__(self):
return self.question_text
class AssessmentQuestionChoice(models.Model):
question = models.ForeignKey(AssessmentQuestion, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return self.choice_text
class AssessmentAnswer(models.Model):
text = models.CharField(max_length=1024)
question = models.ForeignKey('AssessmentQuestion', on_delete=models.CASCADE)
response = models.ForeignKey('AssessmentResponse', on_delete=models.PROTECT)
def __str__(self):
return self.text
Figured it out! Objects.filter is a lazy query so it wasn't actually available to my other query-set to use as a filter. Solved it by using objects.get instead.
form.is_valid() always fails. I tried different ways to handle it but fails every time and it returns false. Please help in figuring out whats wrong with the code.
models.py looks like this -
class Album(models.Model):
album_name = models.CharField(max_length=50, primary_key=True)
place = models.CharField(max_length=50)
date_pub = models.DateTimeField('date published')
def __str__(self):
return self.album_name
class Images(models.Model):
album_name = models.ForeignKey(Album, db_column='album_name')
image_name = models.CharField(max_length=40)
image = models.FileField(null=True, blank=True)
upload_dt = models.DateTimeField(auto_now=True, auto_now_add=False)
like_cntr = models.IntegerField(default=0)
description = models.CharField(max_length=200, null=True)
def __str__(self):
return self.image_name
forms.py is -
class ImagesForm(forms.ModelForm):
description = forms.CharField(required=False)
class Meta:
model = Images
fields = ('album_name', 'description',)
views.py is -
class RandomView(TemplateView):
template_name = 'photos/random.html'
def get(self, request, album_name):
images = Images.objects.filter(album_name=album_name)
context = {'album_name':album_name, 'images' : images}
return render(request, 'photos/random.html', context)
def post(self, request, album_name):
form = ImagesForm(request.POST)
if form.is_valid():
form.save(commit=False)
text = form.cleaned_data['description']
Images.album_name = album_name
form.save()
else:
return HttpResponse("Failed to save")
Templates is -
<h3>Album : {{album_name }}</h3>
{% for image in images %}
<img src="{{image.image.url}}" height="400" width="500">
<h4> {{image.image_name }}</h4>
<form method="POST" action=""> {% csrf_token %}
<span class = "badge">Description</span>
{% if image.description %}
<h4> {{image.description }} </h4>
{% else %}
<input type="text" value=" "/>
<button type="Submit">Submit</button>
{% endif %}
</form>
{% endfor %}
Where is your necessary name and id attributes for your input tag?
<input type="text" name="description" id="id_description"/>
Please try with {{ form.errors }} above "form" tag. And first of all check that what the errors arrive. Then Find the solution based on that error. Let me know if it is helpful or not.