How to select distinct column values from mysql database in django? - python

I need to retrieve distinct value from query set and display it on a div.
Here is my model.py:
class Persons(models.Model):
id = models.IntegerField(primary_key=True)
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
address = models.CharField(max_length=100)
dob = models.CharField(max_length=100)
salary = models.IntegerField
doj = models.DateField()
class Meta:
db_table = "test"
Here is my view.py:
def calender(request):
distinctyears = Persons.objects.all().values('doj').distinct()
year = {
"Items": distinctyears
}
return render(request, "home.html", year)
Here is my html :
<div>
{% for item in Items %}
<div class="numbers">{{ item.doj }}</div>
{% endfor %}
</div>
My code is not working. Any help will be highly appreciated.
Thank You!

You need to add .distinct([*fields]) at the end of your query.
Here's the difference. For a normal distinct() call, the database compares each field in each row when determining which rows are distinct. For a distinct() call with specified field names, the database will only compare the specified field names.
As stated all fields in a record are checked. Mostly likely in your case you are getting records with different field values (more likely a case if you are queries multiple tables ManyToMany or ForeignKey relations).

Related

How to filter out duplicate rows from child model before being displayed in Django ListView

I am using two related models in my Django application. The objects so created in the models are being displayed using the listview class. In the child model I can create multiple rows based on some key date. When I try to display values from both the models (linked with an FK field), all the child objects for the respective FK fields are displayed (wherever more than one records are there).
Is there a way that I may use select distinct to filter out duplicate rows. I have tried:
myModel.objects.distinct().order_by('id')
but still getting all the child rows for the parent id.
In my template I am using:
{% for obj in object_list %}
{{ obj.<field1> }} <!-- field1: Parent model field -->
{% for item in obj.<child_model>_set.all %}
{{ item.<field2> }} <!-- field2: Child model field -->
{% endfor %}
{% endfor %}
My question is:
How do I filter out duplicate rows before the data is displayed?
The backend is sqlite3 on Django 2.0.6 / Python 3.6
Edit
This is how the current list is being generated:
The first column is pk of parent model record and the next column is for child records' pk.
What I am trying to get is:
Option 1: Get only the last (date wise) record for the combination of parent/child rec numbers (i.e. for parent record number 32, only the combination 32|156 should be displayed, and those with values for child records 149 and 148 should not be displayed).
OR
Option 2: Get all combination of records grouped by ParentModel pk field and ChildModel pk field to be shown separately in successive rows (as you can see, the multiple values for a parent record (wherever existing), is being shown in the same row, successive columns).
PS. I am sorry things are getting quite dense here.
Edit 2
This is the class view I am using for displaying data:
class myRateListView(ListView):
template_name = "rate_list.html"
context_object_name = 'ratelists'
model = ParentModel
def get_context_data(self, **kwargs):
context = super(myRateListView, self).get_context_data(**kwargs)
context.update({
'rate_item_list': ChildModel.objects.order_by('field3'),
})
return context
def get_queryset(self):
return ParentModel.objects.values('field1', 'childmodel__field2').distinct()
Here I am getting error :
Cannot resolve keyword 'childmodel' into field. Choices are....
I think my class view is wrong??
Edit 3
Models and view details:
models.py
class TptRateDoc(models.Model):
tpt_rate_doc_number = models.IntegerField(null=True, blank=True.....)
loc_from = models.ForeignKey(Location, related_name='locn_from', on_delete=.......)
loc_to = models.ForeignKey(Location, related_name='locn_to', on_delete=.......)
create_date = models.DateField(default=timezone.now,...)
class TptRateItems(models.Model):
tpt_doc_header = models.ForeignKey(TptRateDoc, on_delete=...)
tpt_rate_item_num = models.CharField(max_length=3, default=10,...)
tpt_rate_valid_from_date = models.DateField(null=True, verbose_name='From date')
tpt_rate_valid_to_date = models.DateField(null=True, verbose_name='To date')
tpt_rate = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True,...)
views.py
class TptRateListView(ListView):
template_name = "tpt_rate_list.html"
context_object_name = 'tptrates'
model = TptRateDoc
def get_context_data(self, **kwargs):
context = super(TptRateListView, self).get_context_data(**kwargs)
context.update({
'tpt_rate_item_list': TptRateItems.objects.order_by('tpt_rate_valid_to_date'), # .distinct()
})
return context
def get_queryset(self):
# return TptRateDoc.objects.order_by('loc_from')
return TptRateDoc.objects.values('tpt_rate_doc_number', 'tptrateitems__tpt_rate_item_num').distinct()
Note: The commented out parts are what I had tried earlier.
did you try to catch the returned queryset of distinct filter to a new queryset? I mean like this:(* according docs, distinct will come after order_by())
queryset = myModel.objects.order_by('id').distinct()
and then pass this updated queryset to template.
return render(request, "html_file.html", { "objects": queryset})
On PostgreSQL only, you can pass positional arguments (*fields) in order to specify the names of fields to which the DISTINCT should apply. This translates to a SELECT DISTINCT ON SQL query. Here’s the difference. For a normal distinct() call, the database compares each field in each row when determining which rows are distinct. For a distinct() call with specified field names, the database will only compare the specified field names.
You have not stated when you consider objects to be "distinct". If you do somthing like
queryset = MyModel.objects.distinct()
your queryset will contain all the MyModel instances. Why? Because each instance will have a different id (or pk) even if all other fields are identical. So for distinct() to work you need to specifify the fields to consider, i.e. you need to use values(). So in order to get a queryset containing the distinct values of field2 in your ChildModel you would need to do something like
queryset = ChildModel.objects.values('field2').distinct()
So if I understand you correctly you want to display all "field1" values and associated "field2" values where "field2" values should be unique. What I would recomend is a 2 step approach.
First in your view create a queryset containing distinct combinations of field1 and field2, e.g.:
queryset = ParentModel.objects.values('field1', 'childmodel__field2').distinct()
and then pass this queryset to your template
return render(request, 'parent_child.html', {'objects': queryset})
Then, in order to do the hierachical rendering, you can use the {% regroup %} template tag as described in the docs:
{% regroup objects by field1 as obj_list %}
<ul>
{% for obj in obj_list %}
<li>
{{ obj.grouper }}
<ul>
{% for child in obj.list %}
<li>
{{ child.childmodel__field2 }}
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
As OP has not posted his models these are the models used for this answer
class ParentModel(models.Model):
field1 = models.CharField(max_length=100)
class ChildModel(models.Model):
parentmodel = models.ForeignKey(ParentModel, on_delete=models.CASCADE)
field2 = models.CharField(max_length=100)
field3 = models.IntegerField()

