Tyrel's Blog

Code, Flying, Tech, Automation

Oct 15, 2023

Djangocon 2023

I am at DjangoCon 2023 this year!

I live in Durham, NC and have been avoiding conferences for the past few years because of Covid and not wanting to travel. This year for, what ever reason, they picked Durham!

So I am breaking my "Don't go to conferences" for multiple reasons.

  1. The DSF has pretty great Covid rules, and mask requirements.
  2. Testing requirements.
  3. It's local, so I get to sleep in my own bed.

I'm not guaranteed to get to see my daughter, but I hope she knows I still love her even if I'm not around. I'm leaving at 7:30 tomorrow as I'm biking in, and she may be asleep.

Already I've gone to one of the local breweries I haven't gone to yet (See above: Covid), and met some great people, can't wait for the rest of the week.

While technically a "Tech Blog" I am by no means a great note taker, so don't expect any quality information from me in blog form, I'm mostly going for the HallwayTrack, and to watch talks.

 · · ·  django  conferences

Nov 13, 2013

How to not trigger a post_save in Django, but still modify data.

Recently I have been diving into using signals with Django, which of course are pretty neat.

I am working on a website for work which in the most basicexplanation, is a task management site. Recently I have added in the ability to subscribe to tasks and get emails, I did this by connecting to the post_save signal. I only email out when a task is changed, not created (of course, no one would be subscribed to it). This worked flawlessly and "emails" out to anyone who is subscribed. I say that in quotes, because I haven't actually hooked it up to a real SMTP server, and only use

python -m smtpd -n -c DebuggingServer localhost:1025

which will output any emails to stdout. But I digress… A problem arose when I was working on ordering tasks.

I store an integer in the "ordering" column, which any authenticated user can drag the row to a new location and that will reorder the task. I did this after I setup the emailing signal, so I didn't think about an email being sent out for EVERY task being changed.

I tried a lot of different things, and was debating some that would be a bit messy. Among those ideas were trying to store the past values in another table, but that would get expensive fast. The reason I tried this was because I wanted to see if the ordering was the only thing that changed, and if that was the case, not send an email. I eventually found a thread on StackOverflow that says to use update on the queryset to not trigger the signal.

You can do this by doing something like this:

from app.models import ModelName

def reorder(request):
    new_order = request.POST.get('new_order', None)
    pk = request.POST.get('modelname_pk', None)
    if new_order:
       ModelName.objects.filter(pk=pk).update(ordering=new_order)

I am not sure if this is the proper way save changes and not trigger a post_save signal, but this is the way that worked for me so I figured I would document this.

 · · ·  django  python

Aug 06, 2013

Help, I have too many Django ManyToMany Queries [FIXED]

My boss tasked me with getting the load time of 90 seconds(HOLY CARP!) on one page down. First thing I did was install the Django Debug Toolbar to see what was really happening.

There are currently 2,000 users in the database, the way our model is setup is that a UserProfile can have other UserProfiles attached to it in one of three M2M relations, which in the Django Admin would cause 2,000 queries PER M2M field. This is very expensive as obviously you don't want 10,000 queries that each take 0.3ms to take place.

The solution, after a day and a half of research is to override the formfield_for_manytomany method in the Admin class for our UserProfile object.

Our solution is to prefetch for any M2M that are related to the current Model.

def formfield_for_manytomany(self, db_field, request, **kwargs):
    if db_field.__class__.__name__ == "ManyToManyField" and \
        db_field.rel.to.__name__ == self.model.__name__:
        kwargs['queryset'] = db_field.rel.to.objects.prefetch_related("user")
    return super(UserProfileInline, self).formfield_for_manytomany(
        db_field, request, **kwargs)

This goes inside our admin class UserProfileInline(admin.StackedInline). Simple clean and easy to drop into another ModelAdmin with minimal changes.

Other things I pondered was to set all our M2M's as raw_id_fields, then using Select2 or Chosen, query our UserProfiles when the related users were being selected. This would take a lot of load off the initial page load, but is more of a bandaid rather than a real fix.

I tried to override the Admin class's def queryset(self, request): but this was not affecting anything.

 · · ·  python  django  bugs

Jan 05, 2012

Custom Django URLField

For work I had to write a custom url model field. This model field when setting up accepts a default protocol, and a list of other protocols.

When checking the protocol, the url is split by "://". If the split has one or two parts, then the url is validly formed.

In the event of a single element split, there is no protocol specified. When there is no protocol, the url is prepended with the default protocol specified. If there is a protocol, it is checked to make sure it exists in a union of the default protocol and other protocols. If it is not, a ValidationError is raised letting the user know that the protocol is not accepted.

This can all be found at On my github [deadlink].

I have a couple ways I could have done this better and probably will. Improvements would be just one parameter called parameters in which it is checked if there is at least one element. Passing this, when there is no protocol specified, the first element is the default one.

This would be a little cleaner.

this example would allow for http, https, ssh, spdy and mailto, anything else would error out.

facebook_page = URLField(default_protocol="http", protocols=["https","ssh","spdy","mailto"])

The way I could improve this would be

facebook_page = URLField(protocols=["https","https","ssh","spdy","mailto"])
 · · ·  python  django