Where to validate Django AJAX app? - python

I'm working on an event based AJAX application using Django. Within my models I've a class that creates and updates an objects and I would like to include better input validation. For example, I know that my start date should be before my end date and would like to check for this fact within the app.
Do I place this within my models? It seems messy to messy to check all 8 input parameters are valid within the creation or save method.
For example, something like this:
if foo != '' and int(foo) > 0:
self.foo = foo
I know Django has the functionality to validate forms, but can this also be applied to AJAX streams?

Maybe this may help: https://github.com/alex/django-ajax-validation
Documentation:
https://github.com/alex/django-ajax-validation/blob/master/docs/usage.txt
https://github.com/alex/django-ajax-validation/blob/master/docs/serving-ajax-validation-media-server.txt

Related

How to create a Django REST Framework View instance from a ViewSet class?

I'm trying to unit test Django REST Framework view set permissions for two reasons: speed and simplicity. In keeping with these goals I would also like to avoid using any mocking frameworks. Basically I want to do something like this:
request = APIRequestFactory().post(…)
view = MyViewSet.as_view(actions={"post": "create"})
self.assertTrue(MyPermission().has_permission(request, view))
The problem with this approach is that view is not actually a View instance but rather a function which does something with a View instance, and it does not have certain properties which I use in has_permission, such as action. How do I construct the kind of View instance which can be passed to has_permission?
The permission is already tested at both the integration and acceptance level, but I would like to avoid creating several complex and time-consuming tests to simply check that each of the relevant actions are protected.
I've been able to work around this by monkeypatching a view set instance and manually dispatching it:
view_set = MyViewSet()
view_set.action_map = {"post": "create"}
view_set.dispatch(request)
You can do something like below.
request = APIRequestFactory().post(…)
view_obj = MyViewSet()
self.assertTrue(MyPermission().has_permission(request, view_obj))

Global Variables in Django Admin Site

This was my original question, but it was not answered and so I thought Id post again with some of the strategies that I have tried, and be a little more specific.
I want to create a dynamic admin site, that based on if the field is blank or not will show that field. So I have a model that has a set number of fields, but for each individual entry will not contain all of the fields in my model and I want to exclude based on if that field is blank. My project is about bridges, and so to put it in practical terms I have a model that has every bridge part in it (this roughly is equivalent to 100), but each individual bridge (mapped to each unique brkey) will not have all 100 bridge parts. And so, I can prepopulate all of the fields it does have, but then the admin site has 100 other fields, and I would like to not display those fields that were not used on my admin site for that specific bridge, but those fields will differ with pretty much every bridge.
Like I said before, I have a unique bridge identifier(a unique 15 digit string), that correlates to each bridge, and then all of the various different variables that describe the bridge.
I have it set up now that the user will go to a url with the unique bridgekey and then this will create an entry of that bridge. So (as i am testing on my local machine) it would be like localhost/home/brkey and that code in my views.py that corresponds to that url is
Is this a final route that I have to take? I am very new to JavaScript and so I do not want to take this route but I will if I have to. Also does Django use Javascript in anyway that is syntactically different? If so I cannot find any Django documentation on incorporating Javascript into my admin site.
A final option that I have exhausted is to use global variables. Instead of having the url that creates the entry in my Views.py, I placed it in my admins.py, and had my modelAdmin class in there as well, so like this.
admins.py
-set up global variable
bridgekey_unique = " "
If I can find a way to either pass that unique bridge key to my modelAdmin class, or figure out if that said field is blank because the bridge doesnt have that part, I will be able to achieve what I want without using Javascript. I have tried a lot of variations of all two of theses strategies to no avail, but have not tried the JavaScript idea as I dont really know any javascript at all.
Sorry for the lengthy post, but people said I wasnt specific enough. Any help would be greatly appreciated.
I didn't read all of that - sorry, there's too much. But I did notice your comment that you expect to access in your modeladmin definition a variable that you set in your view. That can't possibly work.
Anything at class level is always executed when the module containing the class is first imported. That is when the server process starts up, so there is no possible way anything done in the view can have happened yet.
You almost never want to have any logic at class level. You need to put it in methods, which are called at the relevant time. In this case, you probably need to use the get_fields method.
Edit
Looking further up at your attempt at a get_fields method, I can't see at all what you are trying to do here. 'prestressed_concrete_deck' is a literal string, and could never be None, so neither of your conditions can ever be true. And as to your question about what the parameters are, the documentation for that method explains clearly that obj is the object being edited.

Django: make field editable depending on the value of other field

