Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/views/generic/base.py: 56%

111 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import logging 

2 

3from django.core.exceptions import ImproperlyConfigured 

4from django.http import ( 

5 HttpResponse, 

6 HttpResponseGone, 

7 HttpResponseNotAllowed, 

8 HttpResponsePermanentRedirect, 

9 HttpResponseRedirect, 

10) 

11from django.template.response import TemplateResponse 

12from django.urls import reverse 

13from django.utils.decorators import classonlymethod 

14 

15logger = logging.getLogger("django.request") 

16 

17 

18class ContextMixin: 

19 """ 

20 A default context mixin that passes the keyword arguments received by 

21 get_context_data() as the template context. 

22 """ 

23 

24 extra_context = None 

25 

26 def get_context_data(self, **kwargs): 

27 kwargs.setdefault("view", self) 

28 if self.extra_context is not None: 

29 kwargs.update(self.extra_context) 

30 return kwargs 

31 

32 

33class View: 

34 """ 

35 Intentionally simple parent class for all views. Only implements 

36 dispatch-by-method and simple sanity checking. 

37 """ 

38 

39 http_method_names = [ 

40 "get", 

41 "post", 

42 "put", 

43 "patch", 

44 "delete", 

45 "head", 

46 "options", 

47 "trace", 

48 ] 

49 

50 def __init__(self, **kwargs): 

51 """ 

52 Constructor. Called in the URLconf; can contain helpful extra 

53 keyword arguments, and other things. 

54 """ 

55 # Go through keyword arguments, and either save their values to our 

56 # instance, or raise an error. 

57 for key, value in kwargs.items(): 

58 setattr(self, key, value) 

59 

60 @classonlymethod 

61 def as_view(cls, **initkwargs): 

62 """Main entry point for a request-response process.""" 

63 for key in initkwargs: 

64 if key in cls.http_method_names: 64 ↛ 65line 64 didn't jump to line 65, because the condition on line 64 was never true

65 raise TypeError( 

66 "The method name %s is not accepted as a keyword argument " 

67 "to %s()." % (key, cls.__name__) 

68 ) 

69 if not hasattr(cls, key): 69 ↛ 70line 69 didn't jump to line 70, because the condition on line 69 was never true

70 raise TypeError( 

71 "%s() received an invalid keyword %r. as_view " 

72 "only accepts arguments that are already " 

73 "attributes of the class." % (cls.__name__, key) 

74 ) 

75 

76 def view(request, *args, **kwargs): 

77 self = cls(**initkwargs) 

78 self.setup(request, *args, **kwargs) 

79 if not hasattr(self, "request"): 79 ↛ 80line 79 didn't jump to line 80, because the condition on line 79 was never true

80 raise AttributeError( 

81 "%s instance has no 'request' attribute. Did you override " 

82 "setup() and forget to call super()?" % cls.__name__ 

83 ) 

84 return self.dispatch(request, *args, **kwargs) 

85 

86 view.view_class = cls 

87 view.view_initkwargs = initkwargs 

88 

89 # __name__ and __qualname__ are intentionally left unchanged as 

90 # view_class should be used to robustly determine the name of the view 

91 # instead. 

92 view.__doc__ = cls.__doc__ 

93 view.__module__ = cls.__module__ 

94 view.__annotations__ = cls.dispatch.__annotations__ 

95 # Copy possible attributes set by decorators, e.g. @csrf_exempt, from 

96 # the dispatch method. 

97 view.__dict__.update(cls.dispatch.__dict__) 

98 

99 return view 

100 

101 def setup(self, request, *args, **kwargs): 

102 """Initialize attributes shared by all view methods.""" 

103 if hasattr(self, "get") and not hasattr(self, "head"): 103 ↛ 104line 103 didn't jump to line 104, because the condition on line 103 was never true

104 self.head = self.get 

105 self.request = request 

106 self.args = args 

107 self.kwargs = kwargs 

108 

109 def dispatch(self, request, *args, **kwargs): 

110 # Try to dispatch to the right method; if a method doesn't exist, 

111 # defer to the error handler. Also defer to the error handler if the 

112 # request method isn't on the approved list. 

113 if request.method.lower() in self.http_method_names: 

114 handler = getattr( 

115 self, request.method.lower(), self.http_method_not_allowed 

116 ) 

