Pyramid: modifying site content based on settings - python

Is it possible to alter the contents of a view/template based on specific user-defined settings in development.ini or production.ini.
As an example say I am developing a pyramid web-app that lists all the students of the class. The back-end database has only one table - 'student'. Now I develop an optional script that also adds a table 'teacher' to the database. Ideally the web-app should be able to run for both the cases. If teacher table is missing, it will not query it and simply print student details. If teacher table is present, it will print name of the teacher along with the name of the student.
To my mind this can be accomplished in one of the following ways -
Keep separate routes (URLs) for teacher+student and student only
pages. The problem is that you cannot stop people from actually
calling the former when you only have student info. This will lead
to unnecessary error pages
Use a setting teacher_enabled=true/false in .ini file. The setting can be accessed in __ init __.py file through settings['teacher_enabled']. Configure just a single route (say'home','/') but map it to different views based on whether seeting variable is true/false. This will not allow for use of #view_config decorator and templates for both cases will have to be separate
Again using the setting variable, pass it to the view somehow. Make only relevant queries in the view. E.g. - If the teacher_enabled is True, query the teacher table else query the student table only. Pass this variable to templates too and there decide if some details are to be displayed (e.g. teacher name).
So my question is which of these approaches should I use? In case settings variables are to be passed to the views, how can that be done? And is there a standard way of dealing with this problem?

Keep separate routes (URLs) for teacher+student and student only pages. The problem is that you cannot stop people from actually calling the former when you only have student info.
Ah, but you can! Combine it with number 2: Add a teacher_enabled=true/false setting to your .ini file, and then you can use some code similar to this:
from pyramid.threadlocal import get_current_registry
from pyramid.httpexceptions import HTTPFound
#Define some awesome student views here
#view_config(name='student')
def student(request):
return HTTPFound('Foo!')
if get_current_registry().settings['teacher_enabled']:
#Some awesome student and teacher views here
#view_config(name='student_and_teacher')
def student_and_teacher(request):
return HTTPFound('Bar!')
Number 3 is also feasible. Just remember: It's easier to ask for forgiveness than permission. So you could do something like this: (Using SQLAlchemy as an example)
from your_models.teacher import Teacher
from sqlalchemy.exc import NoSuchTableError
try:
teacher = session.query(Teacher).filter(Teacher.id==42).first()
except NoSuchTableError:
teacher = Teacher('Unknown')

Related

How to make the 'return' from a django model conditional to the value of a global variable?

I am a novice in both Python and Django, and I am struggling to find the way to make a 'return' from a Django model conditional upon the value of a global variable.
More specifically, I am designing an app to run an interview with the user / visitor. In the interview the questions to the user can be in past or present tense. This depends on an introduction view from which I get the choice from the user, i.e. either 'past' or 'now'.
My model is
class Question(models.Model):
key = models.CharField(max_length=50)
value = models.CharField(max_length=50)
question_text_past = models.CharField(max_length=2000)
question_text_now = models.CharField(max_length=2000)
def __str__(self):
global TENSE
if TENSE == 'past':
return self.question_text_past
else:
return self.question_text_now
However, no matter what I've tried (while testing the code within the shell), my model does not reflect the changes in the value of TENSE. The model returns a "not defined" error. I've also tried to put TENSE into a module globals.py and import this into my models.py with no success. I might be missing something simple but fundamental about Django, so I appreciate any help.
You can't implement this logic using a global variable in the modules file.
I suggest to call .question_text_past or .question_text_past on the Question object at the location where the logic happens.
I've found three different possibilities to eliminate / replace global variables in my app. In my app (i.e. running a virtual interview with a user) I use the same template over the same view, but the variables within the view change their values depending on the user's choice / response. It is a little bit like a function calling itself with new arguments, but having to "remember" what were the old ones.
First. I set up a classes.py module which contains the class Global. Each attribute replaces a previously global variable. Then import this class in views.py. This avoids Django handling the class as a DB table.
Second. Create the same class as a model. List and dictionary types are defined as JSONField. Here an initial view creates a new instance, a DB record with an id. This id, however, may still need to be "globally" accessible throughout the interview view. One solution was to start a Django Session and use session_key (an awful string) as the id of the newly created record. The other choice was to use a "global" variable through Constance to assign the automatic id to it in settings.py.
Third. Use Constance for all global variables. However, after reading the docs, I had the impression that Constance was not designed to accommodate frequently changing dynamic variables, and it may be problematic using it to store complex data types, e.g. lists, dictionaries. But, again, this was just an impression.
I would appreciate your opinion / guidance / suggestion.

Flask - User to Profile Relationships

