Random string - random username from  django .utils .crypto  import  get_random_string 
User .objects .create_user (username = get_random_string (), email = '' , password = '123' )$ mkdir api &  cd  api
$ pipenv install django djangorestframework django-cors-headers django-filter django-extensions
$ django-admin startproject api .  &  python manage.py startapp core # in settings.py 
ALLOWED_HOSTS  =  ['*' ]
# in INSTALLED_APPS 
'django_extensions' ,
'rest_framework' ,
'django_filters' ,
'corsheaders' ,
'core.apps.CoreConfig' ,
# IN MIDDLEWARE SECTION 
'corsheaders.middleware.CorsMiddleware' ,
# CORS CONFIG 
CORS_ORIGIN_ALLOW_ALL  =  True 
# FILTER AND PAGINATION SECTION 
REST_FRAMEWORK  =  {
    'DEFAULT_PAGINATION_CLASS' : 'rest_framework.pagination.PageNumberPagination' ,
    'PAGE_SIZE' : 24 ,
     'DEFAULT_FILTER_BACKENDS' : (
         'django_filters.rest_framework.DjangoFilterBackend' ,
    ),
}
# models.py 
class  Product (models .Model ):
    name  =  models .CharField (max_length = 200 , db_index = True )
    price  =  models .DecimalField (max_digits = 10 , decimal_places = 2 )
# serializers.py 
from  rest_framework  import  serializers 
from  search  import  models 
class  ProductSerializer (serializers .ModelSerializer ):
    class  Meta :
        fields  =  (
            'id' ,
            'name' ,
            'price' ,
        )
        model  =  models .Product 
# filters.py 
import  django_filters 
from  search  import  models 
class  ProductFilter (django_filters .FilterSet ):
      near_to =  filters .CharFilter (method = 'get_nearest' )
      
      class  Meta :
          model  =  models .Product 
          fields  =  {
               'name' : ['exact' , 'icontains' ],
               'price' : ['exact' , 'lte' , 'gte' , 'range' ],
          }
      
      def  get_nearest (self , queryset , name , value ):
          return  queryset .filter (location__distance_lte = (user_location , D (km = 7 )))
# views.py 
from  rest_framework  import  viewsets 
from  search  import  models 
from  search  import  serializers 
from  search  import  filters 
# Create your views here. 
class  ProductViewSet (viewsets .ModelViewSet ):
    queryset  =  models .Product .objects .all ()
    serializer_class  =  serializers .ProductSerializer 
    filterset_class  =  filters .ProductFilter 
    ordering_fields  =  ['username' , 'email' ] # ?ordering=-username # ?ordering=account,username 
 
# core/urls 
from  django .urls  import  path 
from  search  import  views 
from  rest_framework .routers  import  DefaultRouter 
router  =  DefaultRouter ()
router .register ('products' , views .ProductViewSet )
urlpatterns  =  router .urls 
# api/urls 
from  django .contrib  import  admin 
from  django .urls  import  path , include 
urlpatterns  =  [
    path ('admin/' , admin .site .urls ),
    path ('api/v1/' , include ('search.urls' ))
]from  rest_framework .permissions  import  BasePermission ,SAFE_METHODS 
class  IsOwnerProfileOrReadOnly (BasePermission ):
    def  has_object_permission (self , request , view , obj ):
        if  request .method  in  SAFE_METHODS :
            return  True 
        return  obj .user == request .user 
from  rest_framework  import  viewsets , permissions 
class  ItemViewSet (viewsets .ModelViewSet ):
    
    permission_classes  =  [permissions .IsAuthenticatedOrReadOnly , IsOwnerProfileOrReadOnly  ]# pipenv install djangorestframework-simplejwt 
# settings.py 
REST_FRAMEWORK  =  {
    # ... 
    'DEFAULT_AUTHENTICATION_CLASSES' : (
        'rest_framework_simplejwt.authentication.JWTAuthentication' ,
    )
}
CORS_ORIGIN_ALLOW_ALL  =  True 
from  datetime  import  timedelta 
SIMPLE_JWT  =  {
    'ACCESS_TOKEN_LIFETIME' : timedelta (minutes = 50 ),
    'REFRESH_TOKEN_LIFETIME' : timedelta (days = 1 ),
}
AUTH_USER_MODEL  =  'account.User' 
AUTHENTICATION_BACKENDS  =  (
  'account.custom_auth_backends.EmailAuthBackend' ,
  'django.contrib.auth.backends.ModelBackend' ,
)
# custom_auth_backends.py 
from  account  import  models 
from  django .contrib .auth .hashers  import  check_password 
class  EmailAuthBackend (object ):
    def  authenticate (self , request , username = None , password = None ):
        try :
      # Check if the user exists in Django's database 
            user  =  models .User .objects .get (email = username )
        except  models .User .DoesNotExist :
            return  None 
    # Check password of the user we found 
        if  check_password (password , user .password ):
            return  user 
        return  None 
    # Required for your backend to work properly - unchanged in most scenarios 
    def  get_user (self , user_id ):
        try :
            return  models .User .objects .get (pk = user_id )
        except  models .User .DoesNotExist :
            return  None 
