Django MySql, foreign key query - python

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 %}

Related

Django unable to iterate prefetch_related objects at template

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 %}

How to render data from multiple models django

I want to render data to my webpage from my django app however only two of the required slots are being rendered
my models are:
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=7, decimal_places=2)
digital = models.BooleanField(default=False,null=True, blank=True)
image = models.ImageField(null=True , blank=True)
description = models.TextField(max_length=5000, null=True)
points = models.DecimalField(max_digits=5,decimal_places=0, null=True)
and my views are
def admin_dashboard (request):
order_list = Order.objects.all()
context = {'order':order_list}
template = "admin_dashboard.html"
return render(request, 'store/admin_dashboard.html', context)
my HTML is:
{% extends 'store/admin_main.html' %}
{% load static %}
{% block content %}
{% for order in order %}
<h6>{{ order.transaction_id }}</h6>
<p>{{ order.customer }}</p>
<p>{{ order.shippingaddress }}</p>
<p>{{ order.orderitem }}</p>
{% endfor%}
{% endblock content %}
1598061443.212917
userNew
which is just the transaction id and user.
how can I have all the rest of fields filled

Django How to get a queryset from a queryset in template

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 = []

How to display field text instead of the ID for a model connected by a foreign key in Django?

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.

Need to build a Django queryset based on more models

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")

Categories

Resources