I'm using flask. Database is sqlite3.
In short. I can make lists and I can tick them off as "finished", I want to show the numbers of finished lists in the users profile.
At this time it shows the same as "all lists"..
This is my List model:
class List(Model):
timestamp = DateTimeField(default=datetime.datetime.now)
user = ForeignKeyField(
rel_model=User,
related_name='list'
)
content = TextField()
finished = BooleanField(default=False)
class Meta:
database = DATABASE
order_by = ('-timestamp',)
This is my find finished lists function on the User model:
def finished_lists(self):
return List.select().where(
(List.user == self) |
(List.finished == True)
)
This is the profile template:
{% extends "stream.html" %}
{% block content %}
<div class="row">
<div class="">
<h1>{{ user.username }}</h1>
</div>
<div class="">
<div class="">
<h5>Followers</h5>
<p>{{ user.followers().count() }}</p>
</div>
<div class="">
<h5>Following</h5>
<p>{{ user.following().count() }}</p>
</div>
<div class="">
<h5>Lists</h5>
<p>{{ user.list.count() }}</p>
</div>
<div class="">
<h5>Finished</h5>
<p>{{ user.finished_lists().count() }}</p>
</div>
</div>
<div class="grid-25">
{% if current_user.is_authenticated %}
{% if user != current_user %}
{% if not user in current_user.following() %}
Follow
{% else %}
Unfollow
{% endif %}
{% endif %}
{% endif %}
</div>
</div>
{{ super() }}
{% endblock %}
In your finished list function you select all lists corresponding to the user OR (|) finished . Both conditions should be true to select finished lists so you need and (&)
Related
I'm trying to prevent the deletion of certain entries in the inline model views with flask-admin:
The respective inline model code looks like this:
class ModelCategoryValueInline(InlineFormAdmin):
form_columns = ('id', 'display_name', 'name')
form_edit_columns = ('id', 'display_name')
can_delete = False
form_args= dict(
display_name=dict(label='Display Name', validators=[DataRequired()]),
name=dict(label='Technical Name', validators=[DataRequired()]),
)
def on_model_delete(self, model):
# Not called at all..
print('on_model_delete', model)
if model.builtin == True:
raise ValidationError(f'[{model}] is a build-in CategoryValue and cannot be deleted.')
def on_model_change(self, form, model, is_created):
# Is called, but has model already changed... - deleted models do not get this event
if not is_created:
if form.form.name.data != model.name:
raise ValidationError(f'You cannot change the internal name of a category value!')
def on_form_prefill(self, form, id):
# not called att all
form.name.render_kw = {'disabled': 'disabled', 'readonly': True}
I haven't figured out a way to prevent deletion of inline entries. on_model_delete() is not called when deleting the inline entries. can_delete has no effect either.
How can I disable the deletion of inline entries?
Ideally I want to be able to control deletion via the on_model_delete() method and prevent only deletion of values that match certain criteria.
Even though this is not an ideal solution I've managed to achieve the desired behaviour by editing the inline_list_base.html template:
{% macro render_inline_fields(field, template, render, check=None) %}
<div class="inline-field" id="{{ field.id }}">
{# existing inline form fields #}
<div class="inline-field-list">
{% for subfield in field %}
<div id="{{ subfield.id }}" class="inline-field well well-sm">
{%- if not check or check(subfield) %}
<legend>
<small>
{{ field.label.text }} #{{ loop.index }}
<div class="pull-right">
{% if subfield.get_pk and subfield.get_pk() %}
# Added if statement to check if field is builtin and disable checkbox
{% if subfield.object_data.builtin %}
<label for="del-{{ subfield.id }}" style="display: inline"><i title="This is a built-in value and cannot be deleted" data-toggle="tooltip">Built-in</i></label>
{% else %}
<input type="checkbox" name="del-{{ subfield.id }}" id="del-{{ subfield.id }}" />
<label for="del-{{ subfield.id }}" style="display: inline">{{ _gettext('Delete?') }}</label>
{% endif %}
{% else %}
<i class="fa fa-times glyphicon glyphicon-remove"></i>
{% endif %}
</div>
</small>
</legend>
<div class='clearfix'></div>
{%- endif -%}
{{ render(subfield) }}
</div>
{% endfor %}
</div>
{# template for new inline form fields #}
<div class="inline-field-template hide">
{% filter forceescape %}
<div class="inline-field well well-sm">
<legend>
<small>{{ _gettext('New') }} {{ field.label.text }}</small>
<div class="pull-right">
<span class="fa fa-times glyphicon glyphicon-remove"></span>
</div>
</legend>
<div class='clearfix'></div>
{{ render(template) }}
</div>
{% endfilter %}
</div>
<a id="{{ field.id }}-button" href="javascript:void(0)" class="btn btn-default" onclick="faForm.addInlineField(this, '{{ field.id }}');">{{ _gettext('Add') }} {{ field.label.text }}</a>
</div>
{% endmacro %}
When placing this file in templates/admin/model/inline_list_base.html this has the desired effect and prevents the user from deleting certain fields:
I would want to have a check also at the backend but I haven't found a solution for that yet.
My solution was to use something similar to
class NoDeleteInlineModelFormList(InlineModelFormList):
def display_row_controls(self, field):
return False
class NoDeleteInlineModelConverter(InlineModelConverter):
inline_field_list_type = NoDeleteInlineModelFormList
class ParentView(sqla.ModelView):
inline_models = [Child]
inline_model_form_converter = NoDeleteInlineModelConverter
You can find more details at my repo https://github.com/mapio/Flask-Admin-Inline-Models-And-Related-Fields
Hey there im finishing my little app which is an online platform that sells tickets for events. Im currently having some problems when the user goes out of the page. I want to get rid of the data that he has already submitted. This happens when the promoter of the event wants to create a party, there´s two "stages" the event info and the tickets info. Im handling this with javascript´s "beforeunload" but im stuck. Could anyone give me a hint? Thank you by the way guys.
I don´t have a particular error, i would just like to get rid of the unfinished posts after the user leaves.
routes
#app.route("/post/new",methods=["GET","POST"])
#login_required
def new_post():
#event forms
post_form=PostForm()
#valdiating the submission of those forms
if post_form.validate_on_submit():
if post_form.image_file.data:
picture_file=save_picture(post_form.image_file.data)
#loading to our database
post=Post(title=post_form.title.data,content=post_form.content.data,start_dh=post_form.start_dh.data,
finish_dh=post_form.finish_dh.data,image_file=picture_file,author=current_user)
db.session.add(post)
db.session.commit()
flash("create your tickets now", "success")
return redirect(url_for("tickets", post_id=post.id))
return render_template("create_post.html",title="new post",post_form=post_form,legend="New Event")
#create new tickets
#app.route("/ticket/<int:post_id>",methods=["GET","POST"])
#login_required
def tickets(post_id):
post=Post.query.get_or_404(post_id)
ticket_form=TicketForm()
#this variable give us the id of the last post that this user posted
post_relation=Post.query.filter_by(user_id=current_user.id).order_by(Post.date_posted.desc()).first()
#submission
if ticket_form.validate_on_submit():
tickets=Tickets(ticket_type=ticket_form.ticket_type.data,ticket_quantity=ticket_form.ticket_quantity.data,
price_ticket=ticket_form.price_ticket.data, start_dh_tickets=ticket_form.start_dh_tickets.data,
finish_dh_tickets=ticket_form.finish_dh_tickets.data,event=post_relation)
db.session.add(tickets)
db.session.commit()
flash("your tickets have been created","success")
return redirect(url_for("tickets",post_id=post.id))
tick=Tickets.query.order_by(Tickets.post_id)
return render_template("create_ticket.html",title="tickets",ticket_form=ticket_form,tick=tick,post_id=post.id)
html/javascript
creating the tickets front end
<div class="content-section">
<form method="POST" action="" onsubmit="setFormSubmitting()">
{{ticket_form.hidden_tag()}}
<fieldset class="form-group">
<div class="form-group">
{{ticket_form.ticket_quantity.label(class="form-control-label")}}
{% if ticket_form.ticket_quantity.errors %}
{{ticket_form.ticket_quantity(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in form.ticket_quantity.errors %}
<span> {{error}}</span>
{% endfor %}
</div>
{% else %}
{{ ticket_form.ticket_quantity(class="form-control-label") }}
{% endif %}
</div>
<div class="form-group">
{{ticket_form.ticket_type.label(class="form-control-label")}}
{% if ticket_form.ticket_type.errors %}
{{ticket_form.ticket_type(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in ticket_form.ticket_type.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ ticket_form.ticket_type(class="form-control-label")}}
{% endif %}
</div>
<div class="form-group">
{{ticket_form.price_ticket.label(class="form-control-label")}}
{% if ticket_form.price_ticket.errors %}
{{ticket_form.price_ticket(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in ticket_form.price_ticket.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ ticket_form.price_ticket(class="form-control-label")}}
{% endif %}
</div>
<div class="form-group">
{{ticket_form.start_dh_tickets.label(class="form-control-label")}}
{% if ticket_form.start_dh_tickets.errors %}
{{ticket_form.start_dh_tickets(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in ticket_form.start_dh_tickets.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ ticket_form.start_dh_tickets(class="form-control-label")}}
{% endif %}
</div>
<div class="form-group">
{{ticket_form.finish_dh_tickets.label(class="form-control-label")}}
{% if ticket_form.finish_dh_tickets.errors %}
{{ticket_form.finish_dh_tickets(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in ticket_form.finish_dh_tickets.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ ticket_form.finish_dh_tickets(class="form-control-label")}}
{% endif %}
</div>
<div class="form-group">
{{ticket_form.submit_ticket(class="btn btn-primary")}}
</div>
</fieldset>
</form>
</div>
<script type="text/javascript">
var formSubmitting = false;
var postComplete= true;
var setFormSubmitting = function() { formSubmitting = true; };
var setPostComplete=function() { postComplete=false; };
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting) {
return undefined;
}
var confirmationMessage = 'you want to leave? your data will be lost';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
</script>
creating the post frontend
<div class="content-section">
<form method="POST" action="" enctype="multipart/form-data" onsubmit="setFormSubmitting()">
{{post_form.hidden_tag()}}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> {{ legend }}</legend>
<div class="form-group">
{{post_form.title.label(class="form-control-label")}}
{% if post_form.title.errors %}
{{post_form.title(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in post_form.title.errors %}
<span> {{error}}</span>
{% endfor %}
</div>
{% else %}
{{ post_form.title(class="form-control-label")}}
{% endif %}
</div>
<div class="form-group">
{{post_form.content.label(class="form-control-label")}}
{% if post_form.content.errors %}
{{post_form.content(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in post_form.content.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ post_form.content(class="form-control-label")}}
{% endif %}
</div>
<!-- section for setting the date and hour of the event-->
<!-- starting date hour-->
<div class="form-group">
{{post_form.start_dh.label(class="form-control-label")}}
{% if post_form.start_dh.errors %}
{{post_form.start_dh(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in post_form.start_dh.errors %}
<span> {{error}}</span>
{% endfor %}
</div>
{% else %}
{{ post_form.start_dh(class="form-control-label")}}
{% endif %}
<!-- finish -->
<div class="form-group">
{{post_form.finish_dh.label(class="form-control-label")}}
{% if post_form.finish_dh.errors %}
{{post_form.finish_dh(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in post_form.finish_dh.errors %}
<span> {{error}} </span>
{% endfor %}
</div>
{% else %}
{{ post_form.finish_dh(class="form-control-label")}}
{% endif %}
</div>
<!-- image -->
<div class="form-group">
{{post_form.image_file.label()}}
{{post_form.image_file(class="form-control-file")}}
{% if post_form.image_file.errors %}
{% for error in post_form.image_file.errors %}
<span class="text-danger"> {{error}} </span></br>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{post_form.submit_post(class="btn btn-primary")}}
</div>
</fieldset>
</form>
</div>
<script type="text/javascript">
var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting) {
return undefined;
}
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
</script>
databases
class Post(db.Model):
#unique id for the user
id= db.Column(db.Integer, primary_key=True)
#name of the event
title= db.Column(db.String(100), nullable=False)
#when the event was posted
date_posted= db.Column(db.DateTime, nullable=False, default=datetime.now())
#description of the event
content= db.Column(db.Text, nullable=False)
#start date and hour of the event
start_dh= db.Column(db.DateTime, nullable=False)
#finish date and hour of the event
finish_dh= db.Column(db.DateTime, nullable=False)
#image of the flyer for the post
image_file= db.Column(db.String(20), nullable=False, default="default.jpg")
#linking the post table with the user
user_id= db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
#relation with the ticket model
ticket=db.relationship("Tickets", backref="event", lazy=True)
#relation ship with the customer
customer=db.relationship("Customer", backref="party", lazy=True)
#this is a method that declares how our class is going to be printed out
def __repr__(self):
return "%s,%s,%s,%s,%s" % (self.user_id,self.title,self.date_posted,self.content,self.image_file)
#data base for the tickets
class Tickets(db.Model):
#unique id for the user
id= db.Column(db.Integer, primary_key=True)
#name or kind of the event, this is set by the creators
ticket_type=db.Column(db.String(20), nullable=False)
#initial stock of the ticket
ticket_quantity=db.Column(db.Integer,nullable=False)
#initial price of this kind of ticket
price_ticket=db.Column(db.Integer, nullable=False)
#start date and hour of the event
start_dh_tickets=db.Column(db.DateTime, nullable=False)
#finish date and hour of the event
finish_dh_tickets=db.Column(db.DateTime, nullable=False)
#id of the event we have a relationship with
post_id= db.Column(db.Integer, db.ForeignKey("post.id"), nullable=False)
#this is a method that declares how our class is going to be printed out
def __repr__(self):
return "%s,%s,%s,%s,%s,%s" % (self.post_id,self.ticket_type, self.ticket_quantity,self.price_ticket,self.start_dh_tickets,self.finish_dh_tickets)
You can use warn message to user from browser in JavaScript:
window.onbeforeunload = function(){
return 'Are you sure you want to leave?';
};
Or you can send data to Flask server immidiately after user changes the inputs and after click on the button, you can officially proceed them.
Consider two models in my models.py:
Roles:
class Role(models.Model):
role = models.CharField(max_length=255)
nickname = models.CharField(max_length=255)
is_hero = models.BooleanField(default=False)
def __str__(self):
return self.role
and
Players:
class Player(models.Model):
name = models.CharField(max_length=255)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
nickname = models.CharField(max_length=255, default="Use the default nickname from the role you just chose but also be able to change it from within this model.")
is_hero = models.BooleanField(default="Use the default is_hero from the role you just chose but also be able to change it from within this model.")
def __str__(self):
return self.name
Also consider that I already made a role called "Dumbo" with the nickname "Dunm" and is_hero being False.
I now go ahead and try to use the role in my new player after setting my player name, I choose my role but how do I use the values of my now chosen role in my new player as the default for nickname and is_hero and at the same time, allow them to be overridden if feel so?
Thanks,
Edit:
I've overridden all the Django templates. So I'm not making new forms and rendering them in my custom views. I'm really bad with the terminologies, pardon me. I hope this makes sense.
{% load fieldcss %}
<div class="card">
<div class="card-header">
{% if fieldset.name %}<h4 class="card-title">{{ fieldset.name }}</h2>{% endif %}
{% if fieldset.description %}
<div class="description">{{ fieldset.description|safe }}</div>
{% endif %}
</div>
<div class="card-body">
{% for line in fieldset %}
<div class="row">
{% for field in line %}
{% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if name == "CheckboxInput" %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{{ field|addlabel:field.field.label|safe }}
{% if field.is_readonly %}
<div class="readonly">{{ field.contents }}</div>
{% else %}
<div class="col-sm-10">
{% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
<div class="form-group">
{{ field|addclass:field.field.auto_id|safe }}
{% if field.field.help_text %}
<span class="form-text">{{ field.field.help_text|safe }}</span>
{% endif %}
</div>
</div>
{% endif %}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</fieldset>
This is not something you can do in the model, but by passing the values to the form from the view at creation time. For example:
class PlayerCreateForm(forms.ModelForm):
class Meta:
model = Player
fields = ('name', 'nickname', 'is_hero')
def create_player_from_role(request, role_id):
role = get_object_or_404(Role, role_id)
if request.method == 'POST':
form = PlayerCreateForm(request.POST)
if form.is_valid():
player = form.save(commit=False)
player.role = role
player.save()
return redirect('/')
else:
form = PlayerCreateForm(initial={'nickname': role.nickname, 'is_hero': role.is_hero})
return render(request, 'create_player.html', {'form': form})
Am creating a website where user will be posting information in the site, but when I post in the site, all post appear in a single card while I want each post to appear in a separate card, How would I do this?? would I have to use Javascript in the front end or python in the back end to accomplish this, and how?
Am using python 3.6.8, and django 2.1.8, I have written a code but all post appear in single materialize card
views
def homepage(request):
return render(request=request,
template_name="main/home.html",
context={"documents":Documents.objects.all}
models
class Documents(models.Model):
docs_name = models.CharField(max_length=200)
police_station = models.CharField(max_length=200)
docs_details = models.TextField()
docs_pic = models.ImageField()
def __str__(self):
return self.docs_name
Home template
{% extends 'main/base.html' %}
{% block content %}
<a class="waves-effect waves-light btn" href="">button</a>
<div class="row">
<div class="col s12 m9" >
<div class="card">
<div class="card-image">
{% for Doc in documents %}
<p>{{Doc.docs_name}}</p>
<p>{{Doc.police_station}}</p>
<p>{{Doc.docs_details}}</p>
<p>{{Doc.docs_pic}}</p>
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}
Try:
{% extends 'main/base.html' %}
{% block content %}
<a class="waves-effect waves-light btn" href="">button</a>
<div class="row">
<div class="col s12 m9" >
{% for Doc in documents %}
<div class="card">
<div class="card-image">
<p>{{Doc.docs_name}}</p>
<p>{{Doc.police_station}}</p>
<p>{{Doc.docs_details}}</p>
<p>{{Doc.docs_pic}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
You can achieve what you desire by simply adding the looping construct outside the <div class="card"> like this :
{% extends 'main/base.html' %}
{% block content %}
<a class="waves-effect waves-light btn" href="">button</a>
<div class="row">
<div class="col s12 m9" >
{% for Doc in documents %}
<div class="card">
<div class="card-image">
<p>{{Doc.docs_name}}</p>
<p>{{Doc.police_station}}</p>
<p>{{Doc.docs_details}}</p>
<p>{{Doc.docs_pic}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
This way your card section alone repeats multiple times.
Earlier since the loop was within the card you got all the items within the same card.
I am working on library website in which I want to display data from database which is Book name and description. But I'm not able to do that. Here is my code
views.py
from django.shortcuts import render
from .models import *
def index(request):
book_list = Book.objects.all()
return render(request,template_name='index.html', context={'book_list':book_list})
index.html
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ book_list }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}
You should work with b variable instead of book_list inside of for loop.
If your Book model contains title field, your code might look like this:
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ b.title }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}