#models.py 
from  django .db  import  models 
# Create your models here. 
from  django .db  import  models 
from  django .contrib .auth .models  import  AbstractUser 
class  User (AbstractUser ):
    USER_TYPE_CHOICES  =  (
          (1 , 'student' ),
          (2 , 'teacher' ),
          (3 , 'secretary' ),
          (4 , 'supervisor' ),
          (5 , 'admin' ),
      )
    user_type  =  models .PositiveSmallIntegerField (choices = USER_TYPE_CHOICES )
    email  =  models .EmailField (verbose_name = 'email address' , max_length = 255 , unique = True )
    phone  =  models .CharField (max_length = 30 )
    def  __str__ (self ):
        return  self .email 
        
# serializers.py 
from  account .models  import  User 
from  rest_framework  import  serializers 
from  django .contrib .auth  import  authenticate 
class  SignUpSerializer (serializers .ModelSerializer ):
    class  Meta :
        model  =  User 
        fields  =  ('id' , 'first_name' , 'last_name' , 'email' , 'password' ,)
        extra_kwargs  =  {'password' : {'write_only' : True }}
    def  create (self , validated_data ):
        user  =  User .objects .create_user (
                                        first_name =  validated_data ['first_name' ],
                                        last_name =  validated_data ['last_name' ],
                                        username = validated_data ['first_name' ],
                                        email = validated_data ['email' ],
                                        password = validated_data ['password' ])
        return  user 
class  SignInSerializer (serializers .Serializer ):
    email  =  serializers .CharField ()
    password  =  serializers .CharField ()
    def  validate (self , data ):
        user  =  authenticate (username = data ['email' ], password = data ['password' ])
        if  user  is  not None :
            return  user 
        raise  serializers .ValidationError ("Unable to log in with provided credentials." )
class  UserSerializer (serializers .ModelSerializer ):
    class  Meta :
        model  =  User 
        fields  =  ('id' , 'email' , 'first_name' , 'last_name' , 'username' )        
# views.py 
from  rest_framework  import  viewsets , permissions , generics 
from  rest_framework .response  import  Response 
from  rest_framework_simplejwt .tokens  import  RefreshToken 
from  rest_framework_simplejwt .serializers  import  TokenObtainPairSerializer 
from  account  import  serializers 
from  rest_framework  import  views , permissions , status 
from  rest_framework .response  import  Response 
from  account  import  models 
from  account  import  filters 
class  SignUpAPI (generics .GenericAPIView ):
    serializer_class  =  serializers .SignUpSerializer 
    def  post (self , request , * args , ** kwargs ):
        serializer  =  self .get_serializer (data = request .data )
        serializer .is_valid (raise_exception = True )
        user  =  serializer .save ()
        refresh  =  RefreshToken .for_user (user )
        return  Response ({
            'user' : serializers .UserSerializer (user , context = self .get_serializer_context ()).data ,
            'refresh' : str (refresh ),
            'access' : str (refresh .access_token ),
        })
class  SignInAPI (generics .GenericAPIView ):
    serializer_class  =  serializers .SignInSerializer 
    def  post (self , request , * args , ** kwargs ):
        serializer  =  self .get_serializer (data = request .data )
        serializer .is_valid (raise_exception = True )
        user  =  serializer .validated_data 
        refresh  =  RefreshToken .for_user (user )
        return  Response ({
            'user' : serializers .UserSerializer (user , context = self .get_serializer_context ()).data ,
            'refresh' : str (refresh ),
            'access' : str (refresh .access_token ),
        })
class  UserAPI (generics .RetrieveAPIView ):
    permission_classes  =  [permissions .IsAuthenticated , ]
    serializer_class  =  serializers .UserSerializer 
    def  get_object (self ):
        return  self .request .user 
class  UserViewSet (viewsets .ModelViewSet ):
    queryset  =  models .User .objects .all ()
    serializer_class  =  serializers .UserSerializer 
    filterset_class  =  filters .UserFilter 