I'm new to Django, and I haven't found the answer yet in the extensive documentation. I'm asking for pointers to research, not for working code. That being said, here's my problem:
In one of my models theres a BooleanField (it gets rendered in the admin form as a checkBox). Let's call it 'A'. It only makes sense to edit other field (say, CharField 'B') if A is checked.
So, is there a way to make B read only, or even changing its content to an empty string, dinamically, if A is checked? Thank you.
(Django 1.5.2, Python 2.7.5)
You're going to need several things to make this work. You may be able to skip some of them depending if you mainly care abut the UI, or the data integrity in the db.
Since the user can (presumably) check/uncheck Field A on the client-side you need some Javascript to enable/disable the appearance of Field B. These docs show how to load custom JS in your ModelAdmin class:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-asset-definitions
In your ModelForm you may want to do some check in the __init__ method against the value of self.instance.field_a and substitute some kind of ReadOnlyWidget for Field B for the initial display of the form. These docs show how to give your ModelAdmin a custom form class:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
If you are writing some Javascript to do that dynamically it make be easier to skip this step and just do it client-side.
Finally you can use Django model validation to ensure that Field B is saved with a null value if Field A is checked:
https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects

create view similar to another one

I have to make some changes in a django project and though I'm familiar with python, I'm not with django.
This is my situation:
I have a table with the field "active". What I need to do is to let the users to sort the table based on the value of the field (yes/no).
I looked into views.py and I realized that there is a view that sorts the table based on the id:
users = User.objects.all().order_by('id')
My questions are:
How can I make the view to sort the table based on the url parameter?
Do I have to create another view or can I use the same with some kind of modifications?
You can use the same view.
def myView(request):
get_param = request.GET.get('my_param', 'id')
#some more processing
users = User.objects.order_by(get_param) #note - you dont need the `all()`
#rest of the code here.
That depends on what you want to render in your template. If both views will render similar html the it's probably better refactor them in a generic view and do the sorting depending on GET parameters.
I like separation of concerns, so another approach may be refactoring the view code inside a helper function and just call it inside each view with separated urls.
If the views doesn't render similar html and are different from each other in every aspect except that they sort something in some place, then I think the best way is to code both view separately.
It's just a consideration problem but answering your question you can get GET params accessing the request.GET or request.POST depending on the method.
Hope it helps!

Django get_query_set override is being cached

I'm overriding Django's get_query_set function on one of my models dynamically. I'm doing this to forcibly filter the original query set returned by Model.objects.all/filter/get by a "scenario" value, using a decorator. Here's the decorator's function:
# Get the base QuerySet for these models before we modify their
# QuerySet managers. This prevents infinite recursion since the
# get_query_set function doesn't rely on itself to get this base QuerySet.
all_income_objects = Income.objects.all()
# Figure out what scenario the user is using.
current_scenario = Scenario.objects.get(user=request.user, selected=True)
# Modify the imported income class to filter based on the current scenario.
Expense.objects.get_query_set = lambda: all_expense_objects.filter(scenario=current_scenario)
# Call the method that was initially supposed to
# be executed before we were so rudely interrupted.
return view(request, **arguments)
I'm doing this to DRY up the code, so that all of my queries aren't littered with an additional filter. However, if the scenario changes, no objects are being returned. If I kill all of my python processes on my server, the objects for the newly select scenario appear. I'm thinking that it's caching the modified class, and then when the scenario changes, it's applying another filter that will never make sense, since objects can only have one scenario at a time.
This hasn't been an issue with user-based filters because the user never changes for my session. Is passenger doing something stupid to hold onto class objects between requests? Should I be bailing on this weird design pattern and just implement these filters on a per-view basis? There must be a best practice for DRYing filters up that apply across many views based on something dynamic, like the current user.
What about creating a Manager object for the model which takes the user as an argument where this filtering is done. My understanding of being DRY w/ Django querysets is to use a Model Manager
#### view code:
def some_view(request):
expenses = Expense.objects.filter_by_cur_scenario(request.user)
# add additional filters here, or add to manager via more params
expenses = expenses.filter(something_else=True)
#### models code:
class ExpenseManager(models.Manager):
def filter_by_cur_scenario(self, user):
current_scenario = Scenario.objects.get(user=request.user, selected=True)
return self.filter(scenario=current_scenario)
class Expense(models.Model):
objects = ExpenseManager()
Also, one quick caveat on the manager (which may apply to overriding get_query_set): foreign relationships will not take into account any filtering done at this level. For example, you override the MyObject.objects.filter() method to always filter out deleted rows; A model w/ a foreignkey to that won't use that filter function (at least from what I understand -- someone please correct me if I'm wrong).
I was hoping to have this implementation happen without having to code anything in other views. Essentially, after the class is imported, I want to modify it so that no matter where it's referenced using Expense.objects.get/filter/all it's already been filtered. As a result, there is no implementation required for any of the other views; it's completely transparent. And, even in cases where I'm using it as a ForeignKey, when an object is retrieved using the aforementioned Expense.objects.get/filter/all, they'll be filtered as well.

Categories