117 else: 

118 handler = self.http_method_not_allowed 

119 return handler(request, *args, **kwargs) 

120 

121 def http_method_not_allowed(self, request, *args, **kwargs): 

122 logger.warning( 

123 "Method Not Allowed (%s): %s", 

124 request.method, 

125 request.path, 

126 extra={"status_code": 405, "request": request}, 

127 ) 

128 return HttpResponseNotAllowed(self._allowed_methods()) 

129 

130 def options(self, request, *args, **kwargs): 

131 """Handle responding to requests for the OPTIONS HTTP verb.""" 

132 response = HttpResponse() 

133 response.headers["Allow"] = ", ".join(self._allowed_methods()) 

134 response.headers["Content-Length"] = "0" 

135 return response 

136 

137 def _allowed_methods(self): 

138 return [m.upper() for m in self.http_method_names if hasattr(self, m)] 

139 

140 

141class TemplateResponseMixin: 

142 """A mixin that can be used to render a template.""" 

143 

144 template_name = None 

145 template_engine = None 

146 response_class = TemplateResponse 

147 content_type = None 

148 

149 def render_to_response(self, context, **response_kwargs): 

150 """ 

151 Return a response, using the `response_class` for this view, with a 

152 template rendered with the given context. 

153 

154 Pass response_kwargs to the constructor of the response class. 

155 """ 

156 response_kwargs.setdefault("content_type", self.content_type) 

157 return self.response_class( 

158 request=self.request, 

159 template=self.get_template_names(), 

160 context=context, 

161 using=self.template_engine, 

162 **response_kwargs, 

163 ) 

164 

165 def get_template_names(self): 

166 """ 

167 Return a list of template names to be used for the request. Must return 

168 a list. May not be called if render_to_response() is overridden. 

169 """ 

170 if self.template_name is None: 

171 raise ImproperlyConfigured( 

172 "TemplateResponseMixin requires either a definition of " 

173 "'template_name' or an implementation of 'get_template_names()'" 

174 ) 

175 else: 

176 return [self.template_name] 

177 

178 

179class TemplateView(TemplateResponseMixin, ContextMixin, View): 

180 """ 

181 Render a template. Pass keyword arguments from the URLconf to the context. 

182 """ 

183 

184 def get(self, request, *args, **kwargs): 

185 context = self.get_context_data(**kwargs) 

186 return self.render_to_response(context) 

187 

188 

189class RedirectView(View): 

190 """Provide a redirect on any GET request.""" 

191 

192 permanent = False 

193 url = None 

194 pattern_name = None 

195 query_string = False 

196 

197 def get_redirect_url(self, *args, **kwargs): 

198 """ 

199 Return the URL redirect to. Keyword arguments from the URL pattern 

200 match generating the redirect request are provided as kwargs to this 

201 method. 

202 """ 

203 if self.url: 

204 url = self.url % kwargs 

205 elif self.pattern_name: 

206 url = reverse(self.pattern_name, args=args, kwargs=kwargs) 

207 else: 

208 return None 

209 

210 args = self.request.META.get("QUERY_STRING", "") 

211 if args and self.query_string: 

212 url = "%s?%s" % (url, args) 

213 return url 

214 

215 def get(self, request, *args, **kwargs): 

216 url = self.get_redirect_url(*args, **kwargs) 

217 if url: 

218 if self.permanent: 

219 return HttpResponsePermanentRedirect(url) 

220 else: 

221 return HttpResponseRedirect(url) 

222 else: 

223 logger.warning( 

224 "Gone: %s", request.path, extra={"status_code": 410, "request": request} 

225 ) 

226 return HttpResponseGone() 

227 

228 def head(self, request, *args, **kwargs): 

229 return self.get(request, *args, **kwargs) 

230 

231 def post(self, request, *args, **kwargs): 

232 return self.get(request, *args, **kwargs) 

233 

234 def options(self, request, *args, **kwargs): 

235 return self.get(request, *args, **kwargs) 

236 

237 def delete(self, request, *args, **kwargs): 

238 return self.get(request, *args, **kwargs) 

239 

240 def put(self, request, *args, **kwargs): 

241 return self.get(request, *args, **kwargs) 

242 

243 def patch(self, request, *args, **kwargs): 

244 return self.get(request, *args, **kwargs)