I want to filter a queryset that depends on another queryset that already depends on another queryset
My models.py
class Escola(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
nome = models.CharField(db_column='Nome', max_length=255, blank=True, null=True)
class Inscrio(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
escolaid = models.ForeignKey(Escola, models.DO_NOTHING, db_column='EscolaID', blank=True, null=True)
class Utilizador(AbstractBaseUser)
id = models.AutoField(db_column='ID', primary_key=True)
inscriçãoid = models.ForeignKey(Inscrio, models.DO_NOTHING, db_column='InscriçãoID', blank=True, null=True)
My views.py
def view_forms(request):
return render(request,
"main/view_forms.html",
{"escolas": Escola.objects.all(),
})
I am doing
{% for escola in escolas %}
{% for inscrio in escola.inscrio_set.all %}
{% for utilizador in inscrio.utilizador_set.all %}
<tr>
<td><center>{{inscrio.id}}</center></td>
<td><center>{{escola.nome}}</center></td>
<td><center>{{utilizador.id}}</center></td>
{% endfor %}
{% endfor %}
{% endfor %}
I am currently trying to get the Inscrio data from Escola.
But when I try to get the Utlizador data from the Inscrio I get nothing.
How can I do this?
Thanks in advance
Escola.objects.all method is not executed and is passed into the template as a method.
To fix this, add Parentheses to the end. Escola.objects.all()
If you are extending AbstractBaseUser then you should provide USERNAME_FIELD.
Here Utlizador doesn't save any record due to this error so correct as below
class Utilizador(AbstractBaseUser):
id = models.AutoField(db_column='ID', primary_key=True)
inscriçãoid = models.ForeignKey(Inscrio, models.DO_NOTHING, db_column='InscriçãoID', blank=True, null=True)
username = None
email = models.EmailField('email address', unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
Related
i wrote a code about music and used Many-To-Many-Field() as genre but when i try to show genres it just shows : Genre['a number']
template:
{% extends 'pages/base.html' %}
{% block content %}
<form>
{% if mdata.image %}
<img src="mdata.image.url" height="500" width="500">
{% endif %}
{% for field in form %}
<p>{{ field.label }} : {{ field.value}}</p>
}
{% endfor %}
</form>
edit
{% endblock %}
models is here:(i didnt know which one u need so pasted both of them)
from django.db import models
from django.contrib.auth.models import User
class Genre(models.Model):
name = models.CharField(unique=True,max_length=20)
def __str__(self):
return self.name.title()
class Mdata(models.Model):
name = models.CharField(max_length=100)
artist = models.CharField(max_length=150)
album = models.CharField(max_length=100)
nation = models.CharField(max_length=100)
duration = models.DecimalField(max_digits=4,decimal_places=2)
released_in = models.DecimalField(max_digits=4,decimal_places=0)
uploaded_at = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='images/',blank=True,null=True)
audio = models.FileField(upload_to='audios/',null=True,blank=True)
genre = models.ManyToManyField(Genre)
uploader = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.name.title()+" by "+self.artist.title()
forms.py:(its just a simple form im using)
[![class MdataForm(ModelForm):
class Meta:
model = Mdata
fields =\[
'name',
'artist',
'album',
'genre',
'nation',
'duration',
'released_in',
'image',
'audio',
]
and here the render :dunno if this is enough
[1]: https://i.stack.imgur.com/T5eK2.png
This could be that you don't have a __str__ method on your Genre model. Add a __str__ method and return the genre name. That would be something like:
def __str__(self):
return self.name
self.name here being the field on your genre model used to specify the name. In the sample image below, I set the custom user to return the username by default, that way anywhere I call a user it will automatically show the name of the genre.
class CustomUser(AbstractUser):
id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
email = models.EmailField(_("email address"), unique=True, null=True)
phone_number = PhoneNumberField(unique=True, null=True)
username = models.CharField(max_length=100, unique=True, null=True)
password = models.CharField(_("password"), max_length=128, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "User"
verbose_name_plural = "Users"
def __str__(self):
return self.username
I'm unable to access my prefetch_related objects at my template, can smb help
views.py
def support(request, pk=None):
...
else:
list_support_tickets = sorted(
chain(
SupportTickets.objects.filter(Q(status=0) | Q(status=1), requester=request.user).prefetch_related('reply_relation'), #Can't iter object
), key=attrgetter('creation_date'), reverse=True
)
paginator = Paginator(list_support_tickets, 10)
page = request.GET.get('page')
support_tickets = paginator.get_page(page)
args = {'support_tickets': support_tickets,
'form': form
}
print(list_support_tickets)
return render(request, template, args)
At my template I do the following:
{% for support_ticket in support_tickets %}
...
{% for reply in support_ticket.reply_relation %}
<span class="font-size-small">We have a query, yeah</span>
{% endfor %}
{% endfor %}
But I'm unable get a query here, error:
TypeError: 'GenericRelatedObjectManager' object is not iterable
models.py
class SupportTicketMessages(models.Model):
content_type = models.ForeignKey(ContentType, limit_choices_to=referential_models, on_delete=models.CASCADE)
object_id = models.CharField(max_length=36)
content_object = GenericForeignKey('content_type', 'object_id')
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='support_ticket_reply_author', verbose_name='Author', blank=True)
reply = models.TextField(verbose_name="Reply Content", max_length=2000)
date = models.DateTimeField(auto_now_add=True, blank=False)
class SupportTickets(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
ticket_id = models.IntegerField(default=ticket_id_generator, unique=True, blank=False, null=False, editable=False)
requester = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False)
category = models.IntegerField(choices=TICKET_CATEGORY, verbose_name='Ticket Category')
subject = models.CharField(max_length=40)
problem_description = models.TextField(max_length=5000)
status = models.IntegerField(choices=STATUS_OF_TICKET, verbose_name='Ticket Status', default=0)
reply_relation = GenericRelation(SupportTicketMessages, related_query_name='reply_relation')
creation_date = models.DateTimeField(auto_now_add=True, null=True)
Thanks in advance
support_ticket.reply_relation is a manager, not a QuerySet, so you can not iterate over it, you use .all() [Django-doc] to iterate over this:
{% for support_ticket in support_tickets %}
…
{% for reply_relation in support_ticket.reply_relation.all %}
…
{% endfor %}
{% endfor %}
I have a simple model (kit) connected by another model(client_id) with a foreign key, and also by a ManyToMany field. I have a form view for the kit model, in which user can create new kits, by selecting a few products, and then choosing which client it is made for. Problem is, the fields are being displayed correctly, but with only ID displayed, instead of their names. User does not know what is he selecting as he does not know the ID of all products or clients. How should I approach this ? I searched on SO but found nothing useful.
Code
models.py
# Parent model connected with both models
class Kit(models.Model):
kit_name = models.CharField(max_length=255, default=0)
kit_info = models.CharField(max_length=255, default=0)
components_per_kit = models.IntegerField(default=0)
product_id = models.ManyToManyField(Product, related_name='kit_product')
quantity_per_kit = models.IntegerField(default=0)
kit_client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='kit_owner')
# connected by foreign key
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
client_company = models.CharField(max_length=255, default=0)
client_name = models.CharField(max_length=255, default=0)
# connected by many to many field
class Product(models.Model):
product_id = models.IntegerField(default=0)
product_name = models.CharField(max_length=255, default=0)
product_short_code = models.CharField(max_length=255, default=0)
product_description = models.CharField(max_length=255, default=0)
template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h2 class="mb-3">Add a new Kit</h2>
<div class="row">
<div class="col-md-6 col-sm-8 col-12">
<form method="post" novalidate>
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success">Save</button>
Nevermind
</form>
</div>
</div>
{% endblock %}
Current output
A fairly simple way to do this would be adding string representation to your models. For example in your product model add:
class Product(models.Model):
product_id = models.IntegerField(default=0)
product_name = models.CharField(max_length=255, default=0)
product_short_code = models.CharField(max_length=255, default=0)
product_description = models.CharField(max_length=255, default=0)
def __str__(self):
return self.product_name
Also, if you can use any of the model's fields in there, so for example if you want both id and name you can do something like:
def __str__(self):
return '{}: {}'.format(self.id, self.product_name)
Use __str__.
I asked for your code just in case you have some strange setup, but this is probably the easiest way for you to do it.
Change your Product model to this
class Product(models.Model):
product_id = models.IntegerField(default=0)
product_name = models.CharField(max_length=255, default=0)
product_short_code = models.CharField(max_length=255, default=0)
product_description = models.CharField(max_length=255, default=0)
def __str__(self):
return self.product_name
That will replace the Project Object (1) with whatever is in the product_name charfield.
EDIT: See below for a good comment about Python 2.
I have the following Models in Django.
from django.db import models
#Show DB Table Model
class Shows(models.Model):
show_key = models.CharField(primary_key=True, max_length=7)
show_date = models.DateField(blank=True, null=True)
show_venue = models.CharField(max_length=50, blank=True, null=True)
show_city = models.CharField(max_length=50, blank=True, null=True)
show_state = models.CharField(max_length=3, blank=True, null=True)
show_country = models.CharField(max_length=3, blank=True, null=True)
class Meta:
managed = False
db_table = 'shows'
#Songs DB Table Model
class Songs(models.Model):
song_key = models.CharField(primary_key=True, max_length=8)
show_key = models.ForeignKey('Shows', models.DO_NOTHING, db_column='show_key', blank=True, null=True)
song_name = models.CharField(max_length=100, blank=True, null=True)
song_set = models.CharField(max_length=20, blank=True, null=True)
song_track = models.IntegerField(blank=True, null=True)
song_encore = models.IntegerField(blank=True, null=True)
song_segue = models.CharField(max_length=1, blank=True, null=True)
song_notes = models.CharField(max_length=100, blank=True, null=True)
song_cover = models.CharField(max_length=50, blank=True, null=True)
song_with_guest = models.CharField(max_length=50, blank=True, null=True)
class Meta:
managed = False
db_table = 'songs'
I am trying make a query that will find all objects meeting a certain criteria, ie:
Shows.objects.filter(show_date__year=2000)
This above query would return multiple objects.
I need to take it a step further and pull all of the information from the Songs table/model relating to the filtered Show objects. The models are related in the sense that the "show_key" is a primary key / foreign key relationship and is one to many.
I also need to package all of the found data up into a usable form that I can iterate through and send to a jinja2 template.
For example:
{% for item in query_results %}
<ul>
<li>item.show_date</li>
<li>item.show_venue</li>
<li>item.show_city</li>
<li>item.show_state</li>
<li>item.show_country</li>
</ul>
<ul>
{% for song in item %}
<li>song.song_name</li>
<li>song.song_set</li>
<li>song.song_track</li>
<li>song.song_encore</li>
<li>song.song_segue</li>
<li>song.song_notes</li>
</ul>
{% endfor %}
Thanks in advance. Brent
Seems like what you're trying to do is follow a FK relationship backwards.
This is what it should look like in the template:
{% for show in query_results %}
<ul>
<li>show.show_date</li>
<li>show.show_venue</li>
<li>show.show_city</li>
<li>show.show_state</li>
<li>show.show_country</li>
</ul>
<ul>
{% for song in show.entry_set.all %}
<li>song.song_name</li>
<li>song.song_set</li>
<li>song.song_track</li>
<li>song.song_encore</li>
<li>song.song_segue</li>
<li>song.song_notes</li>
</ul>
{% endfor %}
This will actually force jango to issue one SQL query for every show. If you have too many it can be a pain. To avoid this you can tell Django to select related songs data when it queries for the shows. This can save you a lot of SQL queries.
Shows.objects.select_related(Songs).filter(show_date__year=2000)
I finally figured it out!
First I queried the Shows model/table and saved the results to query_results:
query_results = Shows.objects.filter(show_date__year=2018)
Then in my Jinja Template
{% for show in query_results %}
<ul>
<li>{{show.show_date}}</li>
<li>{{show.show_venue}}</li>
<li>{{show.show_city}}</li>
<li>{{show.show_state}}</li>
<li>{{show.show_country}}</li>
</ul>
<ul>
{% for song in show.songs_set.all %} #This is the key, calling the related "shows_set.all" This grabs the related objects from the Songs table/model
<li>{{song.song_name}}</li>
<li>{{song.song_set}}</li>
<li>{{song.song_track}}</li>
<li>{{song.song_encore}}</li>
<li>{{song.song_segue}}</li>
<li>{{song.song_notes}}</li>
{% endfor %}
</ul>
{% endfor %}
So what I say might seem complicated, but I think the answer is easy. I just can't figure it out. I have a form for a Lecture model, which a logged in teacher can use to post a lecture for his specific courses only. Thing is that in my database I have a TeacherData model which contains a teacher_ID field used for verification, so a teacher cannot create his account on the other Teacher model, if teacher_ID entered doesn't match. But when a course is created in database, the teacher used is the one from TeacherData. So to create my query I have to filter the courses based on TeacherData and then using teacher_ID, to link to Teacher model. I just don't know how to build this queryset but I replicated the wanted behaviour in the template:
{% if user.is_authenticated and user.is_teacher %}
<ul>
{% for data in teacher_data %}
{% if data.teacher_ID == user.teacher.teacher_ID %}
{% for course in courses %}
{% if course.teacher1 == data or course.teacher2 == data %}
<li>
{{ course.name }}
</li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=30, null=True, blank=True, default=None)
surname = models.CharField(max_length=50, null=True, blank=True, default=None)
email = models.EmailField(unique=True, null=True, blank=True, default=None)
teacher_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')],
null=True, blank=True, default=None)
class TeacherData(models.Model):
name = models.CharField(max_length=30)
surname = models.CharField(max_length=50)
teacher_ID = models.CharField(unique=True, max_length=14)
notes = models.CharField(max_length=255, default=None, blank=True)
class Lecture(models.Model):
LECTURE_CHOICES = (
('Courses', 'Courses'),
('Seminars', 'Seminars'),
)
course = models.ForeignKey('Course', on_delete=models.CASCADE, default='', related_name='lectures', )
lecture_category = models.CharField(max_length=10, choices=LECTURE_CHOICES, default='Courses', )
lecture_title = models.CharField(max_length=100, blank=True, null=True)
content = models.TextField(blank=False, default=None)
class Course(models.Model):
study_programme = models.ForeignKey('StudyProgramme', on_delete=models.CASCADE, default='')
name = models.CharField(max_length=50, unique=True)
ects = models.PositiveSmallIntegerField(validators=[MaxValueValidator(99)])
description = models.TextField()
year = models.PositiveSmallIntegerField(validators=[MaxValueValidator(99)])
semester = models.IntegerField(choices=((1, "1"),
(2, "2"),
), default=None)
teacher1 = models.ForeignKey('TeacherData', on_delete=models.CASCADE, default=None,
verbose_name="Course Teacher", related_name='%(class)s_course_teacher')
teacher2 = models.ForeignKey('TeacherData', on_delete=models.CASCADE, default=None, null=True,
verbose_name="Seminar Teacher", related_name='%(class)s_seminar_teacher')
class LectureForm(forms.ModelForm):
lecture_title = forms.CharField(max_length=100, required=True)
course = forms.ModelChoiceField(initial=Course.objects.first(), queryset=Course.objects.filter(
Q(teacher1__id__in=[t.id for t in TeacherData.objects.filter(
teacher_ID__iexact=[t.teacher_ID for t in Teacher.objects.all()])])))
class Meta:
model = Lecture
fields = ('course', 'lecture_category', 'lecture_title', 'content')
try this,
from django.contrib.auth.decorators import permission_required
from .models import Teacher
#permission_required( # permission class to check 'is_authenticated' and 'is_teacher')
def my_view(request):
queryset = Teacher.objects.filter(teacher_ID=request.user.teacher_ID)
if queryset:
# do something with teacher data ('queryset' holds those data)
else:
return HttpResponse("teacher id not found")