Is there a way to query.all() in peewee? - python

I need to transfer all data from an SQL table to an html page. In SQLAlchemy I would do something like this:
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
first = db.Column(db.String(80))
last = db.Column(db.String(80))
#app.route('/authors')
def get_authors():
authors = Author.query.all()
# Serialize the queryset
result = authors_schema.dump(authors)
return jsonify({'authors': result.data})
Is there a something like authors = Author.query.all() in peewee?

To my knowledge, a direct equivalent does not exist in peewee, though there is an all method in the Dataset extension, documented here. You can do this pretty easily using a list comprehension:
authors = [author for author in Author.select()]
Or even just authors = list(Author). However, if you're trying to return these as JSON, it won't work because your list of authors is populated by instances of Author and Flask's JSONEncoder will not work with this type out of the box. You can get around this by using peewee's dicts() method:
authors = [author for author in Author.select().dicts()]
The full example would look like this:
#app.route('/authors')
def get_authors():
authors = [author for author in Author.select().dicts()]
return jsonify(authors)
Instead of serializing using dicts I often use marshmallow. For example you create an author_schema like so:
from marshmallow import Schema, fields
class AuthorSchema(Schema):
id = fields.Integer(dump_only=True)
first = fields.String()
last = fields.String()
author_schema = AuthorSchema()
and use it like so (not showing imports):
#app.route('/authors')
def get_authors():
authors = author_schema(Author, many=True)
return jsonify(authors)

so i make this.
#app.route('/authors')
def get_authors():
authors = Author.select()
return render_template('aurhors.html', authors=authors)
And in html something like this.
{% for a in authors %}
<p>{{a.author_name}}</p>
{% endfor %}
I only in begining of studying python, so thank for help.

What you're looking for is .dicts(), a method well-hidden in the docs, which returns an iterable peewee-specific type:
response = {'authors': []}
authors = Author.select()
for author in authors.dicts():
response['authors'].append(author)

Something like this should work of you're working with APIs:
return list(Account.select().dicts());

Related

Access Model Method for Multiple Objects in Django

Let's say I have created a model in Django that looks like this:
class Book(models.Model):
author = models.CharField(max_length=64)
... (other attributes)
def author_pretty(self):
return "[··" + self.author + "··]"
I need to get from all objects in DB the method author_pretty, as of now I'm doing this:
authors = Book.objects.values_list('author', flat=True)
authors_pretty = ["[·" + author + "·]" for author in authors]
# or
books = Book.objects.all()
authors_pretty = [book.author_pretty() for book in books]
Is there any way of doing this in a single call? Django would still have to make a query to DB and the call the method, but maybe there is a cleaner solution that I'm missing.
It depends on how you are going to use it, if it is one by one on a template, use the method as a property
#property
def author_pretty(self):
return "[··" + self.author + "··]"
However if you want something cleaner and for some reason you need them all in once, take a look into Django Docs for Concat, Query Expressions and Annotate
from django.db.models.functions import Concat
from django.db.models import Value, CharField
Book.objects.all().annotate(author_pretty=Concat(Value(“[··”), “author”, Value(“··]”), output_field=CharField()))
And then you can use it in a for loop like a property
for author in authors:
print(author.author_pretty)

Dynamically filtering with __icontains from input field

I want to filter my fields in a model dynamically from a form input.
Already searched a lot but did not find something suitable. As i am fairly new to django and all this stuff i might not see some obvious stuff.
The form defines the field to search in and what to search(filter).
This should lead to a url like http://localhost:8000/app/search/?col=id&q=1234
In my view i would like to modify the get_queryset() function with a filter like this:
def get_queryset(self):
query1 = self.request.GET.get('q')
query2 = self.request.GET.get('col')
object_list = mymodel.objects.filter(
Q(query2__icontains = query1)
)
Is this possible?
Moe
Yes, You can do it like this.
>>> query = {f'{query2}__icontains': query1}
>>> object_list = mymodel.objects.filter(**query)

obj.authors.all() doesn't show anything

