Git Product home page Git Product logo

learn_django_by_example's Introduction

learn_Django_by_example

Django has three fundamental parts plus one usefull util Form, Form is kinda familar to Model, but worth being taken as the fourth fundamental part, so:

  1. Model Layer(django.db)
  2. View Layer(django.views class based view or view function)
  3. Template Layer(django.template)
  4. Form(django.form)

Added topic:

  1. Authentication
  2. Session
  3. REST API
  4. Coping with Tornado
  5. Nginx as reverse proxy

Model Layer(django.db)

basic use sample:

from django.db.models import Model

class Individual(models.Model): 
    GENDER = (                 
        ('M', 'male'),
        ('F', 'female'),
    )
    #id      = models.AutoField(primary_key=True)     #1
    name     = models.CharField(max_length=50)        #2
    age      = models.PositiveSmallIntegerField()
    species  = models.CharField(max_length=50) 
    gender   = models.CharField(max_length=1, choices=GENDER)
    company  = models.ForeignKey('Company', on_delete=models.CASCADE, null=True)
    friends  = models.ManyToManyField('self')         

    #objects = models.Manager()                       #3

    def __str__(self):
        return self.name

    class Meta:                                       #4
        ordering = ('age',)
        
class Company(models.Model): 
    pass
  1. This auto-incrementing key is auto added by Django,you can make your own field(primary_key=True), only one pk=True field for a whole Model.
  2. Filed coresponds to COLUMN of a TABLE in database. There're plenty filed types in Django. And there're many options for each kind of Field. Among those, vilidators is a good way to vilidate our input data.There's a special catagory field: relationship Field. ForeignKey, ManyToManyField, OneToOneField
  3. This is auto added by Django, Manager provides interfaces(by constructing QuerySet) for makeing queries, at least one Manager is provided for every unabstract model. You can change objects to other names your like with querying with the name your specified. MyModel.objects.all() => MyModel.yourname.all(). Also you can customize your own Manager(). You can define many custom Manager in one Model.
  4. Meta option.. abstract=True makes a model Abstract Model act as a parent class which can be herited. There're many Meta options in Django.

query

When model code is done. You can use Django provided command to deploy your database.

Making query is now what we are facing. Query involves three basic parts. When you have a database, how can you:

  1. Creating data objects and saving them to database

    Creating objects is simple, just like any python object's instantiation, and calling save() method to save it to database. You can also use Manager's API ->create to create and save an object in one time.[1]

  2. Saving changes to objects

    Saving changes to objects is just like updating an attribute of any python object, then save() method will update it to database.[2] You should pay attension to creating or updateing relationship fields: ForeignKey, ManyToManyField, OneToOneField

  3. Retrieving data objects from database.

    By constructing a QuerySet using a Manager() defined in a model. QuerySet provides all(), filter(), get(), exclude() methods to query data objects from database.[3]. QuerySet supports chaining filters, lazy evaluation, Python's array-slicing syntax. Keyword arguments of filter(), get(), exclude() are called "Filed Lookups". They have the form like:

    field__lookuptype=value.

    field is an attribute of a model object, __ has two underscores, lookuptype is provided by Django's built-in django.db.modles.Lookup class.

    For a Lookup to span a relationship, just use the filed name of the related fields across models, then two underscore, then the field name you want to query of the ralated model, you can even use lookup after queried field, like:

    Individual.objects.filter(company__name__iexact='Planet Express')

    There's a sepcial case for ForeignKey, you can use the ForeignKey Field name followed by _id=value to get the objects with Foreign Modle with pk=value. Like:

    Individual.objects.filter(company_id=1)

    And for the related model of ForeignKey field, the object of the model has a relating_name_set, attribute, like:

    express = Company.objects.get(pk=1); express.individual_set.all() will output all individual objects whose company is express.

    More about all/get/filter/exclude

    1. All. I think all is the leatest useful one among the four methods. It simply retrive all objects of a table. No other use. Althoug QuerySet supports chaining, but something like below is really unnecessary.

      Individual.objects.all().filter(friends__name__exact="Fry")

      You should just omit all(), changing it to:

      Individula.objects.filter(friends__name__exact="Fry")

    2. Get. Remember that get directly return a single object according to your query. If your query gets more than one objects satifying it, get will raise a MultipleObjectsReturnedexception. So use it when you're sure that only one object will meet your query condition. Like below, we know that this will return the only one objects due to unique=True is used when defining the Individual's name field.

      Individula.objects.get(name__exact="Fry")

    3. Filter. Filter will always return a QuerySet, even if only a single object matches the query, it will be a QuerySet containing a single element. Each time you refine a QuerySet, you get a brand-new Query that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused.

      human = Species.objects.get(name='human')

      q1 = Individual.objects.filter(species=human)

      Above will return a QuerySet containing Individuals' with species equal to "human", q1 is reuseable, let's reuse it to find out whose name is "Fry" under species equal to human

      q1.get(name="Fry")

      Above will return a single object who is fry.

    4. Exclude. Exclude is the oppsite of filter. It will return a QuerySet which doesn't match the query condition.