# urls.py 
# ... 
urlpatterns = [
    path ('auth/users/me/' , views .UserAPI .as_view ()),
    path ('auth/sign-up/' , views .SignUpAPI .as_view ()),
    path ('auth/sign-in/' , views .SignInAPI .as_view ()),
    path ('auth/refresh-token/' , TokenRefreshView .as_view ()),
]
# ... 
create management/commands folder inside an app folder 
add this inside a fixture.py 
 
from  django .core .management .base  import  BaseCommand 
from  search  import  models 
from  random  import  randrange 
class  Command (BaseCommand ):
    help  =  "fake data generator" 
    def  handle (self , * args , ** options ):
        models .Product .objects .all ().delete ()
        for  i  in  range (400 ):
            models .Product .objects .create (
                name = "Product " +  str (i ),
                price = randrange (97562 ),
            )
        self .stdout .write (self .style .SUCCESS ("done!" ))Custom command with param from  django .core .management .base  import  BaseCommand 
class  Command (BaseCommand ):
    help  =  "fake data generator" 
    def  add_arguments (self , parser ):
        # Required argument 
        parser .add_argument ('total' , type = int , help = 'Indicates the number of item to be created' )
        # Optional argument 
        parser .add_argument ('-p' , '--price' , type = str , help = 'Define an item price' , )
        # Optional list argument 
        parser .add_argument ('-i' , '--items' , nargs = '+' , type = int , help = 'Item ID' )
    def  handle (self , * args , ** options ):
        total  =  options ['total' ]
        price  =  options ['price' ]
        items  =  options ['items' ]
        self .stdout .write (self .style .SUCCESS ('total "%s"'  %  total ))
        if  price :
            self .stdout .write (self .style .SUCCESS ('price "%s"'  %  price ))
        if  items :
            self .stdout .write (self .style .SUCCESS ('items "%s"'  %  items ))class  Place (models .Model ):
    name  =  models .CharField (max_length = 50 )
    address  =  models .CharField (max_length = 80 )
    def  __str__ (self ):
        return  "%s the place"  %  self .name 
class  Restaurant (models .Model ):
    place  =  models .OneToOneField (
        Place ,
        on_delete = models .CASCADE ,
        primary_key = True ,
    )
    serves_hot_dogs  =  models .BooleanField (default = False )
    serves_pizza  =  models .BooleanField (default = False )
    def  __str__ (self ):
        return  "%s the restaurant"  %  self .place .name 
class  Waiter (models .Model ):
    restaurant  =  models .ForeignKey (Restaurant , on_delete = models .CASCADE )
    name  =  models .CharField (max_length = 50 )
    def  __str__ (self ):
        return  "%s the waiter at %s"  %  (self .name , self .restaurant )class  Reporter (models .Model ):
    first_name  =  models .CharField (max_length = 30 )
    last_name  =  models .CharField (max_length = 30 )
    email  =  models .EmailField ()
    def  __str__ (self ):
        return  "%s %s"  %  (self .first_name , self .last_name )
class  Article (models .Model ):
    headline  =  models .CharField (max_length = 100 )
    pub_date  =  models .DateField ()
    reporter  =  models .ForeignKey (Reporter , on_delete = models .CASCADE )
    def  __str__ (self ):
        return  self .headline 
    class  Meta :
        ordering  =  ['headline' ]class  Publication (models .Model ):
    title  =  models .CharField (max_length = 30 )
    class  Meta :
        ordering  =  ['title' ]
    def  __str__ (self ):
        return  self .title 
class  Article (models .Model ):
    headline  =  models .CharField (max_length = 100 )
    publications  =  models .ManyToManyField (Publication )
    class  Meta :
        ordering  =  ['headline' ]
    def  __str__ (self ):
        return  self .headline class  Person (models .Model ):
    name  =  models .CharField (max_length = 128 )
    def  __str__ (self ):
        return  self .name 
class  Group (models .Model ):
    name  =  models .CharField (max_length = 128 )
    members  =  models .ManyToManyField (Person , through = 'Membership' )
    def  __str__ (self ):
        return  self .name 
class  Membership (models .Model ):
    person  =  models .ForeignKey (Person , on_delete = models .CASCADE )
    group  =  models .ForeignKey (Group , on_delete = models .CASCADE )
    date_joined  =  models .DateField ()
    invite_reason  =  models .CharField (max_length = 64 )class  Media (models .Model ):
    title  =  models .CharField (max_length = 255 )
    pub_date  =  models .DateTimeField ()
