本文内容包括:
Django ORM操作进阶
用户认证
常用ORM操作
from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __str__(self): # __unicode__ on Python 2 return self.name class Author(models.Model): name = models.CharField(max_length=50) email = models.EmailField() def __str__(self): # __unicode__ on Python 2 return self.name class Entry(models.Model): blog = models.ForeignKey(Blog) headline = models.CharField(max_length=255) body_text = models.TextField() pub_date = models.DateField() mod_date = models.DateField() authors = models.ManyToManyField(Author) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __str__(self): # __unicode__ on Python 2 return self.headline 示例models
创建
1
2
3
|
>>> from blog.models import Blog >>> b = Blog(name = 'Beatles Blog' , tagline = 'All the latest Beatles news.' ) >>> b.save() |
This performs an INSERT
SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save()
.
The save()
method has no return value.
处理带外键关联或多对多关联的对象
ForeignKey的关联
1
2
3
4
5
|
>>> from blog.models import Entry >>> entry = Entry.objects.get(pk = 1 ) >>> cheese_blog = Blog.objects.get(name = "Cheddar Talk" ) >>> entry.blog = cheese_blog >>> entry.save() |
ManyToManyField关联
1
2
3
|
>>> from blog.models import Author >>> joe = Author.objects.create(name = "Joe" ) >>> entry.authors.add(joe) |
添加多个ManyToMany对象
>>> john = Author.objects.create(name="John") >>> paul = Author.objects.create(name="Paul") >>> george = Author.objects.create(name="George") >>> ringo = Author.objects.create(name="Ringo") >>> entry.authors.add(john, paul, george, ringo)
查询
all_entries = Entry.objects.all() #查询所有 Entry.objects.filter(pub_date__year=2006) #查询所有pub_date为2006年的纪录 Entry.objects.all().filter(pub_date__year=2006) #与上面那句一样 >>> Entry.objects.filter( #链式查询 ... headline__startswith='What' ... ).exclude( ... pub_date__gte=datetime.date.today() ... ).filter( ... pub_date__gte=datetime(2005, 1, 30) ... ) one_entry = Entry.objects.get(pk=1) #单条查询 Entry.objects.all()[:5] #查询前5条 Entry.objects.all()[5:10] #你猜 Entry.objects.order_by('headline')[0] #按headline排序取第一条 Entry.objects.filter(pub_date__lte='2006-01-01') #相当于sql语句SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; Entry.objects.get(headline__exact="Cat bites dog") #相当于SELECT ... WHERE headline = 'Cat bites dog'; Blog.objects.get(name__iexact="beatles blog") #与上面相同,只是大小写不敏感 Entry.objects.get(headline__contains='Lennon') #相当 于SELECT ... WHERE headline LIKE '%Lennon%';
#This example retrieves all Entry objects with a Blog whose name is 'Beatles Blog': Entry.objects.filter(blog__name='Beatles Blog') Blog.objects.filter(entry__headline__contains='Lennon')
对同一表内不同的字段进行对比查询,In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?
Django provides F
expressions
to allow such comparisons. Instances of F()
act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.
For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F()
object to reference the pingback count, and use that F()
object in the query:
1
2
|
>>> from django.db.models import F >>> Entry.objects. filter (n_comments__gt = F( 'n_pingbacks' )) |
Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F()
objects, both with constants and with other F()
objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:
1
|
>>> Entry.objects. filter (n_comments__gt = F( 'n_pingbacks' ) * 2 ) |
To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:
1
|
>>> Entry.objects. filter (rating__lt = F( 'n_comments' ) + F( 'n_pingbacks' )) |
For date and date/time fields, you can add or subtract a timedelta
object. The following would return all entries that were modified more than 3 days after they were published:
1 >>> from datetime import timedelta 2 >>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
Caching and QuerySet
Each QuerySet
contains a cache to minimize database access. Understanding how it works will allow you to write the most efficient code.
In a newly created QuerySet
, the cache is empty. The first time a QuerySet
is evaluated – and, hence, a database query happens – Django saves the query results in the QuerySet
’s cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet
is being iterated over). Subsequent evaluations of the QuerySet
reuse the cached results.
Keep this caching behavior in mind, because it may bite you if you don’t use your QuerySet
s correctly. For example, the following will create two Quer
y
Set
s, evaluate them, and throw them away:
1
2
|
>>> print ([e.headline for e in Entry.objects. all ()]) >>> print ([e.pub_date for e in Entry.objects. all ()]) |
That means the same database query will be executed twice, effectively doubling your database load. Also, there’s a possibility the two lists may not include the same database records, because an Entry
may have been added or deleted in the split second between the two requests.
To avoid this problem, simply save the QuerySet
and reuse it:
1
2
3
|
>>> queryset = Entry.objects. all () >>> print ([p.headline for p in queryset]) # Evaluate the query set. >>> print ([p.pub_date for p in queryset]) # Re-use the cache from the evaluation. |
When QuerySet
s are not cached
Querysets do not always cache their results. When evaluating only part of the queryset, the cache is checked, but if it is not populated then the items returned by the subsequent query are not cached. Specifically, this means that limiting the querysetusing an array slice or an index will not populate the cache.
For example, repeatedly getting a certain index in a queryset object will query the database each time:
1
2
3
|
>>> queryset = Entry.objects. all () >>> print queryset[ 5 ] # Queries the database >>> print queryset[ 5 ] # Queries the database again |
However, if the entire queryset has already been evaluated, the cache will be checked instead:
1 >>> queryset = Entry.objects.all() 2 >>> [entry for entry in queryset] # Queries the database 3 >>> print queryset[5] # Uses cache 4 >>> print queryset[5] # Uses cache
Complex lookups with Q
objects(复杂查询)
Keyword argument queries – in filter()
, etc. – are “AND”ed together. If you need to execute more complex queries (for example, queries with OR
statements), you can use Q objects
.
A Q object
(django.db.models.Q
) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.
For example, this Q
object encapsulates a single LIKE
query:
1
2
|
from django.db.models import Q Q(question__startswith = 'What' ) |
Q
objects can be combined using the &
and |
operators. When an operator is used on two Q
objects, it yields a new Q
object.
For example, this statement yields a single Q
object that represents the “OR” of two "question__startswith"
queries:
1
|
Q(question__startswith = 'Who' ) | Q(question__startswith = 'What' ) |
This is equivalent to the following SQL WHERE
clause:
1
|
WHERE question LIKE 'Who%' OR question LIKE 'What%' |
You can compose statements of arbitrary complexity by combining Q
objects with the &
and |
operators and use parenthetical grouping. Also, Q
objects can be negated using the ~
operator, allowing for combined lookups that combine both a normal query and a negated (NOT
) query:
1
|
Q(question__startswith = 'Who' ) | ~Q(pub_date__year = 2005 ) |
Each lookup function that takes keyword-arguments (e.g. filter()
, exclude()
, get()
) can also be passed one or more Q
objects as positional (not-named) arguments. If you provide multiple Q
object arguments to a lookup function, the arguments will be “AND”ed together. For example:
1
2
3
4
|
Poll.objects.get( Q(question__startswith = 'Who' ), Q(pub_date = date( 2005 , 5 , 2 )) | Q(pub_date = date( 2005 , 5 , 6 )) ) |
... roughly translates into the SQL:
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
Lookup functions can mix the use of Q
objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q
objects) are “AND”ed together. However, if a Q
object is provided, it must precede the definition of any keyword arguments. For example:
1
2
3
|
Poll.objects.get( Q(pub_date = date( 2005 , 5 , 2 )) | Q(pub_date = date( 2005 , 5 , 6 )), question__startswith = 'Who' ) |
... would be a valid query, equivalent to the previous example; but:
1
2
3
4
|
# INVALID QUERY Poll.objects.get( question__startswith = 'Who' , Q(pub_date = date( 2005 , 5 , 2 )) | Q(pub_date = date( 2005 , 5 , 6 ))) |
... would not be valid.
更新
Updating multiple objects at once
1
2
|
# Update all the headlines with pub_date in 2007. Entry.objects. filter (pub_date__year = 2007 ).update(headline = 'Everything is the same' ) |
在原有数据的基础上批量自增
Calls to update can also use F
expressions
to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:
1
|
>>> Entry.objects. all ().update(n_pingbacks = F( 'n_pingbacks' ) + 1 ) |
However, unlike F()
objects in filter and exclude clauses, you can’t introduce joins when you use F()
objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F()
object, a FieldError
will be raised:
1
2
|
# THIS WILL RAISE A FieldError >>> Entry.objects.update(headline = F( 'blog__name' )) |
Aggregation(聚合)
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) age = models.IntegerField() class Publisher(models.Model): name = models.CharField(max_length=300) num_awards = models.IntegerField() class Book(models.Model): name = models.CharField(max_length=300) pages = models.IntegerField() price = models.DecimalField(max_digits=10, decimal_places=2) rating = models.FloatField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) pubdate = models.DateField() class Store(models.Model): name = models.CharField(max_length=300) books = models.ManyToManyField(Book) registered_users = models.PositiveIntegerField()
# Total number of books. >>> Book.objects.count() # Total number of books with publisher=BaloneyPress >>> Book.objects.filter(publisher__name='BaloneyPress').count() # Average price across all books. >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} # Max price across all books. >>> from django.db.models import Max >>> Book.objects.all().aggregate(Max('price')) {'price__max': Decimal('81.20')} # Cost per page >>> Book.objects.all().aggregate( ... price_per_page=Sum(F('price')/F('pages'), output_field=FloatField())) {'price_per_page': 0.4470664529184653} # All the following queries involve traversing the Book<->Publisher # foreign key relationship backwards. # Each publisher, each with a count of books as a "num_books" attribute. >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs [<Publisher BaloneyPress>, <Publisher SalamiPress>, ...] >>> pubs[0].num_books # The top 5 publishers, in order by number of books. >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5] >>> pubs[0].num_books
更多聚合查询例子:https://docs.djangoproject.com/en/1.9/topics/db/aggregation/
用户认证
1
2
3
4
5
6
7
8
9
10
11
|
from django.contrib.auth import authenticate user = authenticate(username = 'john' , password = 'secret' ) if user is not None : # the password verified for the user if user.is_active: print ( "User is valid, active and authenticated" ) else : print ( "The password is valid, but the account has been disabled!" ) else : # the authentication system was unable to verify the username and password print ( "The username and password were incorrect." ) |
How to log a user out
1 from django.contrib.auth import logout 2 3 def logout_view(request): 4 logout(request) 5 # Redirect to a success page.
来源:https://www.cnblogs.com/now-playing/p/8328841.html