###create objects

  1. ordinary objects with no relation field is easily created. Just like ordinary creatation of python objects. instance = Class(args=xxxx)

  2. ForeignField

    You must save an object before it can be assigned to a foreign key relationship. Let's say that an employee and a company is ManyToOne relationship(a company could have lots of employees, but a employee should work for only one company). In this case:

    acompany = Company(name="PlanetExpress", description="deliver things")

    fry = Employee(name="Fry", age=35, company=acompany)

    Above will raise a error when assign acompany to fry's company, you have to save acompany first before use it.

  3. ManyToManyField

    You have to save an objects before associating it with manytomany relationship. Let's say that fry and leela are friends,

    class Individual(modles.Model): 
        ...
        name = models.CharField(max_length=50)
        friends = models.ManyToManyField('self')
        ...
    
    fry = Individual(name="Fry")
    leela = Individual(name="Leela")
    #you have to save it first
    fry.save()
    leela.save()
    fry.friends.add(leela)
    leela.friends.add(fry)

###shut up and show me the example

  1. migrate

    From command line, use the following command to migrate:

    python learndjango.py makemigrations learnmodel

    python learndjango.py migrate

    This will generate the db.sqlite3 database file.

  2. create TABLES

    From command line, input:

    python learndjango.py shell

    in the python prompt, enter:

    >>from learnmodel import create

    >>create.create()

    This will save INSERTs into the TABLEs. And we got the following recoreds:

    Company TABLE

id name description created modified
1 PlanetExpress deliver company a datatime object a datatime object

Species TABLE

id name characteristic created modified
1 Human a human a dt ob a dt ob
2 Mutant they live in the sewage a dt ob a dt ob
3 Robot there are many different kinds of robots with different function a dt ob a dt ob
4 Reptile they are reptile live in the swamp a dt ob a dt ob
5 Crab crab, this is for Zoidberg a dt ob a dt ob

Individual TABLE

id name age species gender company friends created modified
1 Fry 35 Human MALE PlanetExpress leela, bender, amy, hermes a dt ob a dt ob
2 Leela 35 Mutant FAMALE PlanetExpress fry, bender, amy, hermes a dt ob a dt ob
3 Bender 17 Robot MALE PlanetExpress fry, leela a dt ob a dt ob
4 Zoidberg 86 Crab MALE PlanetExpress NULL a dt ob a dt ob
5 Amy Wong 37 Human FAMALE PlanetExpress leela a dt ob a dt ob
6 Hubert J. Farnsworth 210 Human MALE PlanetExpress hermes a dt ob a dt ob
7 Hermes 54 Human MALE PlanetExpress hubert a dt ob a dt ob
Now From command line, input:

python learndjango.py shell

in the python prompt, enter:

>>from learnmodel import query

>>query.test()

This will print some query quiz on the screen, input your anwser then hit Enter to make a check. Answers are contained in the query.py file

###Uncovered topics

Django.db also has lots of other features, like F, Q objects, raw SQL excutions. Keep in mind that offical document always has the treature.

View Layer(class based views in django.views and function based views)

From offical document:

When a page is requested, Django creates an HttpRequest object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest as the first argument to the view function. Each view is responsible for returning an HttpResponse object.

This is offical document descripting how Django process a request

URL dispatcher

When a request coming from client, how does django decide which view is used to generate response? Of course this is based on the comming url, but to know about how does django do the mapping bewteen url and view, we have to understand django's url dispatcher mechanism.

basic use sample:

ROOT_URLCONF file

from django.conf.urls import include, url

urlpatterns = [
    url(r'^learnview/', include('learnview.urls', namespace="learnview"),)
]

urls.py file under learnview

from django.conf.urls import url
from . import views

app_name = "learnview"
urlpatterns = [
    url(r'^$', views.index, name="index"),
    url(r'^all/$', views.allrecord, name="allrecord"),
    url(r'individual/(?P<pk>\d+)$', views.individual, name="individual"),
]

the way it worked out

Django will look for the file you defined as ROOT_URLCONF in django.conf.settings.configer() method, then make it the entry file for identifying urls. It uses regular expression to match url string. Named captured patten as keyword argument to view function, if named group is not used, captured pattern will be used as positional argument to view function. namespace:name could be used as tag for a url stratege. This is very usefull when reverse url. You can also pass extra argument to view function using a {foo: bar} as a parameter to url. Well I think this is pretty much for url now.