class  Photo (Media ): # note that Photo extends Media 
    image  =  models .ImageField (upload_to = 'photos' )
class  Video (Media ):
    video  =  models .FileField (upload_to = 'videos' )class  Invoice (models .Model ):
    SENT  =  1 
    PAID  =  2 
    VOID  =  3 
    STATUS_CHOICES  =  (
        (SENT , 'sent' ),
        (PAID , 'paid' ),
        (VOID , 'void' ),
    )
    user  =  models .ForeignKey (User , on_delete = models .CASCADE , related_name = 'invoices' )
    number  =  models .CharField (max_length = 30 )
    date  =  models .DateTimeField (auto_now_add = True )
    status  =  models .PositiveSmallIntegerField (choices = STATUS_CHOICES )
    amount  =  models .DecimalField (max_digits = 10 , decimal_places = 2 )class  User (AbstractUser ):
  USER_TYPE_CHOICES  =  (
      (1 , 'student' ),
      (2 , 'teacher' ),
      (3 , 'secretary' ),
      (4 , 'supervisor' ),
      (5 , 'admin' ),
  )
  user_type  =  models .PositiveSmallIntegerField (choices = USER_TYPE_CHOICES )Product | Ecommerce | Shop class  Product (models .Model ):
    category  =  models .ForeignKey (Category ,
                                 related_name = 'products' ,
                                 on_delete = models .CASCADE )
    name  =  models .CharField (max_length = 200 , db_index = True )
    slug  =  models .SlugField (max_length = 200 , db_index = True )
    image  =  models .ImageField (upload_to = 'products/%Y/%m/%d' ,
                              blank = True )
    description  =  models .TextField (blank = True )
    price  =  models .DecimalField (max_digits = 10 , decimal_places = 2 )
    available  =  models .BooleanField (default = True )
    created  =  models .DateTimeField (auto_now_add = True )
    updated  =  models .DateTimeField (auto_now = True )
    class  Meta :
        ordering  =  ('name' ,)
        index_together  =  (('id' , 'slug' ),)
    def  __str__ (self ):
        return  self .name 
    def  get_absolute_url (self ):
            return  reverse ('shop:product_detail' ,
                           args = [self .id , self .slug ])
                           
                           
class  Order (models .Model ):
    first_name  =  models .CharField (_ ('first name' ), max_length = 50 )
    last_name  =  models .CharField (_ ('last name' ), max_length = 50 )
    email  =  models .EmailField (_ ('e-mail' ))
    address  =  models .CharField (_ ('address' ), max_length = 250 )
    postal_code  =  models .CharField (_ ('postal code' ), max_length = 20 )
    city  =  models .CharField (_ ('city' ), max_length = 100 )
    created  =  models .DateTimeField (auto_now_add = True )
    updated  =  models .DateTimeField (auto_now = True )
    paid  =  models .BooleanField (default = False )
    braintree_id  =  models .CharField (max_length = 150 , blank = True )
    coupon  =  models .ForeignKey (Coupon ,
                               related_name = 'orders' ,
                               null = True ,
                               blank = True ,
                               on_delete = models .SET_NULL )
    discount  =  models .IntegerField (default = 0 ,
                                   validators = [MinValueValidator (0 ),
                                               MaxValueValidator (100 )])
    class  Meta :
        ordering  =  ('-created' ,)
    def  __str__ (self ):
        return  'Order {}' .format (self .id )
    def  get_total_cost (self ):
        total_cost  =  sum (item .get_cost () for  item  in  self .items .all ())
        return  total_cost  -  total_cost  *  (self .discount  /  Decimal ('100' ))
class  OrderItem (models .Model ):
    order  =  models .ForeignKey (Order ,
                              related_name = 'items' ,
                              on_delete = models .CASCADE )
    product  =  models .ForeignKey (Product ,
                                related_name = 'order_items' ,
                                on_delete = models .CASCADE )
    price  =  models .DecimalField (max_digits = 10 , decimal_places = 2 )
    quantity  =  models .PositiveIntegerField (default = 1 )
    def  __str__ (self ):
        return  '{}' .format (self .id )
    def  get_cost (self ):
        return  self .price  *  self .quantity                            
