<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Dave Dash</title>
 <link href="http://davedash.com/tag/fixtures/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/fixtures"/>
 <updated>2012-01-17T21:54:19-08:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Your objects, and all their friends</title>
   <link href="http://davedash.com/2010/06/25/your-objects%2C-and-all-their-friends/"/>
   <updated>2010-06-25T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/06/25/your-objects,-and-all-their-friends</id>
   <content type="html">&lt;p&gt;This is complicated.&lt;/p&gt;

&lt;p&gt;In my ever-evolving quest to &lt;a href=&quot;/2010/03/05/django-fixture-magic-testing-issues-with-real-data/&quot;&gt;get data out of the AMO database&lt;/a&gt; for tests, I
found myself not just extracting a single object, but a list of complicated
requirements in order to fully replicate behavior in production in a testing
environment.&lt;/p&gt;

&lt;p&gt;For &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/&quot;&gt;AMO&lt;/a&gt; we can use &lt;a href=&quot;http://pypi.python.org/pypi/django-fixture-magic&quot;&gt;fixture magic&lt;/a&gt; to dump a single add-on and all of
it's &lt;em&gt;database&lt;/em&gt; dependencies so that it will insert safely into a
test-database.  But we need more than just valid data.  We need some supporting
data.  For an add-on to be browsable and searchable it needs to have a valid
version and the version needs to have a valid file.&lt;/p&gt;

&lt;p&gt;In our app we can check for these things by using this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my_addon.current_version.files.all()[0]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course we need to check that &lt;code&gt;my_addon.current_version&lt;/code&gt; exists and that
&lt;code&gt;files.all()&lt;/code&gt; has at least one object.  This ends up being a lot of work if you
just know the &lt;code&gt;id&lt;/code&gt; of the add-on object.&lt;/p&gt;

&lt;p&gt;So what I want is something simple, like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py custom_dump addon 3615
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it should get me everything I need to test add-on 3615, including a Version
object and any files associated with the version.&lt;/p&gt;

&lt;p&gt;Turns out this &lt;em&gt;just works&lt;/em&gt;.  It works if you define the following settings:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;## Fixture Magic&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CUSTOM_DUMPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;addon&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# ./manage.py custom_dump addon id&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;primary&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;addons.addon&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# This is our reference model.&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;dependents&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# These are items we wish to dump.&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# Magic turns this into current_version.files.all()[0].&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;#39;current_version.files.all.0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;order&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;app1.model1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;app2.model2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,),&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# stuff gets sorted&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;excludes&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;#39;app1.model1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;fields&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;to&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;hide&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Using this we're able to find out that &lt;code&gt;addon&lt;/code&gt; means an &lt;code&gt;addons.addon&lt;/code&gt; object
and that you want the &lt;code&gt;addon&lt;/code&gt; object with an id of &lt;code&gt;3615&lt;/code&gt;.  From there we'll
try looking for dependent objects.  Using some black magic we can turn:
&lt;code&gt;current_version.files.all.0&lt;/code&gt; into
&lt;code&gt;addon.objects.get(pk=3615).current_version.files.all()[0]&lt;/code&gt;.  This gives us a
file.&lt;/p&gt;

&lt;p&gt;If we mimic our &lt;code&gt;dump_object&lt;/code&gt; command we can get the &lt;code&gt;file&lt;/code&gt; into the database
and everything that the file needs to be valid.  This in turn gives us enough
data (usually) to begin testing a single &lt;code&gt;addon&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So have fun with this, if you're database is remotely complicated, this can
save you some time replicating it during testing.&lt;/p&gt;

&lt;p&gt;Also note, that you can re-order models and exclude certain fields.  This can
make your fixtures very easy to load.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>django-fixture-magic: Testing issues with real data.</title>
   <link href="http://davedash.com/2010/03/05/django-fixture-magic-testing-issues-with-real-data/"/>
   <updated>2010-03-05T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/03/05/django-fixture-magic-testing-issues-with-real-data</id>
   <content type="html">&lt;p&gt;I just released &lt;a href=&quot;http://github.com/davedash/django-fixture-magic&quot;&gt;Fixture Magic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When dealing with legacy data, you'll run into all kinds of edge cases.  Perhaps, an object might not display correctly unless it has the right parameters, or if it has null parameters it might not display at all.  So when testing &lt;a href=&quot;http://djangoproject.com/&quot;&gt;Django&lt;/a&gt;, it's nice to actually use non-dummy data.&lt;/p&gt;

&lt;p&gt;Luckily Django has a way of pulling real data out of your database using &lt;code&gt;django.core.serializers&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from addons.models import Addon
a = Addon.objects.get(id=3615)
from django.core.serializers import serialize
jsonize = lambda a: serialize(&quot;json&quot;, a, indent=4)
jsonize([a])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This solution runs well in a Django shell and can be lots of fun for the whole family... until things get complicated.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h3&gt;Serializing alone isn't enough.&lt;/h3&gt;