SQLAlchemy query tables joined with foreign key

I am trying to display data from MySQL via Flask-SQLAlchemy query and change foreign key (category_id) into name assign to the category_id. To be more precise -
With the query I want to display item with the name from category Table, not the category_id.
Here is my code:
class MyEnum(enum.Enum):
piece = "piece"
kg = "kg"
class Category(db.Model):
__tablename__ = 'category'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25), nullable=False)
class Product(db.Model):
__tablename__ = 'product'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
product_type = db.Column(db.Enum(MyEnum), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
description = db.Column(db.String(255))
category = db.relationship("Categ{{user.id}}ory",
backref=('products'))
def __init__(self,name, quantity, product_type, category_id, description):
self.name = name
self.quantity = quantity
self.product_type = product_type
self.category_id = category_id
self.description = description
db.create_all()
db.session.commit()
#app.route('/grocery-list', methods=['GET'])
def display_data():
data = Product.query.all()
category_name = db.session.query(Product).join(Category, Product.category_id == Category.name)
return render_template('query_database.html', data=data, category_name = category_name)
#query_database.html
<body>
{% for user in data %}
<li>{{user.id}}. {{user.name}} {{user.quantity}} {{user.product_type}} Category {{user.category_id}} {{user.description}}</li>
{% endfor %}
{{ category_name }}
</body>
Result of query_Database.html:
3. Ziemniaczki 2 MyEnum.kg Category 1 Na obiad
SELECT product.id AS product_id, product.name AS
product_name,product.quantity AS product_quantity, product.product_type AS product_product_type, product.category_id AS product_category_id,
product.description AS product_description FROM product INNER JOIN category ON product.category_id = category.name
Questions:
1) How to create such query? I got overview how should this look like in pure SQL but I can't find equivalent in documentation of SqlAlchemy :
select p.name, c.name
from product as p
join category as c
on c.id = p.category_id
2) What MyEnum.kg is doing out there? How to delete the My.Enum from the this view?
EDIT - Success
Just leaving the working code, if someone would ever need so.
#app.route('/grocery-list', methods=['GET'])
def display_data():
data = db.session.query(Product, Category).join(Category).all()
return render_template('query_database.html', data=data)
{% for user, category in data %}
<li>{{user.id}}. {{user.name}} {{user.quantity}} {{user.product_type}} Category {{user.category.name}} {{user.description}}</li>
{% endfor %}
Solution
After joining tables, in template file it's required to unpack the value of the category.name with
{{user.category.name}}
1) How to create such query? I got overview how should this look like in pure SQL but I can't find equivalent in documentation of SqlAlchemy
Here are some links that you might find useful:
Querying with Joins
Query.join()
Using Joins
sqlalchemy: how to join several tables by one query?
Since you've defined the ORM relationship between Product and Category, you can eager load the related categories along with the products:
data = Product.query.options(db.joinedload(Product.category)).all()
and then you can access user.category.name in your template without it emitting new queries. Another, more SQL-esque solution, would be to fetch Product, Category tuples, which seems like what you were after:
# No need to explicitly define the ON clause of the join, unless you
# really want to. SQLAlchemy examines the foreign key(s) and does what
# needs to be done.
data = db.session.query(Product, Category).join(Category).all()
and then in your template you'd unpack the result tuples:
<!-- I don't understand why it's called "user" -->
{% for user, category in data %}
...
{% endfor %}
2) What MyEnum.kg is doing out there? How to delete the My.Enum from the this view?
That's just the string representation of an enum:
In [4]: str(MyEnum.kg)
Out[4]: 'MyEnum.kg'
You'll want to modify {{user.product_type}} to suit your needs, if you're unhappy with it. You've used the SQLAlchemy Enum type and a PEP-435-compliant enumerated class for that column:
When using an enumerated class, the enumerated objects are used both for input and output, rather than strings as is the case with a plain-string enumerated type...