Post | Comment 
class  Post (models .Model ): 
    STATUS_CHOICES  =  ( 
        ('draft' , 'Draft' ), 
        ('published' , 'Published' ), 
    ) 
    title  =  models .CharField (max_length = 250 ) 
    slug  =  models .SlugField (max_length = 250 ,  
                            unique_for_date = 'publish' ) 
    author  =  models .ForeignKey (User , 
                               on_delete = models .CASCADE ,
                               related_name = 'blog_posts' ) 
    body  =  models .TextField () 
    publish  =  models .DateTimeField (default = timezone .now ) 
    created  =  models .DateTimeField (auto_now_add = True ) 
    updated  =  models .DateTimeField (auto_now = True ) 
    status  =  models .CharField (max_length = 10 ,  
                              choices = STATUS_CHOICES , 
                              default = 'draft' ) 
    
    objects  =  models .Manager () # The default manager.  
    published  =  PublishedManager () # Our custom manager. 
    tags  =  TaggableManager ()
    class  Meta : 
        ordering  =  ('-publish' ,) 
    def  __str__ (self ): 
        return  self .title 
    def  get_absolute_url (self ):
        return  reverse ('blog:post_detail' ,
                       args = [self .publish .year ,
                             self .publish .month ,
                             self .publish .day ,
                             self .slug ])
class  Comment (models .Model ): 
    post  =  models .ForeignKey (Post ,
                             on_delete = models .CASCADE ,
                             related_name = 'comments' )
    name  =  models .CharField (max_length = 80 ) 
    email  =  models .EmailField () 
    body  =  models .TextField () 
    created  =  models .DateTimeField (auto_now_add = True ) 
    updated  =  models .DateTimeField (auto_now = True ) 
    active  =  models .BooleanField (default = True ) 
 
    class  Meta : 
        ordering  =  ('created' ,) 
 
    def  __str__ (self ): 
        return  'Comment by {} on {}' .format (self .name , self .post )class  Subject (models .Model ):
    title  =  models .CharField (max_length = 200 )
    slug  =  models .SlugField (max_length = 200 , unique = True )
    class  Meta :
        ordering  =  ['title' ]
    def  __str__ (self ):
        return  self .title 
class  Course (models .Model ):
    owner  =  models .ForeignKey (User ,
                              related_name = 'courses_created' ,
                              on_delete = models .CASCADE )
    subject  =  models .ForeignKey (Subject ,
                                related_name = 'courses' ,
                                on_delete = models .CASCADE )
    title  =  models .CharField (max_length = 200 )
    slug  =  models .SlugField (max_length = 200 , unique = True )
    overview  =  models .TextField ()
    created  =  models .DateTimeField (auto_now_add = True )
    students  =  models .ManyToManyField (User ,
                                      related_name = 'courses_joined' ,
                                      blank = True )
    class  Meta :
        ordering  =  ['-created' ]
    def  __str__ (self ):
        return  self .title 
class  Module (models .Model ):
    course  =  models .ForeignKey (Course ,
                               related_name = 'modules' ,
                               on_delete = models .CASCADE )
    title  =  models .CharField (max_length = 200 )
    description  =  models .TextField (blank = True )
    order  =  OrderField (blank = True , for_fields = ['course' ])
    class  Meta :
            ordering  =  ['order' ]
    def  __str__ (self ):
        return  '{}. {}' .format (self .order , self .title )
class  Content (models .Model ):
    module  =  models .ForeignKey (Module ,
                               related_name = 'contents' ,
                               on_delete = models .CASCADE )
    content_type  =  models .ForeignKey (ContentType ,
                                     limit_choices_to = {'model__in' :('text' ,
                                                                    'video' ,
                                                                    'image' ,
                                                                    'file' )},
                                     on_delete = models .CASCADE )
    object_id  =  models .PositiveIntegerField ()
    item  =  GenericForeignKey ('content_type' , 'object_id' )
    order  =  OrderField (blank = True , for_fields = ['module' ])
    class  Meta :
            ordering  =  ['order' ]
class  ItemBase (models .Model ):
    owner  =  models .ForeignKey (User ,
                              related_name = '%(class)s_related' ,
                              on_delete = models .CASCADE )
    title  =  models .CharField (max_length = 250 )
    created  =  models .DateTimeField (auto_now_add = True )
    updated  =  models .DateTimeField (auto_now = True )
    class  Meta :
        abstract  =  True 
    def  __str__ (self ):
        return  self .title 
    def  render (self ):
        return  render_to_string ('courses/content/{}.html' .format (
            self ._meta .model_name ), {'item' : self })
class  Text (ItemBase ):
    content  =  models .TextField ()
class  File (ItemBase ):
    file  =  models .FileField (upload_to = 'files' )
class  Image (ItemBase ):
       file  =  models .FileField (upload_to = 'images' )
