Django's tastypie is an open source project that allows programmers to create restful APIs quickly while following Django patterns. I was using tastypie to create my website's API and had trouble with a particular situation, following a reverse relationship even though it is suppose to be well documented here (https://django-tastypie.readthedocs.org/en/latest/resources.html#reverse-relationships). The errors I made were simply following directions closely. Enjoy.

Here is my general solution shown with the standard [] brackets syntax. Setup:
  • [top] is the parent resource with will have 0 or more children "[bottom]s". 
  • [bottom] is the child resource.
  • An example is User having Blogs. In this case, a blog cannot exist without a User specified.  



API.py

class [top]Resource(ModelResource):
    [bottom]s = fields.ToManyField([bottom]Resource, '[bottom]s', full=True, null=True)
    class Meta:
        queryset = [top].objects.all()

class [bottom]Resource(ModelResource):
    class Meta:
        queryset = [bottom].objects.all()

Models.py
class [top](models.Model):
pass

class [bottom](models.Model):
    [top] = models.ForeignKey([top],related_name="[bottom]s")

Example with User and Blog:


API.py

class User Resource(ModelResource):
    blogs = fields.ToManyField(BlogResource, 'blogs', full=True, null=True)
    class Meta:
        queryset = User.objects.all()

class BlogResource(ModelResource):
    class Meta:
        queryset = Blog.objects.all()

Models.py
class User(models.Model):
pass

class Blog(models.Model):
    user = models.ForeignKey(User,related_name="blogs")

3

View comments

  1. This works great for ToMany relationships, but in OneToOne relationships it puts your single related object within a 1-element array. Yet when I simply change your ToManyField declarations to ToOneFields instead I get a "RelatedManager has no attribute XYZ" error. This makes sense within Django, because we're getting a Manager instead of an actual object -- but is there a way to tell TastyPie to take the next step?

    ReplyDelete
  2. The ForeignKey.related_name in the models.Model class must match the Tastypie REST API attribute. Otherwise, I see Tastypie fail silently with an empty list like "reverse_field": [].

    The definitions below must match the text "blog" exactly since Python is case sensitive. This is a really odd restriction!
    blogs = fields.ToManyField(BlogResource, 'blogs', full=True, null=True)
    and
    user = models.ForeignKey(User,related_name="blogs")

    ReplyDelete
  3. It took me too long to find this! Thank you for the clear example. If the models were on the TastyPie docs as yours are here, it would have saved me a lot of time.

    ReplyDelete
  1. TL;DR; for setting up Mailvelop with gmail in Chrome.

    1. Stop being lazy.
    2. Go here: https://chrome.google.com/webstore/detail/mailvelope/kajibbejlbohfaggdiogboambcijhkke
    3. Hit add to chrome.
    4. Hit the Mailvelope chrome icon.
    Mailvelope Icon
    5. Hit Options.
    Context Menu
    6. Go through the Generate Key Wizard.
    7. Go to Display Keys.
    8. High light the key you just generated.
    9. In the Blue drop down at the top, click and select display public key.

    10. Copy and paste that value and send it to your friends.
    11. Do the import key wizard for all of your good friends.
    12. Go to gmail.
    13. If you have the new compose email enabled switch back to the old composition style.
    Click on the Switch back to old compose

    14. Write your email and then hit the encrypt icon.
    Lock Icon.

    15. Follow the steps to encrypt.

    0

    Add a comment

  2. Django's tastypie is an open source project that allows programmers to create restful APIs quickly while following Django patterns. I was using tastypie to create my website's API and had trouble with a particular situation, following a reverse relationship even though it is suppose to be well documented here (https://django-tastypie.readthedocs.org/en/latest/resources.html#reverse-relationships). The errors I made were simply following directions closely. Enjoy.

    Here is my general solution shown with the standard [] brackets syntax. Setup:
    • [top] is the parent resource with will have 0 or more children "[bottom]s". 
    • [bottom] is the child resource.
    • An example is User having Blogs. In this case, a blog cannot exist without a User specified.  



    API.py

    class [top]Resource(ModelResource):
        [bottom]s = fields.ToManyField([bottom]Resource, '[bottom]s', full=True, null=True)
        class Meta:
            queryset = [top].objects.all()

    class [bottom]Resource(ModelResource):
        class Meta:
            queryset = [bottom].objects.all()

    Models.py
    class [top](models.Model):
    pass

    class [bottom](models.Model):
        [top] = models.ForeignKey([top],related_name="[bottom]s")

    Example with User and Blog:


    API.py

    class User Resource(ModelResource):
        blogs = fields.ToManyField(BlogResource, 'blogs', full=True, null=True)
        class Meta:
            queryset = User.objects.all()

    class BlogResource(ModelResource):
        class Meta:
            queryset = Blog.objects.all()

    Models.py
    class User(models.Model):
    pass

    class Blog(models.Model):
        user = models.ForeignKey(User,related_name="blogs")

    3

    View comments

    1. This works great for ToMany relationships, but in OneToOne relationships it puts your single related object within a 1-element array. Yet when I simply change your ToManyField declarations to ToOneFields instead I get a "RelatedManager has no attribute XYZ" error. This makes sense within Django, because we're getting a Manager instead of an actual object -- but is there a way to tell TastyPie to take the next step?

      ReplyDelete
    2. The ForeignKey.related_name in the models.Model class must match the Tastypie REST API attribute. Otherwise, I see Tastypie fail silently with an empty list like "reverse_field": [].

      The definitions below must match the text "blog" exactly since Python is case sensitive. This is a really odd restriction!
      blogs = fields.ToManyField(BlogResource, 'blogs', full=True, null=True)
      and
      user = models.ForeignKey(User,related_name="blogs")

      ReplyDelete
    3. It took me too long to find this! Thank you for the clear example. If the models were on the TastyPie docs as yours are here, it would have saved me a lot of time.

      ReplyDelete
  3. This is a TL;DR; version of getting mysql working on OS X and/or Centos (this post became a bastardization, sorry). There are a number of problems that can happen but if you follow this guide you should avoid many of the pit falls:

    Source:
    http://decoding.wordpress.com/2012/01/23/how-to-setup-django-and-mysql-python-on-mac-os-x-lion/

    Prereqs:
    sh setuptools-0.6c11-py2.6.egg
    yum install gcc
    yum install mysql-devel
    yum install mysql-client
    yum install mysql mysql-server
    yum install python-devel

    Simple directions:
    1. Go here: http://dev.mysql.com/downloads/mysql/
    2. Download the 64 bit version of MySql.
    3. Untar the download.
    4. Rename the directory mysql.
    5. Move that directory to /usr/local/
    6. Go here: http://sourceforge.net/projects/mysql-python/files/mysql-python/
    7. Download the latest version of MySQL for Python.
    8. Untar the download.
    9. Open up site.cfg with vi. 
      1. $ vi site.cfg
        1. Goto the line that sets mysql_config.
        2. Edit that line to read: mysql_config = /usr/local/mysql/bin/mysql_config
    10. Run the install with the following comands.
      1. $ sudo python setup.py build
      2. $ sudo python setup.py install
    11. Edit the .bashprofile.
      1. $ vi ~/.bashprofile
      2. Add this line to the end of the file: export DYLD_LIBRARY_PATH=/usr/local/mysql/lib/
      3. Restart the terminal to reload the .bashprofile.
    Double check your install works with:
    $python
    >>> import MySQLdb


    0

    Add a comment

  4. Django 1.4 now has templates which allow a more meta programming style. Here is how to use them and how to use them effectively. Pinax has a great example but I forked theirs and made my own template.

    The new startproject.

    django-admin.py startproject --template=https://github.com/vccabral/DjangoTemplate/zipball/master <project_name>
    Go here to view the directory structure needed: https://github.com/vccabral/DjangoTemplate. The directory is copied and it uses the handle bar mustache syntax to replace certain variables.

    The new startapp.

    django-admin.py startapp --template=https://github.com/vccabral/DjangoAppTemplate/zipball/master <app_name>


    A few things to notice.

    1. Github can convert a project into a zipped download by adding /zipball/[branch].
    2. Django template automatically unzips certain file types.
    3. Including a requirements.txt file in the github repo along with virtualenv will allow easy up time.
    virtualenv localpython --distribute
    source localpython/bin/activate
    pip install -r requirements.txt
    //edit your settings.py to reflect your database settings. 
    python manage.py syncdb
    python manage.py runserver

    My app template has a urls.py file that adds urlpatterns. Simply add the new app to the settings.py file and add the following line to the urls.py in the project directory and you are good to go. 
        
        url(r"^app_url/", include("app.urls")), 

    This project/app combo will create a bootstrap pinax site in no time flat. 


    0

    Add a comment

Blog Archive
About Me
About Me
My Photo
My friend calls me Larbac. I spent several years doing ASP.NET, Java, and PHP web development. After attempting a project in a django, I left my previous ways and have embraced python and django with the god like reverence they deserve. I originally got my start in computers while working as a janitor at MIT sneaking around solving problems that only a few people in the world could solve. After a short love affair with Mini Driver, I quit to move to California leaving my eccentric psychologist with only these immortal words, "I have to go see about a girl". In a former life, I worked at Booz Allen Hamilton doing IT Consulting.
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.