I'm trying to make a django site in the latest version of django, but when i use the obj.authors.all() it returns nothing.
I have tried getting rid of the all() but returns empty Queryset.
views.py
def menu(request):
obj = Book.objects.get(id=1)
obj = obj.authors.all()
else:
obj=""
return render(request, 'menu.html',
{'obj':obj,'numautgors':authors})
models.py
class Book(models.Model):
name = models.CharField(max_length=100,unique=True)
authors = models.ManyToManyField(User)
text = models.TextField(unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('model-detail-view', args=[str(self.id)])
I expect it to return the authors, but it returns nothing.
Sorry if a duplicate. And one more question can i show all book written by a specific author or in this case User?
You can try :
Books.objects.all().values('authors')
And suppose you want to show a book written by specific author then in that case your query should be :
Books.objects.filter(authors__username=request.user.username)
also you can use get based on your scenario
Taking assumption that your User model has username field.
I think you are sending the wrong context, so try like this:
def menu(request):
obj = Book.objects.get(id=1)
authors = obj.authors.all()
return render(request, 'menu.html', {'obj':obj,'numautgors':authors})
Alternatively you can show the authors in template directly(you don't need to pass authors to template with context at all):
{% for author in obj.authors.all %}
{{ author.id }}
{% endfor %}
You are overwriting your variables
Firstly with
obj = Book.objects.get(id=1)
You are assigning the Book object retrieven from the database to the obj variable.
Then with
obj = obj.authors.all()
You assign authors to obj again, and then you are returning authors, a variable that does not exist.
Your naming seems confusing.
If you want the authors of the book with id 1, you could do this:
authors = Book.objects.filter(id=1).authors.all()

GAE Python Query ordering won't take certain properties

In the official tutorial for GAE guestbook, I'm trying to change the order of query results like so:
greetings_query = Greeting.query(
ancestor=guestbook_key(guestbook_name)).order(Greeting.content)
Greeting looks like this:
class Greeting(ndb.Model):
content = ndb.StringProperty(indexed=False)
date = ndb.DateTimeProperty(auto_now_add=True)
Passing Greeting.date obviously works.
What could be the reason?

Referencing a related object in Pyramids/Python/SQLAlchemy

I'm not sure how to title this question. I've also simplified my code so it's easier to ask. Say I have the following code in myproject.models in Pyramid:
class Links(Base):
__tablename__ = 'links'
id = Column(Integer, primary_key=True)
link = Column(Text)
def __init__(self, link):
self.link = link
class Submissions(Base):
__tablename__ = 'submissions'
id = Column(Integer, primary_key=True)
title = Column(Text)
link_id = Column(Integer, ForeignKey('links.id'))
link = relationship(Links)
def __init__(self, title, link):
self.title = title
self.link = link
The view will be very simple:
def my_view(request):
dbsession = DBSession()
submissions = dbsession.query(Submissions)
return {'submissions':submissions}
I want to return this on my page using Chameleon:
<p tal:repeat="thing submissions">
${thing.title} ${thing.link}
</p>
However, ${thing.link} doesn't show the link of the site.
Questions:
How do I reference thing.link's link? Intuitively, I would type ${thing.link.link}, but that doesn't work.
How do I reference an arbitrary subclass? I want to be able to extract any attribute from an object's subclass, for example, thing.link.link, thing.link.domain, thing.link.created, etc.
BTW, someone please tell me a better title to give this question.
In your example, you are missing the .all() after your .query(). You can check in your view if your submissions are really loaded by doing something like
for submission in submissions:
print submission.id, submission.title
and then watch your console when loading the page.
Then, when you confirmed you really have them loaded, you can access the link object with submission.link. In the link object, you can access the link attribute with .link.
for submission in submissions:
print submission.link.link
So in your template, you could write ${thing.link.link}.
Assuming you do have the link object attached (given the fact that the link_id column is not nullable), most probably you need to (eager)load the relationship to Links because the session is alread closed when you populate your view.
See Relationship Loading Techniques for more information. The code below should do it:
submissions = dbsession.query(Submissions).options(joinedload('link'))

Categories

Resources