Tag | Python
Add a Read-Only Role to Django Admin
I was in a meeting where I was asked to give someone read-only access to the Admin part of our application. That was fine — it was written in Django and Django has really fantastic Admin functionality. So I assumed that it could handle it, no problem. So I said yes.
Of course, after a little googling, I found that that it doesn’t support this at all — you can only give people Add, Change, or Delete permissions. You can make individual fields read-only but, in an ideal world, I needed a whole object to be read-only or not, hopefully determined by Group membership.
My searches didn’t give me a lot of hope, but I did find something close in this post.. So I expanded it to look for a Group.
This is what I came up with:
So you used ReadOnlyAdmin to inherit from instead of ModelAdmin for all Admin objects you want to make read-only. Then you also have to add these two properties:
user_readonly– list of the fields to be read-only. If you don’t put in there, the user will be able to change the Model!user_readonly_inlines– If you have a related Model that you want to display Inline, then you can’t add it touser_readonlybecause it’s not part of the Model. You have create a read-only InlineAdmin object and list that here.
Creating a read-only Admin object is simple:
class MyModelInline(admin.StackedInline):
model =MyModel
class MyModelReadOnlyInline(MyModelInline):
readonly_fields = ["label",]
Then you just list MyModelReadOnlyInline in the user_readonly_inlines and MyModelInline in inlines.
To use the ReadOnlyAdmin:
- Create a Admin Group called
readonly. - Add the User to
readonlyand give them full access to the Models you want them to read — yes, give them Add, Change, etc. Or they can’t view them at all.
When the user logs in, they will see the Model and go to individual ones, but none of the fields will be in form fields — just straight text.
Slicing some Python with Emacs
I have a new job and it’s quite probable that I will be doing Python for a lot of it. Which suites me just fine.
. . . except that I’ve been out of the loop in a while. Sure, I have written some Python in the past five years and some of it has been substantial but I feel out of the loop. Most of my simple scripts have been done in good ol’ Emacs and bigger projects have been done in Intellij IDEA with their amazing Python plugin.
As I started at the new digs, I installed Intellij on my shiny MacBook Pro, turned on Emacs mode . . . and was underwhelmed. I forgot that Emacs mode in Intellij on Mac leaves a lot to be desired — C-Del for Cut, Alt-P for paste? Ugh. A quick search shows that I’m not the only one complaining, but it’s not fixable.
I thought about Emacs and what I would miss about running things in Intellij IDEA. The biggies were:
- Syntax checking
- Running unit tests
- Auto-refactoring (Extract Variable, Method, etc)
These are things that are supposed to separate an IDE from a text editor. However, Emacs is an elegant weapon from a more civilized age. So the hunt is on to see what others have did while I was on my hibernation from Python.
I’ve tried to use the Rope library in the past and found it hard to setup. But I did note that it’s still actively developed and so I tried find to some example configs to steal borrow from. That’s when I found Gabriele Lanaro’s excellent emacs-for-python collection. It included Rope, YA Snippet, and other goodies, all configured to work together in harmony.
I forked it, cloned it, and had a few problems, so I fixed them and Gabriele merged them back in. It still didn’t have unit test support, but I found nosemacs, which runs Nose on the Python unit tests.
In searching for something else, I stumbled into virtualenvwrapper, which are some helpers around the most excellent virtualenv utility, which creates a clean environment for Python development. These are used in emacs-for-python, so I put it in as well. I then stumbled into this post, which explains how to use the hooks in virtualenvwrapper to control Emacs. Woot!
So now my workflow is like this:
- type ‘workon something’, which will put my prompt in my “clean room” Python environment for the
project. My Emacs has also switched to that environment, including using that version of the Python interpreter. - In Emacs, type
C-c m, which will run and report on all my unit tests in my current module - In Emacs, type ‘C-c r ` to extract a new variable. Other commands exist for class, method, etc.
- type
deactivateand my prompt moves away from my clean room, and my Emacs leaves too. - when I go back to work on
somethingEmacs will remember the last buffers it worked on.
I put all these changes into my branch of emacs-for-python, and Gabriele has already pulled them in. They are available in HEAD on emacs-for-python
Build a Path for Elementtree Namespaces
I really like using ElementTree and it’s lxml and xml.etree brethern. But one of my pet peeves is how it deals with namespaces. I understand the reasoning — it’s just difficult and bulky. Combining the syntax of {namespace-uri} with an XPath-like search string can be confusing.
I’m muddling over this while I’m writing yet another utility script to help me with some XML. I stop and decided I’m going to build a help class, wittingly called PathBuilder.
class PathBuilder:
def __init__(self,namespace_uri):
self._template=string.Template("{%s}$tag" %namespace_uri)
def all_tags(self,tag):
return "//"+self._template.substitute(tag=tag)
def all_decendents(self,tag):
return ".//"+self._template.substitute(tag=tag)
def children(self,tag):
return self._template.substitute(tag=tag)
My methods above are all that I need at this point, but you can see how to build them all. I can put all my path building knowledge in that class and then just tell it what I want and it will give it to me.
Using Jython as a Terracotta Command Line
My new position at work was best described to me from my AVP: “Figure out how to make it work.” The first thing that I need to see if it will work is Terracotta. Terracotta is cool stuff — more to follow on it later. Probably.
If you know me well enough, or have been reading this blog for a while, you know that I’m a big fan of Python. Well, if I need to figure out how to “make it work” it generally involves Jython. That way, I can open a prompt up and noodle around at the object and see what makes them tick. To me, this could be especially important in Terracotta since you have objects floating around everywhere.
Getting Jython as a command-line interface into a Terracotta cluster is trivial — almost not worth blogging about. And the result is oh-so cool.
Here is my Jython script. It just imports some common things and a Spring application context, and then get an object from the context. That object contains my Terracotta root object, which means that it stays in sync across my client and server JVM’s.
import sys,os
from org.springframework.context.support import ClassPathXmlApplicationContext
if __name__ == '__main__':
ctx = ClassPathXmlApplicationContext("applicationContext.xml")
worker=ctx.getBean("worker")
Not that there isn’t anything specific to Terracotta in there — just like it should be.
I then wrote a shell script to setup my environment and run my Jython script in a Terracotta-instrumented environment. I actually run everything in Windows (unfortunately) so I have some Cygwin magic in there to change the classpath and to run the dso-java.bat in a cmd window:
#!/bin/sh cp="dowork.jar:/c/Projects/jython2.5.1rc2/jython.jar" cygstart bin/dso-java.bat -classpath `cygpath -mp $cp` org.python.util.jython -i $1 $2 $3 $4 $5
This allows me to run any script in a Terracotta cluster and then keep a command line open to I can muck around with stuff. Thejython.jar I use is a stand-alone install. I’ve just found that easier than worrying about where all modules are.
So now I just enter the shell script name with my Jython script as an argument and away I go!
And this works exactly as I expected. I can see the state of the root in the worker object, update that state in another clustered JVM, and then see that state immediately in my Jython prompt.
I’m sure you can do the same with Groovy, JRUby and their ilk. But I use Jython. It’s just how I roll
