Return a URL appropriate for the arguments passed. The arguments could be: * A model: the model's `get_absolute_url()` function will be called. * A view name, possibly with arguments: `urls.reverse()` will be used to reverse-resolve the name. * A URL, w
(to, *args, **kwargs)
| 171 | |
| 172 | |
| 173 | def resolve_url(to, *args, **kwargs): |
| 174 | """ |
| 175 | Return a URL appropriate for the arguments passed. |
| 176 | |
| 177 | The arguments could be: |
| 178 | |
| 179 | * A model: the model's `get_absolute_url()` function will be called. |
| 180 | |
| 181 | * A view name, possibly with arguments: `urls.reverse()` will be used |
| 182 | to reverse-resolve the name. |
| 183 | |
| 184 | * A URL, which will be returned as-is. |
| 185 | """ |
| 186 | # If it's a model, use get_absolute_url() |
| 187 | if hasattr(to, "get_absolute_url"): |
| 188 | return to.get_absolute_url() |
| 189 | |
| 190 | if isinstance(to, Promise): |
| 191 | # Expand the lazy instance, as it can cause issues when it is passed |
| 192 | # further to some Python functions like urlparse. |
| 193 | to = str(to) |
| 194 | |
| 195 | # Handle relative URLs |
| 196 | if isinstance(to, str) and to.startswith(("./", "../")): |
| 197 | return to |
| 198 | |
| 199 | # Next try a reverse URL resolution. |
| 200 | try: |
| 201 | return reverse(to, args=args, kwargs=kwargs) |
| 202 | except NoReverseMatch: |
| 203 | # If this is a callable, re-raise. |
| 204 | if callable(to): |
| 205 | raise |
| 206 | # If this doesn't "feel" like a URL, re-raise. |
| 207 | if "/" not in to and "." not in to: |
| 208 | raise |
| 209 | |
| 210 | # Finally, fall back and assume it's a URL |
| 211 | return to |