class  Video (ItemBase ):
    url  =  models .URLField ()from  django .db  import  models 
from  django .utils .text  import  slugify 
# Create your models here. 
class  Reservation (models .Model ):
    name  =  models .CharField (max_length = 50 )
    email  =  models .EmailField ()
    phone  =  models .IntegerField ()
    number_of_persons  =  models .IntegerField ()
    Date  =  models .DateField ()
    time  =  models .TimeField ()
    def  __str__ (self ):
        return  self .name 
        
        
class  Meals (models .Model ):
    name  =  models .CharField (max_length = 50 )
    description  =  models .TextField (max_length = 500 )
    category  =  models .ForeignKey ('Category'  , on_delete = models .SET_NULL  , null = True )
    people  =  models .IntegerField ()
    price  =  models .DecimalField (max_digits = 5  , decimal_places = 2 )
    preperation_time  = models .IntegerField ()
    image  =  models .ImageField (upload_to = 'meals/' )
    slug  =  models .SlugField (blank = True , null = True )
    def  save (self  , * args  , ** kwargs ):
        if  not  self .slug  and  self .name  :
            self .slug  =  slugify (self .name )
        super (Meals  , self ).save (* args  , ** kwargs )
    class  Meta :
        verbose_name  =  'meal' 
        verbose_name_plural  =  'meals' 
    def  __str__ (self ):
        return  self .name 
class  Category (models .Model ):
    name  =  models .CharField (max_length = 30 )
    class  Meta :
        verbose_name  =  'category' 
        verbose_name_plural  =  'categories' 
    def  __str__ (self ):
        return  self .name # signals.py 
from  core .models  import  Author , Tag , Post 
from  django .db .models .signals  import  post_save , m2m_changed 
from  django .dispatch  import  receiver 
@receiver (post_save , sender = Author ) 
def  author_changed (sender , instance , ** kwargs ):
    for  post  in  instance .posts .with_documents ():
        post .search_vector  =  post .document 
        post .save (update_fields = ['search_vector' ])
@receiver (m2m_changed , sender = Post .tags .through ) 
def  post_tags_changed (sender , instance , action , ** kwargs ):
    if  action  in  ('post_add' , 'post_remove' , 'post_clear' ):
        instance .save ()
        
# apps.py 
from  django .apps  import  AppConfig 
class  CoreConfig (AppConfig ):
    name  =  'core' 
    def  ready (self ):
        import  core .signals   Custom serializers for viewsets # mixins.py 
class  ReadWriteSerializerMixin (object ):
    """ 
    Overrides get_serializer_class to choose the read serializer 
    for GET requests and the write serializer for POST requests. 
    Set read_serializer_class and write_serializer_class attributes on a 
    viewset.  
    """ 
    read_serializer_class  =  None 
    write_serializer_class  =  None 
    def  get_serializer_class (self ):        
        if  self .action  in  ["create" , "update" , "partial_update" , "destroy" ]:
            return  self .get_write_serializer_class ()
        return  self .get_read_serializer_class ()
    def  get_read_serializer_class (self ):
        assert  self .read_serializer_class  is  not None , (
            "'%s' should either include a `read_serializer_class` attribute," 
            "or override the `get_read_serializer_class()` method." 
            %  self .__class__ .__name__ 
        )
        return  self .read_serializer_class 
    def  get_write_serializer_class (self ):
        assert  self .write_serializer_class  is  not None , (
            "'%s' should either include a `write_serializer_class` attribute," 
            "or override the `get_write_serializer_class()` method." 
            %  self .__class__ .__name__ 
        )
        return  self .write_serializer_class 
        
# views.py 
from  .mixins  import  ReadWriteSerializerMixin 
from  .models  import  MyModel 
from  .serializers  import  ModelReadSerializer , ModelWriteSerializer 
class  MyModelViewSet (ReadWriteSerializerMixin , viewsets .ModelViewSet ):
    queryset  =  MyModel .objects .all () 
    read_serializer_class  =  ModelReadSerializer  
    write_serializer_class  =  ModelWriteSerializer $ docker-compose run -rm web ./manage.py [command] [arguments]
$ docker-compose run -rm web ./manage.py test [app]
# pipenv install celery redis 
# settings.py 
CELERY_BROKER_URL  =  'redis://redis:6379' 
CELERY_RESULT_BACKEND  =  'redis://redis:6379' 
CELERY_ACCEPT_CONTENT  =  ['application/json' ]
CELERY_TASK_SERIALIZER  =  'json' 
CELERY_RESULT_SERIALIZER  =  'json' 
# proj/celery.py 
import  os 
from  celery  import  Celery 
os .environ .setdefault ('DJANGO_SETTINGS_MODULE' , 'proj.settings' )
app  =  Celery ('proj' )
app .config_from_object ('django.conf:settings' , namespace = 'CELERY' )
app .autodiscover_tasks ()
@app .task (bind = True ) 
def  debug_task (self ):
    print ('Request: {0!r}' .format (self .request ))
