I have a dashboard that lists locations. You can then click on locations to get more details of that location. I am getting a 404 error message though.
http://127.0.0.1:8000/locations/get//
Heres the part of the code I am having issues with.
urls.py
url(r'^accounts/loggedin/locations/all/$', 'assessments.views.locations'),
url(r'^accounts/loggedin/locations/get/(?P<location_id>\d+)/$', 'assessments.views.location'),
views.py
def locations(request):
return render_to_response('dashboard/locations.html', {'locations': Location.objects.all() })
def location(request, location_id=1):
return render_to_response('dashboard/location.html', {'location': Location.objects.get(id=location_id) })
locations.html
{% for p in locations %}
<tr>
<td>{{ p.landlord_agent }}</td>
<td>{{ p.id }}</td>
</tr>
{% endfor %}
To be honest I don't get why it would be location_id, as the database field is just id but thats how the guide showed me to do it and changing it to just id doesn't seem to make a difference
The problem is inside the template. You are having a loop variable called p, not location.
Replace location.id with p.id.
Or, better have this variable called location - more readable and explicit.
Complete template code:
{% for location in locations %}
<tr>
<td>{{ location.landlord_agent }}</td>
<td>{{ location.id }}</td>
</tr>
{% endfor %}
edit your app/urls.py:
url(r'^locations/get/(?P<location_id>[\d]+)/$', 'assessments.views.location')
Related
I want to print one table row based on the user input. I am getting the user input (id) via HTML and Python, here:
html file:
<tbody class="table-group-divider">
{% for course in user.courses %}
<tr>
<!-- here an ID gets rendered from the table, and user clicks on it -->
<td>{{ course.course_name }}</td>
<td class="align-middle">
{% for student in course.students %}
<span>{{ student.student_name }}</span><br>
{% endfor %}
</td>
<td>{{ course.course_day }} {{ course.course_time }}</td>
<td>{{ course.course_language }}</td>
</tr>
{% endfor %}
</tbody>
app.py:
#app.route('/course_detail/<id>', methods=["GET", "POST"])
#login_required
def course_detail(id):
return render_template("course_detail.html", user=current_user, id=id)
My logic is to loop through the table, and if id provided by user matches id (primary key) in table, I found what I want to display, and then display it. However, my attempt does not print anything:
<!-- setting the ID from url/html, basically what user clicked -->
{% set id = id %}
{% for course in user.courses %}
{% if course.id == id %}
<p>im working</p>
{% endif %}
{% endfor %}
I get the id from user, but I can't seem to compare it with course.id so I could display the whole row. Is there a problem with my if statement?
Edit: If I hardcode the if statement to be for example {% if course.id == 2 %} (or any other valid course.id from the table), the information gets printed with no issues.
While I'm not sure why the original proposition doesn't work, I managed to reach my goal via querying my database in app.py, not my html file.
#app.route('/course_detail/<id>', methods=["GET", "POST"])
#login_required
def course_detail(id):
# query the id in db
db_id = Course.query.filter_by(id=id).first()
# save all info into variables
db_course_name = db_id.course_name
db_course_language = db_id.course_language
db_course_day = db_id.course_day
db_course_time = db_id.course_time
db_hourly_rate = db_id.hourly_rate
# send the variables and print them in html
return render_template("course_detail.html", user=current_user, pageid=db_id, db_course_name=db_course_name, db_course_language=db_course_language, db_course_day=db_course_day, db_course_time=db_course_time, db_hourly_rate=db_hourly_rate)
Then I simply printed the variables using double curly braces. Not sure if this is the best design, but it certainly feels better than my previous attempt.
I have search results in form of table. I want to add a detail page button which can send the id of the result to another function in view.py
so i can query it from database.
{% if sr %}
{% for k,j in sr %}
<tbody>
<tr>
<td>{{ k.id }}</td>
<td>{{ k.chromosome }}</td>
<td>{{ k.gene_id }} </td>
<td> view</td>
</tr>
</tbody>
{% endfor %}
{% endif %}
I want to send this k.id to another function
def detailed(request):
return render(request,"search/Detailed.html")
so I can again perform a query from database by this id
Since you didn't specify the version of django you're using, I'm going to assume it's 2.x. The only huge difference between that and more recent versions of 1.x is the urlpatterns. If you're using 1.11, just use the required regex's you need, as described in the docs. Either way, the principle is the same.
urls.py
urlpatterns = [
....
path('<int:some_id>/', views.detail_view, name='detail_view'),
# if django 1.11... you would use ([0-9]{4}) in place of the 'int', or for whatever max amount of numbers you'd want to capture... But I will continue for django 2.x.
]
views.py
def detail_view(request, some_id):
some_object = YourModel.objects.get(id=some_id)
return render(request, 'detail_template.html', {'some_object ': some_object})
detail_template.html
<p>{{ some_object.chromosome }}</p>
<p>{{ some_object.gene_id }}</p>
<p>View details</p>
Note that the url block above has some_object.id added to it as an argument AFTER the view it goes to in quotations. This is the easiest way.
You can also acheive the same thing with a model method by using the reverse('app_name:view_name', args=[arg_1, arg_2, etc) function, and then call the method with {{ some_object.your_method }}. But those arguments would all depend on what your url patterns and functions took.
I'm brand new to programming. I came up with a project to help me learn and I'm stuck already. I'm using Flask, Flask-SQLAlchemy and Flask-wtf.
I'm trying to create a club attendance system that lists members and checks them off if they are present and logs the amount they paid (either $15 for 1 lesson, or $25 for the week). I have a table that I populate from my database that looks like this:
I want to click on submit to mark the person as present but this ticks the checkbox for everyone in the list and sets the amount paid to the same for everyone.
I have tried lots of things. I have seen similar issues here and people suggesting using FieldList and FormField - I tried this with no luck. Here is my Form code:
class MemberForm(Form):
form_id = HiddenField()
member_id = DecimalField('id')
member_name = StringField('name')
attend_date = StringField('date', default=todays_date())
is_here = BooleanField('here')
has_paid = SelectField('Amount', choices=[(15, '15'), (25, '25')])
submit = SubmitField("Submit")
def __init__(self, *args, **kwargs):
super(MemberForm, self).__init__(*args, **kwargs)
read_only(self.member_name)
My controller code:
#app.route('/', methods=['GET', 'POST'])
def home():
members = Member.query.order_by(Member.name).all()
form = MemberForm()
if request.method == 'POST': # TODO form validation and database stuff
print('got this far')
print(form.data)
return render_template('index.html', title='Tong Long',
today=todays_date(), members=members,
form=form)
and the jinja2 template part:
<table width="483" border="1">
<tbody>
<tr>
<th width="271"><strong>Member</strong></th>
<th width="152"><strong>Grade</strong></th>
<th><strong>Last Seen</strong></th>
<th width="38"><strong>Paid?</strong></th>
<th><strong>Is Here?</strong></th>
<th>Submit</th>
</tr>
{% for member in members %}
<form action="" method="post" name="{{ member.id }}">
<tr>
<td>{{form.member_name(value=member.name)}}</td>
{% for g in member.grade %}
<td>{{ g.grade }}</td>
{% endfor %}
<td>{{ form.attend_date }}</td>
<td>{{ form.has_paid }}</td>
<td>{{form.is_here}}</td>
<td>
{{ form.submit }}
</td>
</tr>
</form>
{% endfor %}
</tbody>
</table>
Viewing the rendered HTML I can see that all the fields have the same id.
I'm starting to think this can't be done with WTForms. Will I need to use javascript perhaps (something I know nothing about). Or manually create the forms rather than using WTF? Any help appreciated!
This is very late, but perhaps it is helpful to somebody.
What calabash is doing, is create one single form and then display it multiple times in the template.
However, to achieve the desired outcome (independend forms with independend submit buttons), multiple forms need to be created within the route function. They can be passed as a list to the template and then looped over. (A simpler solution would be one form with one submit button and dynamically created "lines" for each member. See FieldList...)
Logic:
def home():
members = Member.query.order_by(Member.name).all()
forms = []
for member in members:
form = MemberForm(prefix=member.name)
form.member_name.data = member.name
forms.append(form)
# validation:
for form in forms:
if form.submit.data and form.validate_on_submit():
# do_something here for each form, e.g. write to database
return render_template('index.html', title='Tong Long',
today=todays_date(),
forms=forms,
members=members)
The different forms need to have individual prefixes. They need to be validated individually and it needs to be checked which submit-button was used.
Note: It is perhaps not a good idea to use a form field for the name, as that information is already known from the members database entry and it might not be intended to change it here. A simple text label would make more sense in that case.
The table rows in the template could look like this:
{% for form in forms %}
<form action="" method="post">
{{ form.hidden_tag() }}
<tr>
<td>{{ form.member_name }}</td>
<td>{{ members[loop.index0].grade }}</td>
<td>{{ form.attend_date }}</td>
<td>{{ form.has_paid }}</td>
<td>{{ form.is_here }}</td>
<td>{{ form.submit }}</td>
</tr>
</form>
{% endfor %}
My issue is that I can't seem to translate the dictionary into a table here's the error:
Could not parse ["appid"] from 'game[''appid"]
HTML code:
<table>
<tr>
<th>Game ID</th>
<th>Game Name</th>
<th>Hours Played</th>
</tr>
{% for game in games %}
{# each game object is a dictionary with "appid", "name " and "playtime_forever" keys #}
<tr>
<td>{{ game["appid"] }}</td>
<td>{{game["name"]}}</td>
<td>{{ game["playtime_forever"] }}</td>
</tr>
</table>
views.py code:
~~~~ There's stuff here but it shouldn't be important. ~~~~
return render(request,'hackathon/SteamAPI.html', game)
When I run the server it shows:
game:
[{u'appid': 4000,
u'has_community_visible_stats': True,
u'img_icon_url': u'd9101cbeddcc4ff06c7fa1936c3f381b0bbf2e92',
u'img_logo_url': u'dca12980667e32ab072d79f5dbe91884056a03a2',
u'name': u"Garry's Mod",
u'playtime_forever': 0},
Django templates do not support [] indexing. Instead of
game["appid"]
you should use
game.appid
The same applies for game.name and game.playtime_forever
As an unrelated note, you should also close your for loop:
</tr>
{% endfor %}
</table>
Dictionary should be accessed this way in Django Templates.
choices = {'key1':'val1', 'key2':'val2'}
<ul>
{% for key, value in choices.items %}
<li>{{key}} - {{value}}</li>
{% endfor %}
</ul>
My problem is that I need to know if a user has rated a certain model instance, BlogSite. On the page, there are multiple BlogSite instances, which have a 5-star rating system. When the current user has rated a certain instance, it should be set to read-only.
I'm running into a roadblock because if I use a model function, I need to pass 2 variables - current_user and BlogSite. I haven't been able to find how to access request.user in models.py and it's looking like I shouldn't be doing that?
The other path I went down was to create a custom filter - but I found out that I can only pass in one parameter. I would rather not do this method because I feel it would be better to keep the logic in views.py
Does anyone have ideas of how I can solve this problem?
#models.py
class BlogSite(models.Model):
#fields
#get the average rating for a blogsite
def rating_avg(self):
rating_dict = BlogSiteReview.objects.filter(blog_site=self).aggregate(Avg('review_rating'))
rating_avg = rating_dict.get('review_rating__avg')
if rating_avg:
return rating_avg
else:
#no ratings
return 0
def rated(self, current_user):
#If there is a row for the blogsitereview with this blogsite for the logged in user, return True, else False
#can I access the current user? This does not work, seems like I can't get request here.
current_user = request.user
review = BlogSiteReview.objects.filter(blog_site=self, user=current_user)
if review:
return True
else:
return False
class BlogSiteReview(models.Model):
blog_site = models.ForeignKey(BlogSite)
user = models.ForeignKey(User)
#other fields
Here is the relevant part of the view:
#views.py
def search(request, type, regionValue):
#....
#ideally, the solution would be to have a field or function in the BlogSite model
blog_sites = BlogSite.objects.filter(country=region.id, active=True)
#....
In the template I would have an if statement to add a class if rated returns True
<tr>
<td>{{ blogsite.site_name }}</td>
<td><div id="rating{{ blogsite.id }}" class="rating {% if blogsite.user_rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
<td>{{ blogsite.create_date }}</td>
</tr>
I'm looking for 2 things here - does using a model method to get if a user has rated seem like the correct approach? The problem I have with this so far is that I can't find how to access the current user to use in models.py. Another idea I thought of is to pass in the request.current_user from the view somehow, but the user is not associated with BlogSite, so I can't filter on that.
I ended up taking a slightly different approach which I thought of when trying to fall asleep but couldn't get Django out of my head :) In the view I created a list of blog_sites that a certain user left a review
#views.py
rated = BlogSiteReview.objects.filter(user=request.user).values_list('blog_site', flat=True)
return render(request, page, {..., 'blogsites':blog_sites, 'rated':rated})
And in the template I added a class if that blog_site FK id was in the blog_sites for loop:
#template
{% for blogsite in blogsites %}
<tr>
<td>{{ blogsite.site_name }}</td>
<td><div id="rating{{ blogsite.id }}" class="rating {% if blogsite.id in rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
<td>{{ blogsite.create_date }}</td>
<td>{{ rated }}</td>
</tr>
{% empty %}
<p>There are no registered blogsites for this country.</p>
{% endfor %}
Finally I can go to sleep now!
You could pass the result of blog_site.rated(request.user) via template parameters. If you feed your template with multiple BlogSite instances (blog_sites in your view sample) and iterate over them in the template, you could group the instance and the rated result into tuples or dicts in your view like so:
({"site": block_site, "rated": block_site.rated(request.user)} for block_site in block_sites)
And access these in the template with result.site and result.rated, respectively, assuming that result is the iteration variable (because you named your view search) in the template (replacing blogsite in your template snippet).
Hence, I personally would keep the rated method as you posted it, with the current_user parameter.
EDIT: here is an example which mixes your code (question and answer) and my proposal:
#views.py
def search(request, type, regionValue):
#....
blog_sites = BlogSite.objects.filter(country=region.id, active=True)
search_results = ({"site": block_site, "rated": block_site.rated(request.user)} for block_site in block_sites)
return render(request, page, {..., 'search_results': search_results})
And in the template:
{% for result in search_results %}
{% with blogsite=result.site rated=result.rated %}
<tr>
<td>{{ result.site.site_name }}</td>
<td><div id="rating{{ blogsite.id }}" class="rating {% if rated %}jDisabled{% endif %}" data-average="{{ blogsite.rating_avg }}" data-id="{{ blogsite.id }}"></div></td>
<td>{{ blogsite.create_date }}</td>
<td>{{ rated }}</td>
</tr>
{% endwith %}
{% empty %}
<p>There are no registered blogsites for this country.</p>
{% endfor %}