function based view

A function based view is responsible for returning a HttpResponse object contained in django.http. Besides that, you can do any thing you want in a view function, but you'd better not define some time consuming operations, no body wants to keep waiting for a response long time. You can use Redis Queue/Celery/django-background-task or other task queue library to put time consuming part input asynchronous task queues.

In the example code, I defined three function view to deal with three url strategy.

index deal with url /learnview/, the simplest way to response, just pass string to HttpResponse then return it.

def index(request):
    "view function is responsible for returning a HttpResponse object"
    return HttpResponse("welcome to learn Django by example's learnview page")

individual function take keyword argument pk from named group caputred from url, then use shortcuts get_object_or_404 to retrive instance with that pk from Individual TABLE, and use as_dict() defined in the parent model class method to convert a model instance to a dict, then incrementaly write key:value pair to response, finally return response.

url(r'individual/(?P<pk>\d+)$', views.individual, name="individual")
def individual(request, pk):
    "demonstrate use of shortcut get_object_or_404"
    indi = get_object_or_404(Individual, pk=pk)
    dict = indi.as_dict()
    response = HttpResponse()
    for k,v in dict.iteritems():
	if v.__class__.__name__ == 'QuerySet':
	    vlist =[]
	    for i in v:
		vlist.append(str(i))
	    response.write('<p>'+k+': '+', '.join(vlist)+'</p>')
	    continue
	response.write('<p>'+k+': '+str(v)+'</p>')
    return response

class based view

First glancing at class based view feels like magic. The simplest generic class based view look like this:

view.py file:

from django.views.generic import ListView
from MymodelsModule import Mymodel

class MymodelList(ListView):
    model = Mymodel

urls.py file:

from django.conf.urls import url
from myApp.view import MymodelList

urlpatterns = [
    url(r'^mymodellist/$', MymodelList.as_view())
]

myApp/mymodel_list.html file

{% block content %}
    <h2>Mymodel</h2>
    <ul>
        {% for model in object_list %}
            <li>{{ model.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}

That's all you need. Django will do the magic behind. Now let's reveal the mystery by this chuck of Django offical document.

Keep in mind the following:

  1. self.args and self.kwargs:

    self.args contains the positional arguments captured in url, self.kwargs contains key word arguments caputre by url named group

  2. queryset

    queryset attribut is a QuerySet object in Django, this defines the QuerySet the view will use for retrive object from database. model=ModelName is equal to queryset = ModelName.objects.all(), it's just a shortcut.

  3. get_queryset()

    returns the queryset above.

  4. get_context_data()

    get data from the objects retrived by queryset to context.

  5. self.object and get_object()

    self.object is the object retrived by queryset, get_object() defines the detail of retriving a object from database.

Most time, we will used the above five attributs or method to custom our own class based view.

Mixin and advantage of class based views

There is debates on function based views and class based views. function based is easy to understand, but some kinda lack of ability to reues. While we can use class based views like most object-oriented language, we can use Mixin, Mixin is a class which supply some method, but doesn't mean to substansiate itself. We can just let our view inherit the Mixin and a view class.Pay attension to MRO, typically the following way:

  1. the base view classes provided by Django go to the right.

  2. Mixins go to the left of the base view.

  3. Mixins should inherit frmo Python's built-in object type.

There's a third-party library called django-brace supplies lots of useful Mixins.

Tom Christie is not satified with Django's complex inheriting ralations of class based view. So he made his own simple class-bases views in django-vanilla-views

Uncoverd topices

FormView, CreateView, UpdateView, DeleteView, Generic date views.

Form

Django form is very intuitive. Every field corespondes to a input tag in html with a default widget which you can assign manully. Surly there are some keyword arguments for customing field in form.

There are three aspects when dealing with form in Django.

  1. prepare and constructing data for rendering in html

    This is done by define your Form class, and initialize a form object with no arguments or some initial data

  2. form presentation in html AKA. Django template language for presenting form

    there are some useful template tag for presenting form in template. {{ form.as_table }} {{ form.as_p }} {{ form.as_ul }} and others. Remeber that form is iterable, so you can use {% for field in form %} to loop through a form

  3. receiving and processing submitted forms and data from clients

    Data sent from client is contained in request.POST if your form method is POST, then use myform = MyFormClass(request.POST) to make a form instance, use myform.is_valid() to check its validation, retrive data using form.cleaned_data dict. Field name is its key name.

learn_django_by_example's People

Contributors

pandafeeder avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.