How can I establish grouping in Django through models?

I created a model named MenuItems which will allow for me to enter all of the items that a restaurant has on their menu, later I will use these on the front end. I also created a model name MenuGrouping so that on the front end, I can have Bootstrap tabs show the group_title and under each, show the items in that group. What field should I add in the MenuItems model to associate it to a group? I attempted to use group = models.ForeignKey(MenuGrouping) but then I run into the issue of showing each item in the specific group.
Models.py:
class MenuItems(models.Model):
menu_item_title = models.CharField(max_length=256)
menu_item_description = models.TextField()
menu_item_price = models.DecimalField(max_digits=4, decimal_places=2)
customer_favorite = models.BooleanField(default=False)
is_on_menu = models.BooleanField(default=True)
class Meta:
ordering = ('menu_item_title', )
class MenuGrouping(models.Model):
group_title = models.CharField(max_length=256)
Is there a relationship that I can add in the MenuGrouping model that I can associate multiple MenuItems?
Thank you in advance!
If I understand you correctly that you are trying to make groups like drink, food, desert and ... then here it is:
Each item can be only in one group (I mean soda is a drink and it can't be food too and etc). So what you need to do here is to add a field to MenuItems model.
your MenuItems should be like this:
class MenuItems(models.Model):
menu_item_title = models.CharField(max_length=256)
menu_item_description = models.TextField()
menu_item_price = models.DecimalField(max_digits=4, decimal_places=2)
customer_favorite = models.BooleanField(default=False)
is_on_menu = models.BooleanField(default=True)
group = models.ForeignKey(MenuGrouping)
Now to use this in your template first get the groups in view and send them to template and then:
{% for group in groups %)
# add your tabs or just print the group name. or how ever you want.
Group {{ group.group_title }}:
# and now you can list the items in this group here
{% for item in group.menuitems_set.all %}
Title is: {{ item.menu_item_title }}
Price is: {{ item.menu_item_price }}
...
{% endfor %}
{% endfor %}
If you need all items to be listed somewhere else out of groups or any other way just send the items to the template too.
Here is the Many to One relationship documentation :
Many-to-one relationships
Also you can add a m2m relation to MenuGrouping and add items to each group but then one item can be in multiple groups and for a restaurant menu I can't see how that might happen.

Django - filtering on foreign key

I have a problem about filter in django. Please help me. I want to display the objects of the product which has different categories when I click on l.category_name
my html (CategoryList.html):
{% for l in forms %}
<h2>{{ l.category_name }}</h2>
{% endfor %}
CategoryView.html
{{get_product.product_name}}
my model:
class Category(models.Model):
category_id = models.AutoField(primary_key = True)
category_name = models.CharField(max_length = 20)
def __unicode__(self):
return self.category_name
class Product(models.Model):
product_id = models.AutoField(primary_key = True)
product_name = models.CharField(max_length = 50)
product_category = models.ForeignKey(Category)
product_color = models.CharField(max_length = 30)
def __unicode__(self):
return self.product_name
my view:
def category_list(request):
list = Category.objects.all()
context = {'forms':list}
return render(request,'webpage/CategoryList.html',context)
def category_view(request,category_id):
all = Product.objects.all()
if request.POST:
get_id = Category.objects.get(category_id = request.POST['category_id'])
get_category = Product.objects.get(product_category =
request.POST['product_category'])
get_category.product_category = get_id
get_category.save()
if get_category:
get_product = Product.objects.filter(product_category__category_name =
request.POST['category_name'])
context = {'get_product':get_product}
return render(request,'webpage/CategoryView.html',context)
I read document in https://docs.djangoproject.com/en/1.6/topics/db/queries/ but i don't understand .I know i was wrong category_view
There seem to be a lot of problems with your code.
First, you don't have to declare ids in your code. Django does that automatically for you. So, categor_id and product_id are unnecessary.
Second,
Remove the .POST check. You aren't posting anything.
Third,
get_id = Category.objects.get(category_id = request.POST['category_id']) # returns a category, not an id
get_category = Product.objects.get(product_category =
request.POST['product_category']) # returns the product list, not a category
get_category.product_category = get_id
is the same as
category = Category.objects.get(category_id = request.POST['category_id'])
product_list = Product.objects.get(product_category = category)
Fourth, don't hardcode URLs in your template. Use the {% url %} tag instead.
Finally,
You can then pass this product_list to the template
context = {'product_list':product_list}
return render(request,'webpage/CategoryView.html',context)
The way foreign keys are stored is through automatic fields(IDs). Since 'Category' is a foreign field of 'Product', when you make a record entry, the id of category is stored in 'product_category' field in products table.
I think your code is a little confusing since you are trying to do somethings django does automatically for you. Like, once you define a foreign key, the id of the foreign key table record is stored automatically, you don't have to get the id of 'category' entry and store it in products table entry.
What you are trying to achieve is simple, lets say you have the category_name and nothing else, get the id of the category table entry,
category_object = Category.objects.get(category_name = category_name)
category_id = category_object .id
If you already have the ID of category, then you can skip the above step, and simply use the ID to query the products table to get the needed records
Product.objects.filter(product_category = category_id)
In your templates, you can iterate through these product records and display whatever is needed.
BTW, use the .update() method to update any fields instead of save() method.
Something like this:
Entry.objects.all().update(blog=b)
It will be well worth your time reading through the queries help.
Django queries

compare two fields data from database

models.py
class ReportType(models.Model):
report = models.ForeignKey(Report)
title = models.CharField('Incident Type', max_length=200)
class Report(models.Model):
user = models.ForeignKey(User, null=False)
app_uuid = models.CharField('Unique App Id', max_length=100)
class Types(models.Model):
user = models.ForeignKey(User, null=True)
title = models.CharField('Incident Type', max_length=200)
is_active = models.BooleanField('Is Active', default=True)
In Types table,i am saving some default data in title field.The data entered by user are saved in ReportType table.
I want to compare the data in title field in Types model and ReportType model.After comparison,if title field data in ReportType model is not present in Types model,i need to display that in template.I need to show the non matching value present in ReportType model.
template.html
{% for type in report_type %}
{{type.title}}{% endfor %}
I tried with this query
report_type = Report.objects.filter(reporttype__title=F('types__title'))
I am getting this error "Cannot resolve keyword 'types' into field",this is because Types table don't have relation with Report table.Need help.
It seems you need at least 2 queries then:
# get all types as a list
all_types = Types.objects.values_list('title', flat=True)
# you need to show the mismatch, then use exclude()
report_type = ReportType.objects.exclude(title__in=all_types)
Hope it helps.
You can filter ReportType objects and get Reports from result queryset like this:
ReportType.objects.values_list('report').filter(title__in=Types.objects.values_list('title', flat=True).distinct())

Categories