Harry Khanna
Attorney at Law
Note type

Today I Learned

When I learn a random, useful thing I write it down. It's usually tweet-length and captures the insight I gleaned that day. I group them by year.


  • To install Office 365 on Linux with Crossover Office, you have to download the "offline installer" via the My Account page on account.microsoft.com. But if you're on Linux, it won't let you download it. It keeps telling you to refresh the page. You can get around this by spoofing your User Agent in your browser with a browser extension to make it look like you're on Microsoft Windows. Once you have the .iso file, mount it. The Crossover installer should then be able to see it and install from it. I got to the end of the install and it wouldn't work, so I abandoned it. Will use LibreOffice for now.


  • There appears to be a bug in Google Analytics 4 where linked analytics.js properties don't properly receive pageview events if your GA tracking ID is the GA4 id. The flip side works fine though: If your GA tracking ID is the UA-XXX-type ID, linked GA 4 properties receive pageview events fine.
  • When you are trying to JOIN models in Django that are not related via the ORM, you have to use a Subquery and OuterRef and can only join one column at a time. #django
  • When telling a story, a useful tactic is to describe "how did I feel then?" and "how do I feel now?" #storytelling
  • When telling a story, give us a quirk of each character in a story. For example, if I were telling a story about my friend Jared, I would comment on his fascination with law firm bathrooms. #storytelling
  • usePaginatedQuery is the same as useQuery but status is always success after the first load and resolvedData and latestData take the place of data. #reactjs
  • A ManytoMany relationship in Django will not allow duplicate relations. I.e., the same exact relation can't appear twice in the join table. If you use Model.add() to add the same relation twice, it will just ignore it and not duplicate the relation. #django
  • In Django Rest Framework, rest_framework.exceptions.ValidationError === rest_framework.serializers.ValidationError. If you raise the error in a serializer, you get the non_field_error/field formulation. If you raise it outside, you just get whatever you raised. According to inline comments in DRF, you should actually always reference serializers.ValidationError to avoid confusion with the django named ValidationError. #django
  • Django Rest Framework Serializers
    • Serializer(data=XXX) used to run validation on writable fields and pass a .validated_data to .create() of those writable fields. That same .validated_data gets run back through to_representation to get a .data to return back to the browser.
    • Serializer(instance) does not validate and should be used when (1) your fetching an instance from the db and returning it serialized or (2) you just need to normalize an object into a different representation (e.g., converting account_ids from a pure python object to account slugs).
    • Passing both instance and data to Serializer is for PUT/update operations.
    • .validated_data is generated from to_internal_value. .data is generated from to_representation.