Login

Snippets by willhardy

Snippet List

FeaturedModelChoiceField

Here is a way to get a drop down list from a queryset, with a list of "featured" items appearing at the top (from another queryset). This can be used for long select boxes which have a subset of commonly used values. The empty label is used as a separator and values can appear in both the featured set and the full set (it's more usable if they are in both). For example a country drop down list with 5 featured countries might look like this: Andorra Australia Kazakhstan Singapore Turkey ------------ Afghanistan Albania Algeria American Samoa Andorra Angola (hundreds more) To use this, define your form field like this: country = FeaturedModelChoiceField(queryset=Country.objects.all(), featured_queryset=Country.objects.featured())

  • fields
  • forms
Read More

slug filename

A one-liner that I use all the time: Set `upload_to` to something based on the slug and the filename's extension. Just add this function to the top of your models and use it like this: image = models.FileField(upload_to=slug_filename('people')) and the `upload_to` path will end up like this for eg `myfile.jpg`: people/this-is-the-slug.jpg Enjoy!

  • upload_to
Read More

convenience parent class for UserProfile model

This is just a reusable convenience parent class to allow you to create and administer an automatic user profile class using the following code: class UserProfile(UserProfileModel): likes_kittens = models.BooleanField(default=True) Whenever a `User` object is created, a corresponding `UserProfile` will also be created. That's it. NB: You will still need to set `AUTH_PROFILE_MODULE` in your settings :-) (PS: It would also be nice to have the resulting class proxy the `User` object's attributes like django's model inheritance does, while still automatically creating a `UserProfile` object when a `User` object is created :-)

  • userprofile
Read More

Friendly ID

Invoice numbers like "0000004" are a little unprofessional in that they expose how many sales a system has made, and can be used to monitor the rate of sales over a given time. They are also harder for customers to read back to you, especially if they are 10 digits long. This is simply a perfect hash function to convert an integer (from eg an ID AutoField) to a unique number. The ID is then made shorter and more user-friendly by converting to a string of letters and numbers that wont be confused for one another (in speech or text). To use it: import friendly_id class MyModel(models.Model): invoice_id = models.CharField(max_length=6, null=True, blank=True, unique=True) def save(self, *args, **kwargs): super(MyModel, self).save(*args, **kwargs) # Populate the invoice_id if it is missing if self.id and not self.invoice_id: self.invoice_id = friendly_id.encode(self.id) super(MyModel, self).save(*args, **kwargs) if self.id and not self.invoice_id When an object from this model is saved, an invoice ID will be generated that does not resemble those surrounding it. For example, where you are expecting millions of invoices the IDs generated from the AutoField primary key will be: obj.id obj.invoice_id 1 TTH9R 2 45FLU 3 6ACXD 4 8G98W 5 AQ6HF 6 DV3TY ... 9999999 J8UE5 The functions are deterministic, so running it again sometime will give the same result, and generated strings are unique for the given range (the default max is 10,000,000). Specifying a higher range allows you to have more IDs, but all the strings will then be longer. You have to decide which you need: short strings or many strings :-) This problem could have also been solved using a random invoice_id generator, but that might cause collisions which cost time to rectify, especially when a decent proportion of the available values are taken (eg 10%). Anyhow, someone else has now already written this little module for you, so now you don't have to write your own :-)

  • field
  • id
Read More

Full Model History

This was a wild experiment, which appears to work! One model holds all the data, from every object version ever to exist. The other model simply points to the latest object from its gigantic brother. All fields can be accessed transparently from the little model version, so the user need not know what is going on. Coincidently, Django model inheritance does exactly the same thing, so to keep things insanely simple, that's what we'll use: class EmployeeHistory(FullHistory): name = models.CharField(max_length=100) class Employee(EmployeeHistory): pass That's it! Django admin can be used to administer the `Employee` and every version will be kept as its own `EmployeeHistory` object, these can of course all be browsed using the admin :-) This is early days and just a proof of concept. I'd like to see how far I can go with this, handling `ForeignKey`s, `ManyToManyField`s, using custom managers and so on. It should all be straightforward, especially as the primary keys should be pretty static in the history objects... *updated 3 August 2009 for Django 1.1 and working date_updated fields*

  • history
  • audit-trail
Read More

SuperChoices

Seeing [snippet 1178](http://www.djangosnippets.org/snippets/1178/) reminded me that I also had a go at writing a Choices class at some point. I'm content with the result, but I doubt xgettext will discover your translation strings, which will no doubt be inconvenient. Here it is anyway, in all its overly-complicated glory :-) The following demo was pulled from the function's docstring tests. >>> simple = Choices("one", "two", "three") >>> simple Choices(one=0, two=1, three=2) >>> tuple(simple) ((0, u'ein'), (1, u'zwei'), (2, u'drei')) >>> (0, _('one')) in simple True >>> simple.ONE 0 >>> hasattr(simple, 'FOUR') False Ordering just follows the order that positional arguments were given. Keyword arguments are ordered by their value at appear after positional arguments. >>> [ key for key, val in simple ] [0, 1, 2] >>> Choices(one=1, two=2, three=3) Choices(one=1, two=2, three=3) A Mix of keyword and non-keyword arguments >>> Choices("one", two=2, three=3) Choices(one=0, two=2, three=3) Automatically generated values (for "one" below) should not clash. >>> Choices("one", none=0, three=1, four=2) Choices(one=3, none=0, three=1, four=2) Here is an example of combined usage, using different object types. >>> combined = Choices(one=1, two="two", three=None, four=False) >>> len(combined) 4 >>> (1, _('one')) in combined True >>> ('two', _('two')) in combined True >>> (None, _('three')) in combined True >>> (False, _('four')) in combined True And here is an empty choices set. Not sure why you would want this.... >>> empty = Choices() >>> empty Choices()

  • models
  • choices
Read More

Django model cron jobs

Inspired by [snippet 1126](http://www.djangosnippets.org/snippets/1126/), I thought I would post a module that stores crontab entries in a database, with a less powerful, but more end-user friendly API. ("twice a week starting on Sat 1 Dec 2007, 6:23am", instead of "23 6,18 * * *"). The crontab is synchronised when an entry is changed, and relevant environment variables, function name and arguments are provided. You might want to store this as an app called "scheduler" to match the imports. Enjoy!

  • cron-jobs
  • scheduled-events
Read More

Admin definition converter (for newforms-admin)

A script I wrote a little while ago to help speed up newforms-admin conversion. From memory it works best when run from an old-forms installation, but it is still useful post-conversion. There are some features missing, but it's supposed to be a starter. Just install this command and run: ./manange.py port2nfa > admin.py (To install, copy the file to management/commands/port2nfa.py in an app somewhere)

  • newforms
  • admin
  • command
Read More

SSL Redirect Middleware and testing

While we're on the topic of SSLRedirect (See snippet 240 and 880) here's what I add to the end of my ssl middleware module, so that SSLRedirect wont break my automated testing. It simply creates a dummy middleware class that removes the SSL argument, but does not do any redirecting. If you were to simply remove the middleware from settings, the extra SSL argument will then get passed on to all the relevant views. Of course, you'll need to define a TESTING variable in settings, or change this to something else like settings.DEBUG. Having the separate variable for testing allows you to run your server in DEBUG mode without side effects like the change above.

  • middleware
  • ssl
  • testing
  • redirect
Read More

Command to dump data as a python script

This creates a fixture in the form of a python script. Handles: 1. `ForeignKey` and `ManyToManyField`s (using python variables, not IDs) 2. Self-referencing `ForeignKey` (and M2M) fields 3. Sub-classed models 4. `ContentType` fields 5. Recursive references 6. `AutoField`s are excluded 7. Parent models are only included when no other child model links to it There are a few benefits to this: 1. edit script to create 1,000s of generated entries using `for` loops, python modules etc. 2. little drama with model evolution: foreign keys handled naturally without IDs, new and removed columns are ignored The [runscript command by poelzi](http://code.djangoproject.com/ticket/6243), complements this command very nicely! e.g. $ ./manage.py dumpscript appname > scripts/testdata.py $ ./manage.py reset appname $ ./manage.py runscript testdata

  • dump
  • manage.py
  • serialization
  • fixtures
  • migration
  • data
  • schema-evolution
  • management
  • commands
  • command
Read More

willhardy has posted 10 snippets.