I have 2 models:
class Professors(models.Model):
professors_name = models.CharField('professor', max_length=32, unique=True)
class Discipline(models.Model):
auditorium = models.IntegerField('auditorium')
professors_name = models.ForeignKey(Professors)
In views:
disciplines = Discipline.objects.all()
So, I have number of auditorium and professors_name_id. But I need full profrssors name, not id. How to do it?
Models:
# models usually named in the singular
class Professor(models.Model):
professors_name = models.CharField('professor', max_length=32, unique=True)
class Discipline(models.Model):
auditorium = models.IntegerField('auditorium')
# your pointer is to a professor, not to the name
professor = models.ForeignKey(Professor)
In view:
# select_related('professor') to avoid a second query when accessing professor
disciplines = Discipline.objects.select_related('professor')
Template:
{% for disc in disciplines %}
{{ disc.auditorium }}: {{ disc.professor.name }}
{% endfor %}
For values:
Discipline.objects.values('auditorium', 'professor__name')
Django ORM will always returns the objects not the ids. You should have a design like this.
class Professor(models.Model):
name = models.CharField('professor', max_length=32, unique=True)
class Discipline(models.Model):
auditorium = models.IntegerField('auditorium')
professor = models.ForeignKey(Professors)
and use discipline.professor.name to retrieve the name alone.
Related
I have an intermediate models connection
Simplified:
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
etc...
class Company(models.Model):
name = models.CharField(max_length=60)
etc...
class CompanyEnrollment(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
company_position =
models.ForeignKey(CompanyPosition,on_delete=models.CASCADE)
etc...
class Meta:
unique_together = [['person', 'company']]
class CompanyPosition(models.Model):
name = models.CharField(max_length=60)
I want to create the following array:
datas = Person.objects.All(...{All elements of Person model supplemented with CompanyPosition_name}...)
There is a case where a person does not have a company_name association
Is it possible to solve this with a query?
If you have an explicit through model for your many-to-many relationship, you could use this to only get or exclude based on the entries of this table, using an Exists clause:
enrollments = CompanyEnrollment.objects.filter(person_id=OuterRef('pk'))
enrolled_persons = Person.objects.filter(Exists(enrollments))
unenrolled_persons = Person.objects.filter(~Exists(enrollments))
If you don't have an explicit intermediate table, then it's has been generated by Django directly. You should be able to use it by referring to it with Person.enrollments.through instead of CompanyEnrollment.
Since you did not detailed much the CompanyEnrollment table, I assumed you're in the second case.
This is not the best solution in my opinion, but it works for now, with little data. I think this is a slow solution for a lot of data.
views.py I will compile the two necessary dictionaries
datas = Person.objects.all().order_by('last_name', 'first_name')
companys = CompanyEnrollment.objects.all()
Use Paginator
p = Paginator(Person.objects.all(), 20)
page = request.GET.get('page')
pig = p.get_page(page)
pages = "p" * pig.paginator.num_pages
Render HTML:
context = {
"datas": datas,
"pig": pig,
"pages": pages,
"companys": companys,
}
return render(request, "XY.html", context)
HTML template:
{% for datas in pig %}
{{datas.first_name}} {{datas.last_name}}
{% for company in companys %}
{% if datas == company.person %}
{{company.company.name}} <br>
{% endif %}
{% endfor %}
{% endfor %}
not the most beautiful, but it works ... I would still accept a more elegant solution.
I am busy with a project where I have two models and I'm not sure how to do as I am fairly new to programming.
what I would like to do is have a template that
renders all the instances of first model
and then on the same template I want to have all the sales associated with each of those instances as well as the instances with different states(for example if an instance of first model is linked to 2 sales that has a state of "Confirmed" it should say 2 next to that instance name.)
class QAAgent(models.Model):
user=models.OneToOneField(User,on_delete=models.SET_NULL,null=True)
Qa_name = models.CharField(max_length=15)
def __str__(self):
return self.user.username
States = (('Pending',"Pending"),("Confirmed","Confirmed"),("Requested","Requested),("Cancelled","Cancelled"),("Not interested","Not interested"))
class Sale(models.Model):
QA = models.ForeignKey(QAAgent,on_delete=models.SET_NULL,blank=True,
null=True,related_name="sale")
State = models.CharField(choices=States,default="Pending",max_length=15)
Date_created = models.DateTimeField(auto_now_add=True)
Date_edited = models.DateTimeField(auto_now=True)
def__str__(self):
return self.client_name + " " + self.client_surname
I am not sure how to reply to answers but thanks guys that worked perfectly!
To list all your entries of the first model including it's related items you can do the following. Just be sure to pass the correct queryset to the view context.
{% for entry in qa_agent %}
{{ entry.qa_name}}
{{ entry.user.name }}
{% for sale in entry.qa_sale.all %}
{{sale.category.state }}
{% endfor %}
{% endfor %}
For your second request just create a method in your model class which filters for the desired status. I've called it get_confirmed here.
class QAAgent(models.Model):
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
qa_name = models.CharField(max_length=15) # You had Qa_name before
def get_confirmed(self):
return self.qa_sale.filter(state="Pending") # just write a method like this one for each of the other statuses.
def __str__(self):
return self.user.username
And then modify your template code so it uses this method to display the confirmed ones.
{% for entry in qa_agent %}
{{ entry.qa_name}}
{{ entry.user.name }}
{{ entry.get_confirmed.count }} # <-- like this
{% endfor %}
Just a quick side note about python code styling.
For variables and function names use snake_case. for classes use CamelCase.
So for your model properties it's best to only use lower case letters and separate words using an underscore. For classes start with an uppercase letter and separate words by using an uppercase letter for the first letter of the new word. This is how it should look like:
states = (
("Pending", "Pending"),
("Confirmed", "Confirmed"),
("Requested", "Requested"),
("Cancelled", "Cancelled"),
("Not interested", "Not interested"),
)
class Sale(models.Model):
qa = models.ForeignKey(QAAgent, on_delete=models.SET_NULL, blank=True, null=True, related_name="qa_sale")
state = models.CharField(choices=States, default="Pending", max_length=15)
date_created = models.DateTimeField(auto_now_add=True)
date_edited = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.client_name} {self.client_surname}" # If you concatenate strings use an fstring like I did here. It's more readable
I'm moving my first steps with django and I'm trying to figure out a thing.
Suppose that we have a model.py made like this where NameEffect has a many to many relation
class Name(models.Model):
nameid = models.IntegerField()
name = models.CharField(max_length=255)
class Effect(models.Model):
effectid = models.IntegerField()
effect = models.TextField()
class NameEffect(models.Model):
nameid = models.IntegerField()
effectid = models.IntegerField()
start = models.PositiveIntegerField()
strand = models.PositiveIntegerField()
and I want to create a QuerySet where every entry contains name,effect,start,strand of the researched name. Fact is that the only solution I found was using raw SQL queries but I can't understand how to do it with the django models approach
You haven't defined any relationships here at all. You should identify the fields as ForeignKeys - and also define the implicit many-to-many relationship explicitly (although you don't actually need it for this particular query, but it'll definitely come in useful).
class Name(models.Model):
nameid = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255)
effects = models.ManyToManyField('Effect', through='NameEffect')
class Effect(models.Model):
effectid = models.IntegerField(primary_key=True)
effect = models.TextField()
class NameEffect(models.Model):
name = models.ForeignKey('Name', db_column='nameid')
effect = models.ForeignKey('Effect', db_column='effectid')
start = models.PositiveIntegerField()
strand = models.PositiveIntegerField()
Now you can can query NameEffect directly to get the result you want.
data = NameEffect.objects.values('name__name', 'effect__effect', 'start', 'strand')
Also note, unless you know you really need just these fields, you should avoid using values and just query NameEffect using select_related:
name_effects = NameEffect.objects.select_related('name', 'effect')
and then access the values when you need them, eg in a template:
{% for obj in name_effects %}
{{ obj.name.name }}
{{ obj.effect.effect }}
{{ obj.start }}
{{ obj.strand }}
{% endif %}
I am trying to perform a query via a join.
My models.py looks like:
class TSFH(models.Model):
sB = models.DateTimeField(null=True)
sE = models.DateTimeField(null=True)
FKToUser = models.ForeignKey(User,default=None, on_delete=models.PROTECT)
class Tld(models.Model):
dNm = models.CharField(verbose_name="",max_length=40,unique=True)
FKToUser = models.ForeignKey('auth.user', default=None, on_delete=models.PROTECT)
class TSF(models.Model):
FKToT = models.ForeignKey('T', on_delete=models.PROTECT)
FKToTSFH = models.ForeignKey('TSFH', on_delete=models.PROTECT, null=True, blank=True)
views.py
enteredd = request.GET.get('d', '')
query=TSFH.objects.filter(FKToT__dNm=enteredd,FKToUser=request.user,sE__isnull=False)
return render(request, 'view.html', {'q':q})
templates/file.html
{% if q %}
{% for res in q %}
<li><span>{{ res.sE }}</span></li>
{% endfor %}
{% else %}
{% endif %}
When I view this all it complains about:
Cannot resolve keyword 'FKToT' into field
In plain sql I'm looking to perform the following just with dNm search directly from the enteredd instead of a hardcoded value of 123.145.23.1 as shown below:
SELECT sE
FROM tsfh, tsf, t
where
tsfh.id=tsf.FKTotsfh_id
and
t.id=tsf.FKToT_id
and
tsfh.sE is not null
and
t.dNm='123.145.23.1';
How can I keep these existing checks in the query but include this FKToT__dNm=enteredd somehow?
Thank you very much.
Do a little modification at this line:
query=TSFH.objects.filter(TST__FKToT__dNm=......)
If you put this meta into your class, it will specifically name the table.
class Meta:
db_table = '<your_table_name>'
You can read more here.
I need several models that inherit from a base class in a one-to-one relationship. In keeping with the Django example:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
class Garage(Place):
car_brands_serviced = Models.ManyToManyField(Brands)
class Boutique(Place):
for = Models.ChoiceField(choices=( ("m", "men"), ("w", "women"), ("k","kids"))
# etc
Now how do I effectively distinguish between the various types of Places when I iterated them in a template (or view function)? Right now, I only see this solution (if I want to iterate over Places, rather than child models individually):
for place in Place.objects.all():
try:
r = place.restaurant
# Do restaurant stuff here
except ObjectDoesNotExist:
try:
g = place.garage
# Do garage stuff here
except ObjectDoesNotExist:
try:
b = place.boutique
# Do boutique stuff here
except ObjectDoesNotExist:
# Place is not specified
Not even sure how that would translate to a template, but this code seems very wrong and inefficient.
As an escape, I guess you could make a choicefield in Place to track which child model is related, but that equates to dangerous denormalisation.
Am I somehow overthinking this? How do you do this?
Could it be something simple like:
models.py:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
is_restaurant = True
class Garage(Place):
car_brands_serviced = Models.ManyToManyField(Brands)
is_garage = True
A template could work like this – template.html:
{% for place in places %}
{% if place.is_restaurant %}
<!-- Restaurant Stuff -->
{% elif place.is_garage %}
<!-- Garage Stuff -->
{% endif %}
{% endfor %}