I'm working with Flask-restplus and I am at a point where I would like to associate each User in my user model to a type of profile, where each user can be associated with one or many profile types. I'm wondering how you guys would go about this. So far, here's what I'm thinking/planning to do. NOTE: I'm not very experienced in web development, so there's a chance I don't know the best way to accomplish this.
Step 1: Create a one-to-many (clients need to also be employees, see below) field (profile_types) relating to a static table that just lists all possible profile options. EXAMPLE:
PK PROFILE TYPE
1 provider
2 employee
3 client
.....
The idea here is to track different information and allow for different views/endpoints for users who are tied to certain profile types. Example, employees would provide a valid login authentication and be directed to page A while a client would be directed to page B, etc. We're also planning on collecting different data points within each profile model.
So an instance of a user might look like this, user1.profile == [client, employee'].
NOTE: This is more important for data collection (ie age of employee, start date, etc) than it is for creating directives based on permissions.
Step 2: Upon creating the new user, a signal fires off the creation of a profile based on the profile_types supplied to the user instance. I've used signals with django in the past, is there a signal library for Flask?
Step 3: An empty profile instance(s) now exists for that user. It will be up to a superuser to upload data in bulk or manually fill out profile information.
Is this a sensible way to go about this? My other though is to create a bunch of Boolean fields in the User model is_provider, is_employee, is_client, etc. All fields that are True get assigned a profile instance. What's the best way to go about this?
Thanks everyone!
Seeing that are you try to validate multiple profile types, you may use
if user.profile_type in ['employee', 'client']
Now, if you want to add an super user I think you can use this
if user.profile_type in ['employee', 'client'] and user.profile_type == 'superuser'
Now, you relationship is more like 'many-to-many', because you are saying that an client also needs to be an employee, if you mean that some endpoints needs to be accessible for employees and clients, then you need to use a 'many-to-one' relationship (an Stackoverflow question which explains what is that)
For your instances, there is Flask Marshmallow, which has an amazing compatibility with Flask SQLAlchemy if you are using an database, but Flask Marshmallow can work alone.

Where to Start with Custom Reporting Python/Django

I'm trying to find a way to build a robust report library that I can use with a Django project.
Essentially, what I'm looking for is a way to access a list of functions(reports) that I can allow an end-user to attach to a Django model.
For example, let's say I have an Employee object. Well, I have a module called reports.py that has a growing list of possible reports that take an employee object and output a report, usually in JSON form. There might be number of timecards submitted, number of supervisions created, etc.
I want to be able to link those changing report lists to the Employee object via a FK called (job description), so admins can create custom reports per job description.
What I've tried:
Direct model methods: good for some things, but it requires a programmer to call them in a template or via API to generate some output. Since the available reports are changing, I don't want to hard-code anything and would rather allow the end-user to choose from a list of available reports and attach them to a related model (say a JobDescription).
dir(reports): I could offer up a form where the select values are the results from dir(reports), but then I'd get the names of variables/libraries called in the file, not just a list of available reports
Am I missing something? Is there a way to create a custom class from which I can call all methods available? Where would I even start with that type of architecture?
I really appreciate any sort of input re: the path to take. Really just a 'look in this direction' response would be really appreciated.
What I would do is expand on your dir(reports) idea and create a dynamically loaded module system. Have a folder with .py files containing module classes. Here's an example of how you can dynamically load classes in Python.
Each class would have a static function called getReportName() so you could show something readable to the user, and a member function createReport(self, myModel) which gets the model and does it's magic on it.
And then just show all the possible reports to the user, user selects one and you run the createReport on the selected class.
In the future you might think about having different report folders for different models, and this too should be possible by reflection using model's __name__ attribute.

How to add to google app engine flask website the user registration ability if it wasn't scheduled in application architecture

I created website-app for myself and it become really useful and many peoples wont also use it. But user management was not scheduled in application architecture. Is there any way to easy add user registration so each user would have his own google database tables but with same name?
example of one "table":
class Settings(db.Model):
email = db.StringProperty()
link = db.LinkProperty()
rating = db.StringProperty()
How can I separate data from this "table" between different users? I search for some kind of wrapper so I don't need to change current architecture.
You have to remember there is no concept of tables with the datastore so you can't have a separate set of tables for each user as such.
You have a few choices, the two I would investigate are
create a separate app with the existing code base and each user runs their own site. You may not need to do any code changes at all
If you want complete separation of data for each user in a single app then look at namespaces (thats how multi-tenancy is normally implemented.)
However you haven't really provided a clear definition of how you want to separate the users etc.. so there a probably other approaches you can take.
Short of having a copy of the database for each user; you'll have to implement some code changes.
The easiest one you can do is add a foreign key to your data tables that points to your user table; then you filter all records based on this foreign key.
Once you have that change, you can write a view decorator that will automatically filter the records for you.

Django - alternative to subclassing User?

I am using the standard User model (django.contrib.auth) which comes with Django. I have made some of my own models in a Django application and created a relationship between like this:
from django.db import models
from django.contrib.auth.models import User
class GroupMembership(models.Model):
user = models.ForeignKey(User, null = True, blank = True, related_name='memberships')
#other irrelevant fields removed from example
So I can now do this to get all of a user's current memberships:
user.memberships.all()
However, I want to be able to do a more complex query, like this:
user.memberships.all().select_related('group__name')
This works fine but I want to fetch this data in a template. It seems silly to try to put this sort of logic inside a template (and I can't seem to make it work anyway), so I want to create a better way of doing it. I could sub-class User, but that doesn't seem like a great solution - I may in future want to move my application into other Django sites, and presumably if there was any another application that sub-classed User I wouldn't be able to get it to work.
Is the best to create a method inside GroupMembership called something like get_by_user(user)? Would I be able to call this from a template?
I would appreciate any advice anybody can give on structuring this - sorry if this is a bit long/vague.
First, calling select_related and passing arguments, doesn't do anything. It's a hint that cache should be populated.
You would never call select_related in a template, only a view function. And only when you knew you needed all those related objects for other processing.
"Is the best to create a method inside GroupMembership called something like get_by_user(user)?"
You have this. I'm not sure what's wrong with it.
GroupMembership.objects.filter( user="someUser" )
"Would I be able to call this from a template?"
No. That's what view functions are for.
groups = GroupMembership.objects.filter( user="someUser" )
Then you provide the groups object to the template for rendering.
Edit
This is one line of code; it doesn't seem that onerous a burden to include this in all your view functions.
If you want this to appear on every page, you have lots of choices that do not involve repeating this line of code..
A view function can call another function.
You might want to try callable objects instead of simple functions; these can subclass a common callable object that fills in this information.
You can add a template context processor to put this into the context of all templates that are rendered.
You could write your own decorator to assure that this is done in every view function that has the decorator.

Categories

Resources