Content tagged with "django"
Markdown and Django Post on Apr 25, 2011
Note to self (aren't they all...)
One line after {% filter markdown %} or it renders as code...
Satchmo store and YAML fixtures Post on Oct 20, 2010
I have been working on a Satchmo installation, which is pretty intense because of the size of the project, but, because it's Django, it's still relatively simple to find what I need. Recently I got the error:
ContactRole matching query does not exist
It was pretty simple, although not obvious at first. The YAML fixtures for the satchmo_store.contact app weren't installing because I didn't have PyYAML installed on my machine. A quick installation, another syncdb and boom, good to go.
Cheers, Aaron
Django and multiple joins on the same table Post on Jan 22, 2010
I picked up this trick back using Wordpress, which I always kinda liked, you scenario: you have a Content model and a Date model, but the Date model is generically-related:
#django models
class Date(models.Model):
# GR stuff
content_type = models.ForeignKey(ContentType, null=True, blank=True)
object_id = models.PositiveIntegerField(null=True, blank=True)
content_object = generic.GenericForeignKey()
# actual data
key = models.CharField(max_length=75)
date = models.DateTimeField()
class Content(models.Model):
title = models.CharField(max_length=75)
body = models.TextField()
dates = generic.GenericRelation(Date)
The reason you would do this is so you could have as many dates related to the content as you wanted (you don't have to use a generic relation for this, but I like to use dates on lots of things).
What fun
I'm a little eccentric, I like to do wierd things, like with Django's .extra() method on querysets, you can do some funky stuff, like pull several of the generically-related dates based on their 'key' value, and add that 'key' value directly to the Content object as though it were a native attribute. Something like this:
>>> from myapp.models import Content, Date >>> from datetime import datetime >>> content = Content(title="Hello", body="My content :)") >>> content.save() >>> post_date = Date(key='post_date', date=datetime.now()) >>> post_date.save() >>> content.dates.add(post_date) >>> modified_date = Date(key='modified_date', date=datetime.now)) >>> modified_date.save() >>> content.dates.add(modified_date)
Now the trick here is to join the myapp_date table on to our content twice, which is easy enough:
>>> content = Content.objects.all() >>> content.filter(dates__key='post_date') >>> content.filter(dates__key='modified_date')
But now we have a problem
Because django is so wonderful, it does all the work of joining tables and keeping track of those pesky aliases for you, but how do we select the dates from the joined tables (using .extra(select={xxx})) if we don't know the aliases? Well we can spit out the query, as mentioned in the django docs, and that works fine (for now):
>>> print content.query # live on the edge...
# the result is something like:
SELECT "myapp_content"."title", "myapp_content"."body" FROM "myapp_content" INNER JOIN "myapp_date" ON ("myapp_content"."id" = "myapp_date"."object_id") INNER JOIN "myapp_date" T2 ON ("myapp_content"."id" = T2."object_id") WHERE ("myapp_date"."key" = "post_date" AND T2."key" = "modified_date")
# Disclaimer: I wrote this query by hand, it's an approximation, yours may differ, also note: it's pretty damn close.
Now if you were just feeling adventurous, you could simply nab the alias names from that query and grab the extra data as needed:
>>> content.extra(select={'post_date': 'myapp_date.date', 'modified_date': 'T2.date'})
>>> print content.query
# the result is something like:
SELECT (myapp_date.date) AS post_date, (T2.date) AS modified_date, "myapp_content"."title", "myapp_content"."body" FROM "myapp_content" INNER JOIN "myapp_date" ON ("myapp_content"."id" = "myapp_date"."object_id") INNER JOIN "myapp_date" T2 ON ("myapp_content"."id" = T2."object_id") WHERE ("myapp_date"."key" = "post_date" AND T2."key" = "modified_date")
# extra(select={}) just pops a couple extra selects in there, like it should, but yuck, static references ie: T2
>>> content[0].post_date
datetime.datetime(2010, ...)
>>> content[0].modified_date
datetime.datetime(2010, ...)
Fun huh?
But, there is a gotcha...
I had been employing this method in an application, and arbitrarily decided to upgrade my django. Lo' and behold, the alias names changed! Whooda thought? So after much turmoil and source-code-diggery, I found the way to get those pesky aliases (and therefore perform the query) without all the guilt. The trick was I had to find the place in django.db.models.sql.query.Query where the table alias (T2) was related to the part in the where clause that was related to the field (post_until). The answer was in the content object's where clause, something like:
>>> content.query.where.children [(<django.db.models.sql.where.constraint object="object" at="at">, 'exact', True, 'post_date'),(</django.db.models.sql.where.constraint><django.db.models.sql.where.constraint object="object" at="at">, 'exact', True, 'modified_date'),...] >>> content.query.where.children[0].alias # < the constraint holds the key, literally 'myapp_date' >>> content.query.where.children[1].alias 'T2' </django.db.models.sql.where.constraint>
And there you have it
So my quick solution to keep the aliases produced by they code referenced dynamically, I just build a quick little dict out of the 'where.children' so I could reference the aliases properly later...
# summed up
>>> content = Content.objects.all()
>>> content.filter(dates__key='post_date')
>>> content.filter(dates__key='modified_date')
>>> alias_map = {}
>>> for condition in content.query.where.children:
... # alias_map['modified_date'] = 'T2'
... alias_map[condition[3]] = condition[0].alias
>>> content.extra(select={ \
... 'post_date': '%s.date' % alias_map['post_date'], \
... 'modified_date': '%s.date' % alias_map['modified_date']})
And with that, the keys end up as they should. Nothing spectacular, it just took some digging to find where the join "black magic" was happening in django. Thanks to jtiai on #django for the pointers.
Hope that really helps someone down the line,
Aaron
Flex Django and AMF Post on Dec 15, 2009
Been working back in Flex again a bit, using Vim in Linux for a while, but I been really impressed with the short compile times in FlashDevelop for Windows.
Besides the point
Having become increasingly frustrated with the shortcomings of Django-amf, I've decided to give pyamf another try. I tried it the first time around, and got hung up on an error that made me bail out on it:
Cannot find a view for the path ['/gateway/cardservice/echo'], 'DjangoGateway' object has no attribute '__name__'
Some poking around in the source didn't help any, but the fix turned out to be easy. I stumbled on this post on StackOverflow, the author answered his own question in his comment. Turns out, leaving the django-amf middleware turned on in the settings.py file messed up the operation.
I don't have enough clout on StackOverflow to tell the author thanks there, so I'll do it here...
Aaron
Dreamhost, Django, Premature end of script headers: dispatch.fcgi Post on Oct 28, 2009
This problem comes up from time to time on my Dreamhost account, I get a long page load, finally ending with a 500 error in the browser. Tail'ing the apache error_log shows:
... [Wed Oct 28 13:48:37 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:48:37 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:48:40 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:49:18 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:49:21 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:49:58 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi [Wed Oct 28 13:50:39 2009] [error] [client 198.53.10.99] Premature end of script headers: dispatch.fcgi ...
But where's the real error?
A little trick for you: go to the folder where your dispatch.fcgi file is and type:
./dispatch.fcgi
Basically you are executing the script, similar to an incoming request. You should then see the original traceback.
Hth,
Aaron
Dreamhost and Django (fcgi) caching Post on Oct 28, 2009
Every once in a while (while dabbling with Django on Dreamhost) I run into the problem that Dreamhost appears to cache my site. I've even canned the db or deleted the settings file to try and provoke an error. But the site ticks on (for a bit anyway), and I want to see results now! damnit...I am after all hacking on the live site instead of my staging server! Talk about living on the edge!
The cure
Thwart the so-called caching with a mighty blow to the process itself, it will be restarted at the next request:
killall -USR1 dispatch.fcgi
Thanks to the dreamhosters forum for the tip.
Af
Automatic moderation with Django 1.0 Comments Post on Oct 16, 2008
This one was actually a lot easier than I thought it would be. The Django comments framework was totally revamped for the Django 1.0 release, and it is now way mo betta :)
But! Even with all the new anti-spam stuff built in, I needed all comments to go into a moderation queue for a client site. At first I tried the pre_save hook to change the is_public flag on the comment, but there's no way (that I could tell) how to distinguish when the comment was submitted, and when it was moderated.
The solution
The Django folks are always thinking :) Then put in a sweet little hook called comment_will_be_posted that gets called when the user submits the comment. Hook in and change the 'is_public' flag to 'False', and the comments automatically go into the moderation queue.
The Code
from django.contrib.comments.models import Comment from django.core.mail import send_mail from django.contrib.sites.models import Site from django.contrib.comments.signals import comment_will_be_posted from django.conf import settings def comment_set_public(sender, comment, request, **kwargs): # set the flag to false so it hits moderation comment.is_public = False # send an email subject = '%s > New Comment on %s' % (Site.objects.get_current(), comment.content_object.title) msg = """ You have a new comment on the item:\n%s\n\n Comment text:\n%s\n\n To moderate comments, visit the link below:\n http://%s/comments/moderate/ """ % (comment.content_object.title, comment.comment, Site.objects.get_current()) send_mail(subject, msg, settings.COMMENT_FROM_EMAIL, [settings.COMMENT_TO_EMAIL]) # from the docs: "If any receiver returns False the comment will be discarded..." # so there's much more potential for spam checking/protection return True # the hook comment_will_be_posted.connect(comment_set_public, sender=Comment)
Other goodies
Just for good measure, we put email notification in the same place which is handy (otherwise, how would you know comments were added?). The other super handy goodie with Comments 1.0 is they have added views for moderation also. Just point your browser to:
http://mysite.com/comments/moderate/
and you get a nice little view that looks just like the admin interface with which to moderate your comments. Obviously, if you're not logged in, it will prompt you to do so :)
Cheers, Af
PS: Here's a little screen to give you a taste:
Django TimeSelect widget Snippet on Oct 15, 2008
# based on the DateSelect widget from django, tested with newforms-admin, need to test with 1.0 class SelectTimeWidget(Widget): """ A Widget that splits time input into two <select> boxes. This also serves as an example of a Widget that has more than one HTML element and hence implements value_from_datadict. """ hour_field = '%s_hour' minute_field = '%s_minute' apm_field = '%s_apm' def __init__(self, attrs=None): # years is an optional list/tuple of years to use in the "year" select box. self.attrs = attrs or {} def render(self, name, value, attrs=None): hour_val = minute_val = apm_val = None try: value = datetime.time(*map(int, value.split(':'))) #value = datetime.date(*map(int, value.split('-'))) #pdb.set_trace() #year_val, month_val, day_val = value.year, value.month, value.day if value.hour > 12: value.hour -= 12 apm_val = 'pm' else: hour_val = value.hour apm_val = 'am' minute_val = value.minute except (AttributeError, TypeError, ValueError): hour_val = '8' minute_val = apm_val = None output = [] hour_choices = ( ('1','1'), ('2','2'), ('3','3'), ('4','4'), ('5','5'), ('6','6'), ('7','7'), ('8','8'), ('9','9'), ('10','10'), ('11','11'), ('12','12'), ) select_html = Select(choices=hour_choices).render(self.hour_field % name, hour_val) output.append(select_html) minute_choices = (('00','00'), ('15','15'), ('30','30'), ('45','45')) select_html = Select(choices=minute_choices).render(self.minute_field % name, minute_val) output.append(select_html) apm_choices = (('am','AM'), ('pm','PM')) select_html = Select(choices=apm_choices).render(self.apm_field % name, apm_val) output.append(select_html) return mark_safe(u'\n'.join(output)) def value_from_datadict(self, data, files, name): #y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name) h, m, a = data.get(self.hour_field % name), data.get(self.minute_field % name), data.get(self.apm_field % name) if a == 'pm': h = int(h) + 12 if h and m: return '%s:%s:%s' % (h,m,'00') #if y and m and d: # return '%s-%s-%s' % (y, m, d) return data.get(name, None) </select>
Comment email notification in Django 1.0 on Webfaction Post on Oct 10, 2008
It's always nice to know when someone posts a comment on your blog, and if you're using something like Wordpress then email notification is already built in. Well, you guessed it, I'm not using Wordpress :)
The code
I got the original code to hook into signals sent from the comment system from here, but it's not compatible with 1.0. Thankfully, the fix is easy:
from django.contrib.comments.models import Comment from django.core.mail import send_mail from django.db.models.signals import post_save def comment_notification(sender, instance, **kwargs): subject = 'New Comment on %s' % instance.content_object.title msg = 'Comment text:\n\n%s' % instance.comment send_mail(subject, msg, 'from@mysite.ca', ['mail-to-me@mysite.com']) # ideally these go in the settings post_save.connect(comment_notification, sender=Comment)
There were minimal modifications to make the code work from the original version, now the next trick is to get Webfaction to send my email.
Webfaction and send_mail
Wefaction won't just let you send mail right off the bat, you need to set up a mailbox and email address on your Webfaction account, and then change a couple settings in your project's settings.py file. I had found a forum post with the details but they implied I should be using 'mailx.webfaction.com' (x being my mail server number), but it wouldn't work. I recalled after that my outgoing mail server is 'smtp.webfaction.com'.
EMAIL_HOST='smtp.webfaction.com' EMAIL_HOST_USER='mymailbox' # < this should be the mailbox EMAIL_HOST_PASSWORD='mymailboxpass' # < a valid password (obviously) EMAIL_PORT='25' DEFAULT_FROM_EMAIL = "my-email@my-webfaction-account.com" # < the next 2 are the email address tied you your mailbox SERVER_EMAIL = "my-email@my-webfaction-account.com"
And bada-bing! The mail comes through snappy fast too. Thank goodness for Django, black licorice, and Webfaction :)
Cheers, Aaron
Django 1.0 Cheat Sheet Link on Oct 09, 2008
http://www.mercurytide.co.uk/whitepapers/django-cheat-sheet/
The first post (again) Post on Sep 23, 2008
Okay, I'm going to test the first post this time. My 'miraculous new system' that I'm using for my weblog failed to post my first blog post. So let's test it first.
Okay, so it worked
I feel better now. I won't ramble on about the new site, let's just say this site is the first manifestation of the 'top-secret' project I've been working on, and is just a little test to try out the versatility of it.
More to come later, af