# app/tasks.py 
from  celery  import  shared_task 
@shared_task  
def  hello ():
    print ('Hello there!' )
@app .task  
def  test (arg = None ):
    print (arg )
# proj/__init__.py 
from  .celery  import  app  as  celery_app 
__all__  =  ['celery_app' ]
# demo 
from  app .tasks  import  hello 
hello .delay ()
# crontab 
# settings.py 
from  celery .schedules  import  crontab 
CELERY_BEAT_SCHEDULE  =  {
    'hello' : {
        'task' : 'app.tasks.test' ,
        'schedule' : crontab (hour = 7 , minute = 30 , day_of_week = 1 )  # Executes every Monday morning at 7:30 a.m, 
        #'args': ('hello') 
        
    }
}
# more info 
# https://www.revsys.com/tidbits/celery-and-django-and-docker-oh-my/ # dockerfile.ymlservices :
  db :
    image : postgres:9.6.5 
    volumes :
      - postgres_data:/var/lib/postgresql/data/ 
  redis :
    image : " redis:alpine" web :
    build : . 
    command : bash -c "python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" 
    volumes :
      - .:/code 
    ports :
      - " 8000:8000" depends_on :
      - db 
      - redis 
  celery :
    build : . 
    command : celery -A proj worker -l info 
    volumes :
      - .:/code 
    depends_on :
      - db 
      - redis 
  celery-beat :
    build : . 
    command : celery -A proj beat -l info 
    volumes :
      - .:/code 
    depends_on :
      - db 
      - redis 
volumes :
  postgres_data :# Dockerfile
# Pull base image
FROM python:3.8
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Set work directory
WORKDIR /code
# Install dependencies
RUN pip install pipenv
COPY Pipfile Pipfile.lock /code/
RUN pipenv install --system
RUN apt-get update -y
RUN apt-get -y install apt-utils binutils libproj-dev gdal-bin
# Copy project
COPY . /code/
version: '3.7'
services:
  
  db:
    image: kartoza/postgis:12.0
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment: 
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASS=${POSTGRES_PASS}
      - POSTGRES_MULTIPLE_EXTENSIONS=postgis,hstore,postgis_topology,pg_trgm,unaccent
    ports:
      - 5432:5432
    restart: always
  
    
  web:
    build: .
    command: bash -c "while !</dev/tcp/db/5432; do sleep 1; done; python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000 && pytest" 
    volumes:
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db
     
volumes:
  postgres_data:
#.... 
DATABASES  =  {
    'default' : {
        'ENGINE' : 'django.contrib.gis.db.backends.postgis' ,
        'NAME' : 'postgres' ,
        'USER' : 'postgres' ,
        'PASSWORD' :'postgres' ,
        'HOST' : 'db' , # set in docker-compose.yml 
        'PORT' : 5432 , # default postgres port 
        'CONN_MAX_AGE' : 1000 ,  # pooling 
    }
}$ docker-compose run --rm web python /code/manage.py createsuperuser # settings.py 
MEDIA_URL  =  '/media/' 
#MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 
MEDIA_ROOT  =  '/media' 
STATIC_URL  =  "/static/" 
STATIC_ROOT = "/static/" 
# urls.py -> demo 
from  django .conf  import  settings 
from  django .conf .urls .static  import  static  # new 
if  settings .DEBUG : # new 
    urlpatterns  +=  static (settings .MEDIA_URL , document_root = settings .MEDIA_ROOT )
    
# models.py 
class  File (models .Model ):
    image  =  models .ImageField (upload_to = 'images/' )
# serializers.py 
class  FileSerializer (serializers .ModelSerializer ):
    class  Meta :
        fields  =  (
            'id' ,
            'image' 
        )
        model  =  models .File 
 
 # views.py 
 class  FileViewSet (viewsets .ModelViewSet ):
    queryset  =  models .File .objects .all ()
    serializer_class  =  serializers .FileSerializer 
    
    
# urls.py 
# ... 
 router .register ('files' , views .FileViewSet )# Dockerfile
