I want to join 3 tables and get the results of them without any duplicates
SELECT * FROM `database`.project
INNER JOIN post on project.id = post.project_id
INNER JOIN media on media.post_id = post.id
;
Current output
I was wondering if the output could be something like
floaty
Headphone
fasion + technolgie
I tried using the distinct function. but then it only returns the names's i would like to return the joined tables, because i still want to use that data.
models.py
I am using the Project.with_media() all
"""models."""
from app import db
from peewee import *
import datetime
class Project(Model):
"""Projects."""
name = CharField(unique=True)
content = CharField()
created_date = DateTimeField(default=datetime.datetime.today())
class Meta(object):
"""Select database."""
database = db
def get_project_media(self):
"""Grab image from get_posts."""
post = Post.select().where(Post.project_id == self).get()
return Media.select().where(Media.post_id == post).get().media
def check_media(self):
"""Check if project has media."""
try:
post = Post.select().where(Post.project_id == self).get()
Media.select().where(Media.post_id == post.id).get()
print('True')
return True
except DoesNotExist:
print('False')
return False
This is my calling so i can display it on jinja engine
def with_media():
"""Grab image from get_posts."""
return (Project.select(Project, Post, Media)
.join(Post)
.join(Media)
.where(Post.id == Media.post_id
and
Project.id == Post.project_id))
def posts(self):
"""Return all posts that are accosicated with this project."""
return Post.select().where(Post.project_id == self)
def media_post(self):
"""Return all posts that are accosicated with this project."""
post = Post.select().where(Post.project_id == self)
return post.get_media()
# return Media.select().where(Media.post_id == post).get()
class Post(Model):
"""Model for posts."""
project = ForeignKeyField(Project, backref='Post', null=True, default=None)
name = CharField()
content = TextField()
"Media Model"
"Category Model"
"Project Model"
created_date = DateTimeField(default=datetime.datetime.today())
class Meta(object):
"""Select database."""
database = db
def get_category(self):
"""Grab all the posts from project."""
return (Category.select()
.where(Category.post_id == self))
def get_media(self):
"""Grab all media from this post."""
return (Media.select()
.where(Media.post_id == self))
def standalone():
"""Return a model of all posts not bound to a project."""
return (Post.select()
.where(Post.project.is_null())
.order_by(Post.created_date.desc()))
def date():
"""Return dates order_by."""
return(Post.select()
.order_by(Post.created_date.desc()))
class Media(Model):
"""Media for post."""
post = ForeignKeyField(Post, backref='Media')
media = CharField()
class Meta(object):
"""Select database."""
database = db
class Category(Model):
"""model for all avaible category's."""
post = ForeignKeyField(Post, backref='Category')
name = CharField()
class Meta(object):
"""Select database."""
database = db
def get_name():
"""Get all category's without overlaping."""
categorys = Category.select()
categoryList = []
for category in categorys:
categoryName = category.name.title()
if categoryName not in categoryList:
categoryList.append(categoryName)
return categoryList
def initialize():
"""Create tables."""
db.connect()
db.create_tables([Category, Project, Post, Media], safe=True)
db.close()
main.py
I want to call the projects with media() function so i can use the database items to call images and display content
<ul class='projects'>
{% for project in projects.with_media() %}
{% if loop.index <= 3 %}
<li class='project_w'>
<img src="{{project.media_post()}}" alt="">
<a href="{{url_for('project', id=project.id)}}">
<h2>{{project.name}}</h2>
</a>
</li>
{% else %}
<li class='project_h'>
<img src="{{project.post.media.media}}" alt="">
<a href="{{url_for('project', id=project.id)}}">
<h2>{{project.name}}</h2>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
The problem:
.where(Post.id == Media.post_id
and
Project.id == Post.project_id))
Instead of "and" you must use "&". Please see http://docs.peewee-orm.com/en/latest/peewee/query_operators.html
Related
I am rendering data from my views into my template, as follows:
<tbody>
{% for item in lyrics %}
<tr class='lyrics-table'>
<td>{{item}}</td>
<td>
{% if item in user_flash %}
<p>{{flash}}</p>
{% else %}
<p>xxx</p>
{% endif %}
</td>
{{item}} works as expected, but {{flash}} only gives the same value for every row, instead of the relevant value.
My views are as follows:
class SongVocab(LoginRequiredMixin, generic.DetailView):
model= models.Song
template_name = 'videos/song_vocab.html'
context_object_name = 'song'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
from pymystem3 import Mystem
m = Mystem()
user_flash = Flashcard.objects.filter(owner=self.request.user).values_list('question', flat=True)
lyrics_list = models.Song.objects.get().lyrics_as_list()
user_flash_ = [item.replace('\n', ' ') for item in m.lemmatize(" ".join(user_flash))]
user_flash_clean = [w for w in user_flash_ if w.strip()] ##removes empty strings
lyrics_list_ = [item.replace('\n', ' ') for item in m.lemmatize(" ".join(lyrics_list))]
lyrics_list_clean = [w for w in lyrics_list_ if len(w.strip())]
user_word = list(set(user_flash_clean) & set(lyrics_list_clean))
import icu # PyICU
def sorted_strings(strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
context['percent_known'] = ((len(user_word))/(len(set(lyrics_list_clean))))*100
context['lyrics'] = sorted_strings(set(lyrics_list_clean),"ru_RU.UTF8")
context['user_flash'] = user_flash_clean
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash'] = flash.answer
return context
I thought that using the for loop would let me get flash.answer for all words in user_word. In the example I'm testing, there should be two words, but I get just one. What am I doing wrong?
Models.py:
class Flashcard(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
deck = models.ForeignKey(Deck, on_delete=models.CASCADE)
question = models.TextField()
answer = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
last_shown_at = models.DateTimeField(auto_now_add=True)
next_due_date = models.DateTimeField(default=timezone.now)
difficulty = models.FloatField(default=2.5)
consec_correct_answers = models.IntegerField(default=0)
objects = FlashcardManager()
def __str__(self):
return self.question
def number_of_questions(self):
return self.question.count(deck=deck.id)
In your code
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash'] = flash.answer
context['flash'] will hold the last flash.answer, because the last line is outside the for-loop (it has one indentation level less than the second line).
Did you perhaps mean something like this?
context['flash_list'] = []
for word in user_word:
flash = Flashcard.objects.get(owner=self.request.user, question=word)
context['flash_list'].append(flash.answer)
How can I iterate over the results returned by session.query from a database and print them in a flask template?
I have the following code where I am able to successfully iterate over the results returned from database and print employees name outside of my flask app.
I am just not able to figure out as how to use the following code and print out the employees name in a flask template:
def getEmployees():
engine = create_engine('mssql+pyodbc://<server name>/<DB name>?driver=SQL+Server+Native+Client+11.0')
Base = declarative_base(engine)
class Bookmarks(Base):
__tablename__ = 'table name'
Employee = Column(String(50))
__table_args__ = {'autoload':True}
def loadSession():
metadata = Base.metadata
Session = sessionmaker(bind=engine)
session = Session()
return session
if __name__ == "__main__":
session = loadSession()
results = Bookmarks.query.filter_by(Manager='Bob')
Route:
#app.route('/employeesName', methods=['GET')
def employeesName():
if request.method == 'GET':
return render_template('getEmployees.html')
Template (getEmployees.html):
<h2>Results</h2>
{% for employees in results %}
{{ employees.Employee }}
{% endfor %}
How can I print employees name filtered by Manager = 'Bob' in the flask template?
Thank you so much!
figured this out.
I was supposed to add function name while rendering the template:
#app.route('/employeesName', methods=['GET')
def employeesName():
if request.method == 'GET':
return render_template('getEmployees.html', results=getEmployees())
I am trying to set initial, default value on select box created by DjangoFilter ChoiceFilter (more info here). Code seems to be pretty simple:
class MyFilter(FilterSet):
CHOICES = (
('', 'Any'),
('closed', 'Closed'),
('new', 'New'),
)
my_select_box = ChoiceFilter(choices=CHOICES, initial='new')
class Meta:
model = MyModel
fields = ('my_select_box')
def __init__(self, *args, **kwargs):
super(MyFilter, self).__init__(*args, **kwargs)
self.form.helper = FormHelper()
self.form.helper.form_method = 'get'
self.form.helper.add_input(Submit('submit', 'Search'))
self.form.helper.form_class = 'form-inline'
self.form.helper.field_class = 'm-r m-b-sm'
self.form.helper.label_class = 'm-r'
On views.py:
class MyView(BaseListView):
content_template = "template.html"
model = MyModel
filter_class = MyFilter
table_class = MyTable
class BaseListView(BaseView, MultipleObjectMixin, SingleTableMixin):
table_class = None
filter_class = None
queryset = None
list = None
dictionary = {}
def get_context_data(self, **kwargs):
if self.list is not None:
self.object_list = self.list
else:
if self.queryset is None:
self.queryset = self.get_queryset()
self.object_list = self.queryset
if self.filter_class is not None:
filter = self.filter_class(self.request.GET, queryset=self.object_list)
table = self.table_class(filter.qs)
# filter.form.fields['my_select_box'].default = 'new'
# filter.form.initial['my_select_box'] = 'new'
ids = json.dumps(list(filter.qs.values_list('id', flat=True)))
else:
filter = ""
table = self.table_class(self.object_list)
ids = [obj['id'] for obj in self.object_list] if self.object_list is list else None
RequestConfig(self.request, paginate={"per_page": 10}).configure(table)
kwargs['content'] = render_to_string(self.content_template, context_instance=RequestContext(self.request),
dictionary=dict(
{'filter': filter, 'object_list': self.object_list, 'ids_list': ids,
'table': table}.items() + self.dictionary.items()))
context = super(BaseListView, self).get_context_data(**kwargs)
return context
On template.html:
<div class="panel-body">
<section class="panel panel-default">
<header class="panel-heading font-bold">
Filter
</header>
<div class="panel-body">
{% crispy filter.form %}
</div>
</section>
{% render_table table %}
</div>
On template side I can see with debugger that form.my_select_box.initial is set to be 'new'. But well, its not working (instead of 'new' I was trying also integers). If I change CHOICES to be like this:
CHOICES = (
('any', 'Any'),
('closed', 'Closed'),
('', 'New'),
)
It seems to work - but I don't have value from "New" selection, which makes things rough later - I can of course swap my '' value to become 'new', and 'any' to become '' on the backend in views.py by editing request.GET (not pretty solution though), but after page refresh if I used New, I see results for New, but selections displays Any (and opposite).
I believe solution can be achieved on server side (I don't want JS)?
I have a Django model (db is PostgreSQL) with a datetime field for publication date:
class Story(models.Model):
...
pub_date = models.DateTimeField(default=datetime.datetime.now)
...
And a template tag to get those objects for a given month and year:
from django import template
from news.models import Story
class StoryYearListNode(template.Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
context[self.varname] = Story.live.dates("pub_date", "year").reverse()
return ''
def do_get_story_year_list(parser, token):
"""
Gets a list of years in which stories are published.
Syntax::
{% get_story_year_list as [varname] %}
Example::
{% get_story_year_list as year_list %}
"""
bits = token.contents.split()
if len(bits) != 3:
raise template.TemplateSyntaxError, "'%s' tag takes two arguements" % bits[0]
if bits[1] != "as":
raise template.TemplateSyntaxError, "First arguement to '%s' tag must be 'as'" % bits[0]
return StoryYearListNode(bits[2])
class StoryMonthListNode(template.Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
context[self.varname] = Story.live.dates("pub_date", "month").reverse()
return ''
def do_get_story_month_list(parser, token):
"""
Gets a list of months in which stories are published.
Syntax::
{% get_story_month_list as [varname] %}
Example::
{% get_story_month_list as month_list %}
"""
bits = token.contents.split()
if len(bits) != 3:
raise template.TemplateSyntaxError, "'%s' tag takes two arguements" % bits[0]
if bits[1] != "as":
raise template.TemplateSyntaxError, "First arguement to '%s' tag must be 'as'" % bits[0]
return StoryMonthListNode(bits[2])
register = template.Library()
register.tag('get_story_month_list', do_get_story_month_list)
register.tag('get_story_year_list', do_get_story_year_list)
But when I use the tag on a template, the date (using get_story_month_list as an example) is one month or year back from the pub date:
{% load date%}
{% get_story_month_list as month_list %}
<ul class="list-unstyled">
{% for month in month_list %}
<li>{{ month|date:"F Y" }}</li>
{% endfor %}
</ul>
Any clue what I'm doing wrong?
auto_now=True did'nt worked for me in django 1.4.1 but the below code saved me.
from django.utils.timezone import get_current_timezone
from datetime import datetime
class EntryVote(models.Model):
voted_on = models.DateTimeField(auto_now=True)
def save(self, *args, **kwargs):
self.voted_on = datetime.now().replace(tzinfo=get_current_timezone())
super(EntryVote, self).save(*args, **kwargs)
I'm trying to understand how to edit or update a model. I have tried several scenarios which sometimes give an error message: 405 Method Not Allowed - The method POST is not allowed for this resource. Below is my code:
The Python Models:
import os
import webapp2
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext.webapp import template
class MessageModel(db.Model):
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class Message(webapp2.RequestHandler):
def get(self):
doRender(self,'message.htm')
def post(self):
m = MessageModel()
m.content = self.request.get('content')
m.put()
self.redirect('/view')
class View(webapp2.RequestHandler):
def get(self):
que = db.Query(MessageModel)
messageview_list = que.fetch(999)
doRender(self,
'view.htm',
{'messageview_list': messageview_list })
class Edit(webapp2.RequestHandler):
def get(self):
doRender(self,'edit.htm')
def post(self):
updated_content = self.request.get('content')
content_query = db.GqlQuery("SELECT * "
"FROM MessageModel "
"ORDER BY date DESC LIMIT 1")
messageview_list = content_query.fetch(1)
m = MessageModel()
m.content = self.request.get(updated_content)
m.put()
doRender(self,
'edit.htm',
{'messageview_list': messageview_list })
class Main(webapp2.RequestHandler):
def get(self):
doRender(self,'index.htm')
def doRender(handler, tname = 'index.htm', values = { }):
temp = os.path.join(
os.path.dirname(__file__),
'templates/' + tname)
if not os.path.isfile(temp):
return False
newval = dict(values)
newval['path'] = handler.request.path
outstr = template.render(temp, newval)
handler.response.out.write(outstr)
return True
app = webapp2.WSGIApplication([('/', Main),
('/message', Message),
('/view', View),
('/edit', Edit)],
debug=True)
The HTML Form:
{% for messageview in messageview_list %}
<form method="post" action="/edit">
<p>
<textarea name="message" rows="3" cols="60" MAXLENGTH=60>
{{ messageview.content }}</textarea>
<br>
<input type="submit" value="Update"/>
</p>
</form>
{% ifnotequal error None %}
<p>
{{ error }}
</p>
{% endifnotequal %}
{% endfor %}
I am assuming the indentation is due to copy/paste, but make sure that the post() and get() functions are actually indented inside of your class.
In your form, you have <textarea name="message" rows="3" cols="60" MAXLENGTH=60>, but in your def post() you use updated_content = self.request.get('content'), which is looking for the content keyword in the request. Also, your edit doesn't look like it is doing what you want it to do. In order to edit an entity, the basic outline of the process is 1.) Retrieve the entity (so do as you do, query using some parameter); 2.) Modify the properties of the entity however you want; and 3.) put() the entity back in the datastore.
From your code, it looks like you are retrieving the last entity entered into the datastore, but then creating a new model instead of editing that one (assuming that is what you want to do - not quite sure if that is accurate :) ). If you are looking to modify the entity that is returned, this should work:
def post(self):
updated_content = self.request.get('message')
content_query = db.GqlQuery("SELECT * "
"FROM MessageModel "
"ORDER BY date DESC LIMIT 1")
# Your query will always return just one entity (due to the LIMIT),
# but you can use get() here instead of fetch(1)
latest_model = content_query.get()
# Update the model's content property
latest_model.content = updated_content
latest_model.put()
# Assuming you want to output that model, you'd output it now
doRender(self,
'edit.htm',
{'messageview_list': latest_model })