I will try to explain this issue the better I can.
So I built a calculator using django. The user can put the desired input, and then he sees all the results in a table, only by pressing the button: 'select'.
If the user only wants this result, the user see the result output in the table.
However, if the user selects one of the options presented in the dropdowns, then the result should be different. Meaning that the dropdown list, has specific calculus.
This is the part that I don't understand,I know that I have to use JS to this, but I don't know in which module this should be added.
Here is my code:
models.py
class CalcAnalyzer(models.Model):
sequence = models.TextField()
gc_calc = models.CharField(max_length=2000000)
person_of = models.ForeignKey(User,null=True,on_delete=models.CASCADE)
def save(self, *args, **kwargs):# new
if self.sequence != None:
self.gc_calc = gc_calc(self.sequence)
super(CalcAnalyzer,self).save(*args, **kwargs)
def __str__(self):
return self.sequence
class addcalc_1(models.Model):
name_sequence = models.ForeignKey(OligoAnalyzer, on_delete=models.SET_NULL, null=True)
Option1_5 = models.FloatField(default=0)
def save(self, *args, **kwargs):
self.Option1_5 = Option1_5(self.sequence)
class addcalc_3(models.Model):
name_sequence = models.ForeignKey(OligoAnalyzer, on_delete=models.SET_NULL, null=True)
optional_3
def save(self, *args, **kwargs):
self.optional_3 = optional_3(self.sequence)
views.py
def calc_sequence(request):
sequence_items=Calanalisis.objects.filter(person_of=request.user)
form=AddSequenceForm(request.POST)
if request.method=='POST':
form=AddSequenceForm(request.POST)
if form.is_valid():
profile=form.save(commit=False)
profile.person_of = request.user
profile.save()
return redirect('calc_sequence')
else:
form=AddSequenceForm()
myFilter=SequenceFilter(request.GET,queryset=sequence_items)
sequence_items=myFilter.qs
context = {'form':form,'sequence_items':sequence_items,'myFilter':myFilter}
return render(request, 'Add_Calc.html', context)
How can I insert this in the view.py? If the user selects the 5 or 3 box, the result should appear in the table bellow, if not, the result will stay the same.
Sofia, hi!
To subscribe on the dropdown's events you need a piece of javascript.
HTML and static files
So, you need to attach your new script.js file to your project. You can check what you need to serve static files (it's not a "one-click" solution, especially if you want to deploy your code for external users) docs
When your static file is ready you can include it in the front-end.
Let's imagine that you have index.html where your controls live.
Add the link to the file in your html (before closing </body> tag):
<script type="text/javascript" src="/static/script.js"></script>
static.js
This example shows you how to make an event listener and listen to the dropdown changes.
Use values from the selected options of your dropdowns to make a URL for the request. Ex. /calc/api/?param=1, so you will be able to catch param=1 in your view and react properly.
dropdown example:
<select id="param" name="here_name">
<option value="">Select …</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
API
Create an additional view to handle the requests that will be sent on events. Make it accessible with urls.py.
Use the proper URL to the endpoint in the javascript. Here you can find how to make requests from the JS to your Django back-end.
The param that was chosen will be in the request.GET of your view (if you've chosen GET method to send the data). So make a proper answer and send it back to the JS. You can use JSON format for this.
Parse the answer in the JS and change your page with updated information.
Related
I'm looking to delete an object in Django, but none of the other Stack Overflow questions fix mine. I looked at this one, but it doesn't seem to be working. My delete object code (in the views file) looks like this:
#login_required
def delete_entry(request, entry_id):
"""Delete an existing entry."""
if request.method != 'POST':
# No data submitted; create a blank form.
form = TopicForm()
else:
# POST data submitted; process data.
form = TopicForm(data=request.POST)
if form.is_valid():
new_topic = form.delete(commit=False) ### Code to delete object
new_topic.owner = request.user
new_topic.save()
return redirect('learning_logs:topics')
# Display a blank or invalid form.
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
And in URLs.py:
path('delete_entry/<int:entry_id>', views.delete_entry, name='delete_entry'),
I would like to use a Bootstrap 4 button (inside a modal) to delete the entry (so without any redirects to another confirmation page),
Unfortunately, this isn't working. I'm just getting a server error saying that NoReverseMatch at /delete_entry/6.
What does this mean?
It seems like you're trying to call the delete method on the form. If you want to delete the object, you should call it on the object:
my_object = MyModel.objects.get(id=entry_id) # Retrieve the object with the specified id
my_object.delete() # Delete it
Here is the relevant Django documentation.
I think that you're looking for a DeleteView.
I have a form setup like this where I use the values from TestModel to create a select field in a form. However if I want to update the TestModel to add a new column, Django gives me a psycopg2.errors.UndefinedColumn saying the new column is not found on the table and the stack trace points back to this form ModelChoiceField. Its not until I comment out this select that I am able to make the migration to the database.
So my question is there a better way to setup this ModelChoiceField where I don't have to comment it out to update the underlying model on the database? I'm using Django 4.0 and python 3.8 for reference.
class TestModelChoiceField(forms.ModelChoiceField):
"""
Overwriting model choice field attribute to use
a different __str__ representation than the default
model
"""
def label_from_instance(self, obj):
return obj.test_field
class TestForm(forms.Form):
first_select = TestModelChoiceField(
queryset=TestModel.objects.filter(model_attribute__isnull=False),
initial=TestModel.objects.filter(model_attribute__isnull=False)
.filter(test_field="Yes")
.first()
.team_id,
label="Field One:",
)
When it comes to needing database access in a form like this, you're best waiting until the form is initialised rather than at runtime like you are doing here. With it setup like you have, when you start your app the form will get loaded and immediately try to query the database. If you wait until the app creates an instance of the form, you can be assured that the database will be ready/available.
So what you'd end up with is something like;
class TestForm(forms.Form):
first_select = TestModelChoiceField(
queryset=TestModel.objects.none(),
label="Field One:",
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['first_select'].queryset = TestModel.objects.filter(model_attribute__isnull=False)
self.fields['first_select'].initial = TestModel.objects.filter(
model_attribute__isnull=False
).filter(test_field="Yes").first().team_id
I need to make a dynamic path for a file that I want to open. I need to retrieve the .tif file from within a path.
this path is formed by a combination of a "STATICFILES_DIRS" from my settings.py and a field ccalled docId from my models.py that get filled from the views.py
now, I'm very new to django so I really don't understand what I dont know (if this makes sense)
my views.py has the following:
from django.shortcuts import render
import pyodbc
# Create your views here.
def home(request): conn=pyodbc.connect('Driver={sql server};'
'Server=server.domain.com;' 'Database=database;' 'Trusted_Connection=yes;')
cursor = conn.cursor() cursor.execute("select top 100 docId, supplierName,
invoiceNumber, reference from table") result = cursor.fetchall() return
render(request, 'azolve/home.html', {'Azolve': result})
and my models.py has this:
from django.db import models
import os import fnmatch
class Azolve(models.Model):
docId = models.IntegerField
supplierName = models.CharField(max_length=100)
invoiceNumber = models.IntegerField
reference = models.CharField(max_length=100)
# for file_name in os.listdir(str(filePath)):
# if fnmatch.fnmatch(file_name, '*.tif'):
# docIdFileName = file_name
and in my settings.py I have this part:
STATIC_URL = '/static/'
STATICFILES_DIRS = [ "//server1/Shared1/folder/ Migration Images/", ]
so, to give an idea, each docId that gets retrieved is the name of a folder contained in the path "STATICFILES_DIRS " what I was trying to do is to navigate for each folder and get the .tif file inside the folder, so I can concatenate and make the complete filename with the format:
//server1/Shared1/folder/ Migration Images/--docIDFOLDER--/FILENAME.TIF
this would later be shown in a table in my html file doing something like:
<tbody>
{% for datarow in Azolve %}
<tr>
<td>{{datarow.supplierName}}</td>
<td>{{datarow.invoiceNumber}}</td>
<td>{{datarow.reference}}</td> <td><a href= ' {% static "" %}{{ datarow.docId }}/{{ datarow.docIdFileName }}'>Open Invoice</a></td> </tr>
{% endfor %}
</tbody>
Does this makes sense? I've been checking different django tutorials, but I couldn't find an example of something similar to what I need to do :(
I don't know how should I get this data so I can concatenate and then pass it to the "datarow"
I've tried adding this in the models but I think is not correct to add it on the class, should be then in the views inside the function? as a new function?
Note: I'm not having the user upload files, these are stored in a network drive and I only need to have users look for them and download them, my problem is generating the complete path from the folder where the .tif file is stored (I get to "//Server/Folder/Folder2/docIdFolder/XXXX.tif" but I can't assign the value of the XXXX.tif part.
I would suggest adding a field to the model to store the file name, and look it up once from the file system, storing it in the db after that.
class Azolve(models.Model):
docId = models.IntegerField
supplierName = models.CharField(max_length=100)
invoiceNumber = models.IntegerField
reference = models.CharField(max_length=100)
img_filename = models.CharField(max_length=255, blank=True, null=True)
but also add a def to the Azolve model class which attempts to populate that img_filename if it doesn't exist. Something along the lines of the following which tries to locate the .tif using pathlib's glob (https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob):
# put this at the top of your models.py
from pathlib import Path
# and this right in your class
def tif_file(self):
if self.img_filename:
return self.img_filename:
else:
search_path = Path(r'//server1/Shared1/folder/Migration Images')
# the filter likely not needed, was using this in where I copied from
files_in_path = list(filter(Path.is_file, search_path.glob('*.tif')))
if files_in_path:
# may have to wrap the files_in_path with str()
# untested, writing in the s/o answer box
self.img_filename = files_in_path[0]
return files_in_path[0]
else:
return None
Then in your template you should be able to use {{datarow.tif_file}}. From a performance standpoint, I'm not certain if this would get run everytime you reference this record or not or if it would only fire when called upon. Might be worth tracing through the debugger.
I've started using pyramid recently and I have some best-practice/general-concept questions about it's hybrid application approach. Let me try to mock a small but complex scenario for what I'm trying to do...
scenario
Say I'm building a website about movies, a place where users can go to add movies, like them and do other stuff with them. Here's a desired functionality:
/ renders templates/root.html
/movies renders templates/default.html, shows a list of movies
/movies/123456 shows details about a movie
/movies/123456/users shows list of users that edited this movie
/users renders templates/default.html, shows a list of users
/users/654321 shows details about a user
/users/654321/movies shows a list of favorite movies for this user
/reviews/movies renders templates/reviews.html, shows url_fetched movie reviews
/admin place where you can log in and change stuff
/admin/movies renders templates/admin.html, shows a list of editable movies
/admin/movies/123456 renders templates/form.html, edit this movie
extras:
ability to handle nested resources, for example movies/123/similar/234/similar/345, where similar is a property of movie class that lists ids of related movies. Or maybe more clear example would be: companies/123/partners/234/clients/345...
/movies/123456.json details about a movie in JSON format
/movies/123456.xml details about a movie in XML format
RESTFull methods (GET, PUT, DELETE..) with authorization headers for resource handling
approach
This is what I've done so far (my views are class based, for simplicity, I'll list just decorators...):
# resources.py
class Root(object):
__name__ = __parent__ = None
def __getitem__(self, name):
return None
def factory(request):
# pseudo code...
# checks for database model that's also a resource
if ModelResource:
return ModelResource()
return Root()
# main.py
def notfound(request):
return HTTPNotFound()
def wsgi_app():
config = Configurator()
config.add_translation_dirs('locale',)
config.add_renderer('.html', Jinja2Renderer)
# Static
config.add_static_view('static', 'static')
# Root
config.add_route('root', '/')
# Admin
config.add_route('admin', '/admin/*traverse', factory='factory')
config.add_route('default', '/{path}/*traverse', factory='factory')
config.add_notfound_view(notfound, append_slash=True)
config.scan('views')
return config.make_wsgi_app()
# views/root.py
#view_config(route_name='root', renderer="root.html")
def __call__():
# views/default.py
#view_defaults(route_name='default')
class DefaultView(BaseView):
#view_config(context=ModelResource, renderer="default.html")
def with_context():
#view_config()
def __call__():
# views/admin.py
#view_defaults(route_name='admin')
class AdminView(BaseView):
#view_config(context=ModelResource, renderer="admin.html")
def default(self):
#view_config(renderer="admin.html")
def __call__(self):
And following piece of code is from my real app. ModelResource is used as context for view lookup, and this is basically the reason for this post... Since all my models (I'm working with Google App Engine datastore) have same basic functionality they extend specific superclass. My first instinct was to add traversal functionality at this level, that's why I created ModelResource (additional explanation in code comments), but I'm begining to regret it :) So I'm looking for some insight and ideas how to handle this.
class ModelResource(ndb.Model):
def __getitem__(self, name):
module = next(module for module in application.modules if module.get('class') == self.__class__.__name__)
# this can be read as: if name == 'movies' or name == 'users' or .....
if name in module.get('nodes'):
# with this setup I can set application.modules[0]['nodes'] = [u'movies', u'films', u'фильми' ]
# and use any of the defined alternatives to find a resource
# return an empty instance of the resource which can be queried in view
return self
# my models use unique numerical IDs
elif re.match(r'\d+', name):
# return instance with supplied ID
cls = self.__class__
return cls.get_by_id(name)
# this is an attempt to solve nesting issue
# if this model has repeated property it should return the class
# of the child item(s)
# for now I'm just displaying the property's value...
elif hasattr(self, name):
# TODO: ndb.KeyProperty, ndb.StructuredProperty
return getattr(self, name)
# this is an option to find resource by slug instead of ID...
elif re.match(r'\w+', name):
cls = self.__class__
instance = cls.query(cls.slug == name).get()
if instance:
return instance
raise KeyError
questions
I have basically two big questions (widh some sub-questions):
How should I handle traversal in described scenario?
Should I extend some class, or implement an interface, or something else?
Should traversal be handled at model level (movie model, or it's superclass would have __getitem__ method)? Should resource be a model instance?
What's the best practice for __getitem__ that returns collection (list) of resources? In this scenario /movies/
My ModelResource in the code above is not location aware... I'm having trouble getting __public__ and __name__ to work, probably because this is the wrong way to do traversal :) I'm guessing once I find the right way, nested resources shouldn't be a problem.
How can I switch back from traversal to url dispatching?
For the extra stuff: How can I set a different renderer to handle JSON requests? Before I added traversal I configured config.add_route('json', '/{path:.*}.json') and it worked with appropriate view, but now this route is never matched...
Same problem as above - I added a view that handles HTTP methods #view_config(request_method='GET'), but it's never matched in this configuration.
Sorry for the long post, but it's fairly complex scenario. I should probably mention that real app has 10-15 models atm, so I'm looking for solution that would handle everything in one place - I want to avoid manually setting up Resource Tree...
I have Python 3.2 set up with Apache via mod_wsgi. I have CherryPy 3.2 serving a simple "Hello World" web page. I'd like to start templating using Jinja2 as I build out the site. I'm new to Python and therefore don't know much about Python, CherryPy, or Jinja.
Using the code below, I can load the site root (/) and the products page (/products) with their basic text. That at least lets me know I've got Python, mod_wsgi, and CherryPy set up somewhat properly.
Because the site will have many pages, I'd like to implement the Jinja template in a way that prevents me from having to declare and render the template in each page handler class. As far as I can tell, the best way to do that is by wrapping the PageHandler, similar to these examples:
http://docs.cherrypy.org/dev/concepts/dispatching.html#replacing-page-handlers
http://docs.cherrypy.org/stable/refman/_cptools.html#cherrypy._cptools.HandlerWrapperTool
I've implemented the code in the second example, but it doesn't change anything.
[more details after code]
wsgi_handler.py - A mash-up of a few tutorials and examples
import sys, os
abspath = os.path.dirname(__file__)
sys.path.append(abspath)
sys.path.append(abspath + '/libs')
sys.path.append(abspath + '/app')
sys.stdout = sys.stderr
import atexit
import threading
import cherrypy
from cherrypy._cptools import HandlerWrapperTool
from libs.jinja2 import Environment, PackageLoader
# Import from custom module
from core import Page, Products
cherrypy.config.update({'environment': 'embedded'})
env = Environment(loader=PackageLoader('app', 'templates'))
# This should wrap the PageHandler
def interpolator(next_handler, *args, **kwargs):
template = env.get_template('base.html')
response_dict = next_handler(*args, **kwargs)
return template.render(**response_dict)
# Put the wrapper in place(?)
cherrypy.tools.jinja = HandlerWrapperTool(interpolator)
# Configure site routing
root = Page()
root.products = Products()
# Load the application
application = cherrypy.Application(root, '', abspath + '/app/config')
/app/config
[/]
request.dispatch: cherrypy.dispatch.MethodDispatcher()
core module classes
class Page:
exposed = True
def GET(self):
return "got Page"
def POST(self, name, password):
return "created"
class Products:
exposed = True
def GET(self):
return "got Products"
def POST(self, name, password):
return "created"
Based on what I read on a Google Group I figured I might need to "turn on" the Jinja tool, so I updated my config to this:
/app/config
[/]
tools.jinja.on = True
request.dispatch: cherrypy.dispatch.MethodDispatcher()
After updating the config, the site root and products pages display an CherryPy generated error page "500 Internal Server Error". No detailed error messages are found in the logs (at least not in the logs I'm aware of).
Unless it came pre-installed, I know I probably need the Jinja Tool that's out there, but I don't know where to put it or how to enable it. How do I do that?
Am I going about this the right way, or is there some better way?
Edit (21-May-2012):
Here is the Jinja2 template I'm working with:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
I figured it out.
In the interpolator function, the next_handler function call the original PageHandler (Page.GET or Products.GET in this case). Those original PageHandlers return strings while the interpolator function is treating the response like a python dict (dictionary), hence the double asterisk when it's passed to template.render as **response_dict.
The Jinja template has a placeholder for title, so it needs a title to be defined. Passing a plain string to the render function doesn't define what title should be. We need to pass an actual dict to the render function (or nothing at all, but what good is that?).
Note: For either of these fixes, the jinja tool does need to be enabled, as shown in the question by setting tools.jinja.on to True in the config.
Quick Fix
Define the title as the render function is called. To do this I need to change this line:
return template.render(**response_dict) # passing the string as dict - bad
to this:
return template.render(title=response_dict) # pass as string and assign to title
Like this, the template renders with my PageHandler text as the page title.
Better Fix
Because the template will grow to be more complex, one render function probably won't always be able to correctly assign the necessary placeholders. It's probably a good idea to let the original page handler return an actual dict with the template's many placeholders assigned.
Leave the interpolator function as it was:
def interpolator(next_handler, *args, **kwargs):
template = env.get_template('base.html')
response_dict = next_handler(*args, **kwargs)
return template.render(**response_dict)
Update Page and Products to return actual dicts that define the value's for the template's placeholders:
class Page:
exposed = True
def GET(self):
dict = {'title' : "got Page"}
return dict
def POST(self, name, password):
# This should be updated too
# I just haven't used it yet
return "created"
class Products:
exposed = True
def GET(self):
dict = {'title' : "got Products"}
return dict
def POST(self, name, password):
# This should be updated too
# I just haven't used it yet
return "created"
Like this, the template renders with my PageHandler title text as the page title.
There's also an updated Jinja2 tool found on a repository of various recipes the community has contributed to.