Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django V Rails

Django V Rails

A talk I gave to pybelfast on the 26th October 2016

Stephen McCullough

November 05, 2016
Tweet

More Decks by Stephen McCullough

Other Decks in Programming

Transcript

  1. django v rails
    Stephen McCullough

    View full-size slide

  2. who am i
    • Stephen McCullough
    • @swmcc on the interwebs
    • Senior Software Engineer @ ShopKeep
    • We are hiring - python/ruby - talk to me after

    View full-size slide

  3. Translation
    • models
    • template
    • views
    • URL
    • models
    • views
    • controllers
    • routes
    django rails

    View full-size slide

  4. Tools
    • pypi
    • pip
    • pdb
    • virtualenv
    • rubygems
    • bundler
    • debugger
    • rvm/rbenv
    django rails

    View full-size slide

  5. Comparison
    • generic templates
    • models
    • admin interface
    • authentication
    • south
    • scaffolding
    • active record
    • active admin
    • devise
    • migrations
    django rails

    View full-size slide

  6. models
    To create a model in rails you run a command
    rails generate model SomeModel 

    somerow:string
    class SomeModel < ActiveRecord::Base


    end
    create_table “some_model”, force => true do |t|
    t.string “somerow”
    end

    View full-size slide

  7. models
    To create a model in django you run a command
    class SomeModel(models.Model):

    somerow = models.CharField()
    created_at = models.DateTimeField(auto_now_add=True)
    upcated_at = models.DateTimeField(auto_now=True)

    View full-size slide

  8. migrations
    To create a migration in rails you run a command
    rails generate migration AddAnotherThingToSomeModel
    something_else:string

    View full-size slide

  9. migrations
    To create a migration in django you edit model.py
    class SomeModel(models.Model):

    somerow = models.CharField()
    something_else = models.CharField()
    created_at = models.DateTimeField(auto_now_add=True)
    upcated_at = models.DateTimeField(auto_now=True)
    end
    python manage.py schemamigration somemodel —auto
    python manage.py migrate somemodel

    View full-size slide

  10. queries
    In rails you can be quite expressive with your queries.
    Client.where(created_at: (Time.now.midnight -
    1.day)..Time.now.midnight)
    Model.where('field >= ?', value)
    Model.objects.filter(field__gt=value)

    View full-size slide

  11. controllers
    In rails the controllers look nice.
    class OrdersController < ApplicationController
    def index
    @orders = Order.where(active: true)
    end
    def show
    @order = Order.find(params[:id])
    end
    def new
    @order = Order.new
    end
    def create
    @order = Order.new(params[:order])
    if @order.save
    redirect_to @order
    else
    render 'new'
    end
    end
    end

    View full-size slide

  12. controllers
    In django the controllers don’t look so nice.
    # django usually calls the 'show' method 'detail'
    # the product_id parameter comes from the routing
    def detail(request, product_id):
    p = Product.objects.get(pk=product_id) # pk = primary key
    # renders detail.html with the third parameter passed as context
    return render(request, 'products/detail.html', {'product': p})
    def create(request):
    # check if form was submitted
    if request.method == 'POST':
    # similar to RoR' 'create' action
    form = ProductForm(request.POST) # A form bound to the POST data
    if form.is_valid(): # All validation rules pass
    new_product = form.save()
    return HttpResponseRedirect(new_product.get_absolute_url())
    else:
    # similar to RoR' 'new' action
    form = ProductForm() # An empty form
    return render(request, 'products/create.html', { 'form': form })

    View full-size slide

  13. controllers
    In django controllers don’t look so nice.
    # Supposes the routing passed in a parameter called 'pk'
    # containing the object id and uses it for fetching the object.
    # Automatically renders the view /products/product_detail.html
    # and passes product as a context variable to the view.
    class ProductDetail(DetailView):
    model = Product
    # Generates a form for the given model. If data is POSTed,
    # automatically validates the form and creates the resource.
    # Automatically renders the view /products/product_create.html
    # and passes the form as a context variable to the view.
    class ProductCreate(CreateView):
    model = Product

    View full-size slide

  14. views
    Forms
    <%= form_tag("/contact", method: "post") do %>
    <%= label_tag(:subject, "Subject:") %>
    <%= text_field_tag(:subject) %>
    <%= label_tag(:message, "Message:") %>
    <%= text_field_tag(:message) %>
    <%= label_tag(:subject, "Sender:") %>
    <%= text_field_tag(:sender) %>
    <%= label_tag(:subject, "CC myself:") %>
    <%= check_box_tag(:sender) %>
    <%= submit_tag("Search") %>
    <% end %>

    View full-size slide

  15. views
    Forms
    class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)
    def contact(request):
    if request.method == 'POST':
    form = ContactForm(request.POST)
    if form.is_valid():
    return HttpResponseRedirect('/thanks/') # Redirect after POST
    else:
    form = ContactForm() # An unbound form
    return render(request, 'contact.html', { 'form': form }

    View full-size slide

  16. views
    Forms
    class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)
    def contact(request):
    if request.method == 'POST':
    form = ContactForm(request.POST)
    if form.is_valid():
    return HttpResponseRedirect('/thanks/') # Redirect after POST
    else:
    form = ContactForm() # An unbound form
    return render(request, 'contact.html', { 'form': form }

    View full-size slide

  17. views
    Forms

    {{ form.as_p }}


    View full-size slide

  18. routing
    # automatically maps GET /products/:id to products#show
    # GET /products to products#index
    # POST /products to products#create
    # DELETE /products/:id to products#destroy
    # etc.
    resources :products
    urlpatterns = patterns('',
    # matches the detail method in the products controller
    url(r'^products/(?P\d+)/$', products.views.DetailView.as_view(),
    name='detail'),
    # matches the index method, you get the gist
    url(r'^products/$', products.views.IndexView.as_view(), name='index'),
    url(r'^products/create/$', products.views.CreateView.as_view(),
    name='create'),
    url(r'^products/(?P\d+)/delete/$', products.views.DeleteView.as_view(),
    name='delete'),
    )

    View full-size slide

  19. testing
    class UsersControllerTest < ActionController::TestCase
    test "should get index" do
    get :index # GET request to the index action
    assert_response :success # request returned 200
    # assigns is a hash containing all instance variables
    assert_not_nil assigns(:users)
    end
    end
    class UsersTest(unittest.TestCase):
    def setUp(self):
    self.client = Client()
    def test_index(self):
    """ should get index """
    response = self.client.get(reverse('users:index'))
    self.assertEqual(response.status_code, 200)
    self.assertIsNotNone(response.context['users'])

    View full-size slide

  20. Conclusion
    • Both are outstanding frameworks
    • You can’t go wrong my picking either one.
    • I prefer django, marginally
    • It's not hard to switch from one to another

    View full-size slide