Search code examples
djangodjango-request

content function in django.http source code


I was looking into below codes from Django Official Docs

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

Then I deep dive into the source code of django.http

class HttpResponse(HttpResponseBase):
    """
    An HTTP response class with a string as content.
    This content can be read, appended to, or replaced.
    """

    streaming = False

    def __init__(self, content=b'', *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Content is a bytestring. See the `content` property methods.
        self.content = content

    def __repr__(self):
        return '<%(cls)s status_code=%(status_code)d%(content_type)s>' % {
            'cls': self.__class__.__name__,
            'status_code': self.status_code,
            'content_type': self._content_type_for_repr,
        }

    def serialize(self):
        """Full HTTP message, including headers, as a bytestring."""
        return self.serialize_headers() + b'\r\n\r\n' + self.content

    __bytes__ = serialize

    @property
    def content(self):
        return b''.join(self._container)

    @content.setter
    def content(self, value):
        # Consume iterators upon assignment to allow repeated iteration.
        if (
            hasattr(value, '__iter__') and
            not isinstance(value, (bytes, memoryview, str))
        ):
            content = b''.join(self.make_bytes(chunk) for chunk in value)
            if hasattr(value, 'close'):
                try:
                    value.close()
                except Exception:
                    pass
        else:
            content = self.make_bytes(value)
        # Create a list of properly encoded bytestrings to support write().
        self._container = [content]

Q1: Shouldn't we use return HttpResponse(content=html) since content is a keyword argument defined in def __init__(self, content=b'', *args, **kwargs):?

Q2: Where is the decorator @content.setter defined?

Q3: when & where the attribute self._container is defined?

Q4: How everything works out for command return HttpResponse(html)?

Found similar question What is the _container property of Django's http.response?, but I did not understand the answer at all.


Solution

  • Q1: python keyword argument accept both ordered arguments without keyword and unordered arguments with keyword.and keyword arguments always come with default values.I will give you an example.

    def f(a=0,b=0,c=0):
        pass
    
    f(1,2,3)
    f(a=1,b=2,c=3)
    f(1,b=2,c=3)
    #they call funciton f with same arguments
    

    Q2:@content.setter is a property decorator.it make effect togather with @property.
    if you don't familiar with setter and getter.I give your a brief:We can direct give object's property a value directly,but if we want do some tranform or check,then we can use property decorator.
    here is Python doc about property decorator.you can read it.


    Q3:I am not sure about this.maybe some can give better answer.but I guess self._container do not need define._container will init by @content.setter,and if the _container be called before init,it will throw an error,that maybe the author's intent because you can't not return an not well init HttpResponse.


    Q4:If you really interest in how the return HttpResonse(html) work.I suggest you use debug mode.it's easy to run debug mode in visual studio code or pycharm or any other popular IDE.
    then you can run code step by step.at each step you can investigate every variable in the context.trust me that's very helpful.I always use debug to study framework.