&lt;p&gt;Serializing a fixture with foreign keys means you'll have an un-loadable fixture unless you serialize the dependent fixtures.  Even for one or two foreign keys, this can be a pain.  For &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt;, we have a spidery-web of dependencies: &lt;code&gt;File&lt;/code&gt;s need a &lt;code&gt;Version&lt;/code&gt; which needs an &lt;code&gt;Addon&lt;/code&gt; which need &lt;code&gt;Translation&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Thus begat the &lt;code&gt;dump_object&lt;/code&gt; management command.  Give it an app, model name and a &lt;code&gt;pk&lt;/code&gt; and it will give you not only a serialized JSON of that object, but all the objects that it requires.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py dump_object files.file 64874 64876 &amp;gt; my_new_fixture.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This looks for the &lt;code&gt;File&lt;/code&gt; model in the &lt;code&gt;files&lt;/code&gt; app and pulls out of the database &lt;code&gt;File&lt;/code&gt;s instances with &lt;code&gt;pk&lt;/code&gt;s of &lt;code&gt;64874&lt;/code&gt; and &lt;code&gt;64876&lt;/code&gt;.  It then recursively searches for any required objects.&lt;/p&gt;

&lt;h3&gt;Too much serial&lt;/h3&gt;

&lt;p&gt;If you create a lot of fixtures, you'll eventually have overlapping serialized objects.  In &lt;code&gt;addons.mozilla.org&lt;/code&gt; we have &lt;code&gt;Addon&lt;/code&gt;s, &lt;code&gt;Version&lt;/code&gt;s (which depend on &lt;code&gt;Addon&lt;/code&gt;s) and &lt;code&gt;AddonCategory&lt;/code&gt;s (which depend on &lt;code&gt;Addon&lt;/code&gt;s and &lt;code&gt;Category&lt;/code&gt;s).  If we wanted to get serialize a specific &lt;code&gt;Addon&lt;/code&gt;, it's dependent &lt;code&gt;Version&lt;/code&gt;s and &lt;code&gt;AddonCategory&lt;/code&gt;s it makes sense to start with &lt;code&gt;dump_object&lt;/code&gt;ing the related &lt;code&gt;Version&lt;/code&gt; and then &lt;code&gt;dump_objecting&lt;/code&gt; the &lt;code&gt;AddonCategory&lt;/code&gt;.  Both &lt;code&gt;dump_object&lt;/code&gt; commands will fetch the &lt;code&gt;Addon&lt;/code&gt; in question, resulting in duplicated data.&lt;/p&gt;

&lt;p&gt;To combat this we can use &lt;code&gt;merge_fixtures&lt;/code&gt; to dedupe our fixtures:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py dump_object versions.version 64874 &amp;gt; 1.json
./manage.py dump_object categories.addoncategory &amp;gt; 2.json
./manage.py merge_json 1.json 2.json &amp;gt; happy_fixture.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should make creating test data slightly less painful.  So &lt;a href=&quot;http://github.com/davedash/django-fixture-magic&quot;&gt;give it a try&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Resolving Django dumpdata errors</title>
   <link href="http://davedash.com/2009/09/13/resolving-django-dumpdata-errors/"/>
   <updated>2009-09-13T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/13/resolving-django-dumpdata-errors</id>
   <content type="html">&lt;p&gt;Recently I recieved this wonderful piece of news when I ran &lt;code&gt;./manage.py dumpdata&lt;/code&gt; for the first time:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Error: Unable to serialize database: User matching query does not exist.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I knew this might not work out since I was dealing with a legacy database, but the resolution is quite simple.  First I had to narrow it down to which app was causing this.  Naturally I assumed it was one of the two apps I had, either &lt;code&gt;common&lt;/code&gt; or &lt;code&gt;restaurant&lt;/code&gt;.  So I ran: &lt;code&gt;./manage.py dumpdata common&lt;/code&gt; and &lt;code&gt;./manage.py dumpdata restaurant&lt;/code&gt;.  The latter had no problem whatsoever.&lt;/p&gt;

&lt;p&gt;This made sense, since my &lt;code&gt;common&lt;/code&gt; application was the only one that made any reference to a &lt;code&gt;User&lt;/code&gt;.  By looking in my &lt;code&gt;models.py&lt;/code&gt; for that application, I narrowed it down to my &lt;code&gt;Profile&lt;/code&gt; object.  Sure enough, commenting it out meant I could get my data.&lt;/p&gt;

&lt;p&gt;It ended up being a foreign key mismatch between the &lt;code&gt;profile&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; tables.  Since this is legacy data, this mismatch made sense.  A simple &lt;code&gt;SELECT id,userid FROM profile WHERE userid NOT IN (SELECT id FROM auth_user)&lt;/code&gt; gave me a list of bad profiles.  Removing them allowed me to create my Django fixtures.&lt;/p&gt;
</content>
 </entry>
 

</feed>