# Pull base image
FROM python:3.8
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV POSTGRES_USER postgres
ENV POSTGRES_PASS postgres
ENV BIZAO_CLIENT_ID ugyrNwqHv6bX9CB1K8tjmqtvDIYa
ENV BIZAO_CLIENT_SECRET OSQ47FxbhsWrWNfz3FP2ITWLmVsa
ENV BIZAO_TOKEN dWd5ck53cUh2NmJYOUNCMUs4dGptcXR2RElZYTpPU1E0N0Z4YmhzV3JXTmZ6M0ZQMklUV0xtVnNh
# Set work directory
WORKDIR /code
# Install dependencies
RUN pip install pipenv
COPY Pipfile Pipfile.lock /code/
RUN pipenv install --system
RUN apt-get update -y
RUN apt-get -y install apt-utils binutils libproj-dev gdal-bin
# Copy project
COPY . /code/
version : ' 3.7' services :
  
  db :
    image : kartoza/postgis:12.0 
    volumes :
      - adafri_postgres:/var/lib/postgresql/data/ 
    environment : 
      - POSTGRES_USER=${POSTGRES_USER} 
      - POSTGRES_PASS=${POSTGRES_PASS} 
    ports :
      - 5432:5432 
    restart : always 
    
    
  web :
    build : . 
    command : bash -c "while !</dev/tcp/db/5432; do sleep 1; done; python manage.py collectstatic --noinput && python manage.py makemigrations && python manage.py migrate  && gunicorn api.wsgi:application --bind 0.0.0.0:8000"  
    volumes :
      - .:/code 
      - static:/static    
      - media:/media    
    expose : 
      - 8000 
    depends_on :
      - db 
    
  nginx :
    image : nginx:latest 
    ports :
      - 8000:80 
    volumes :
      - ./nginx:/etc/nginx/conf.d 
      - static:/static   
      - media:/media  
    depends_on :
      - web 
   
volumes :
  adafri_postgres :
  static :
  media :
# nginx/nginx.conf
 
upstream web {
    server web:8000;
}
server {
    listen 80;
    server_name localhost;
    location /static/ {
        alias /static/;
    }
    location /media/ {
        alias /media/;
    }
    location / {
        proxy_pass http://web/;
        proxy_set_header Host $http_host;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #proxy_set_header X-Forwarded-Protocol "";
        #proxy_set_header X-Forwarded-Ssl "";
    }
    
}
Query for each item in a list def  get_queryset (self ):
    queryset  =  super (MyModel , self ).get_queryset ()
    states_filter  =  [
        item .strip ()
        for  item  in  config .STATES .split (',' )
    ]
    if  not  states_filter :
        MyModel .objects .none ()
    q  =  Q ()
    for  state  in  states_filter :
        q  =  q  |  Q (status__iexact = state )
    queryset  =  queryset .filter (q )
    return  queryset Dynamic fields in Django Rest Framwork serializers from  django .db  import  models 
from  django .utils  import  timezone 
class  Author (models .Model ):
    name  =  models .CharField (max_length = 40 )
    dob  =  models .DateField (verbose_name = 'Date of birth' )
    @property  
    def  age (self ):
        return  timezone .now ().year  -  self .dob .year 
class  AuthorSerializer (serializers .ModelSerializer ):
    age  =  serializers .SerializerMethodField ()
    class  Meta :
        model  =  Author 
        fields  =  '__all__' 
    def  get_age (self , instance ):
        return  datetime .datetime .now ().year  -  instance .dob .year 
class  AuthorSerializer (serializers .ModelSerializer ):
    age  =  serializers .SerializerMethodField (method_name = 'calculate_age' )
    class  Meta :
        model  =  Author 
        fields  =  ('id' , 'name' , 'dob' , 'age' )
    def  calculate_age (self , instance ):
        request  =  self .context .get ('request' )
        user  =  request .user 
        if  user .is_authenticated () and  user .is_staff :
            return  datetime .datetime .now ().year  -  instance .dob .year 
        return  'Hidden' class  Team (models .Model ):
    LEADERSHIP_TEAM  =  1 
    ACCOUNT_TEAM  =  2 
    CREATIVE_TEAM  =  3 
    TEAM_CHOICES  =  (
        (LEADERSHIP_TEAM , 'Leadership' ),
        (ACCOUNT_TEAM , 'Account' ),
        (CREATIVE_TEAM , 'Creative' ),
    )
    team  =  models .IntegerField (choices = TEAM_CHOICES , default = LEADERSHIP_TEAM )
    ...{% for member in object_list %}
    {{ member.get_team_display|lower }}
{% endfor %}