2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

Add docstring documentation to the main InvenTree app

This commit is contained in:
Oliver Walters 2019-04-27 21:21:58 +10:00
parent c3f0570926
commit 5e6d49102d
7 changed files with 128 additions and 47 deletions

View File

@ -1,3 +1,7 @@
"""
Helper forms which subclass Django forms to provide additional functionality
"""
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
@ -6,6 +10,7 @@ from crispy_forms.helper import FormHelper
class HelperForm(forms.ModelForm): class HelperForm(forms.ModelForm):
""" Provides simple integration of crispy_forms extension. """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(forms.ModelForm, self).__init__(*args, **kwargs) super(forms.ModelForm, self).__init__(*args, **kwargs)

View File

@ -1,3 +1,7 @@
"""
Provides helper functions used throughout the InvenTree project
"""
import io import io
from wsgiref.util import FileWrapper from wsgiref.util import FileWrapper
@ -5,7 +9,14 @@ from django.http import StreamingHttpResponse
def str2bool(text, test=True): def str2bool(text, test=True):
""" Test if a string 'looks' like a boolean value """ Test if a string 'looks' like a boolean value.
Args:
text: Input text
test (default = True): Set which boolean value to look for
Returns:
True if the text looks like the selected boolean value
""" """
if test: if test:
return str(text).lower() in ['1', 'y', 'yes', 't', 'true', 'ok', ] return str(text).lower() in ['1', 'y', 'yes', 't', 'true', 'ok', ]
@ -13,21 +24,36 @@ def str2bool(text, test=True):
return str(text).lower() in ['0', 'n', 'no', 'none', 'f', 'false', ] return str(text).lower() in ['0', 'n', 'no', 'none', 'f', 'false', ]
def WrapWithQuotes(text): def WrapWithQuotes(text, quote='"'):
# TODO - Make this better """ Wrap the supplied text with quotes
if not text.startswith('"'):
text = '"' + text
if not text.endswith('"'): Args:
text = text + '"' text: Input text to wrap
quote: Quote character to use for wrapping (default = "")
Returns:
Supplied text wrapped in quote char
"""
if not text.startswith(quote):
text = quote + text
if not text.endswith(quote):
text = text + quote
return text return text
def DownloadFile(data, filename, content_type='application/text'): def DownloadFile(data, filename, content_type='application/text'):
""" """ Create a dynamic file for the user to download.
Create a dynamic file for the user to download.
@param data is the raw file data Args:
data: Raw file data (string or bytes)
filename: Filename for the file download
content_type: Content type for the download
Return:
A StreamingHttpResponse object wrapping the supplied data
""" """
filename = WrapWithQuotes(filename) filename = WrapWithQuotes(filename)

View File

@ -1,3 +1,7 @@
"""
Generic models which provide extra functionality over base Django model types.
"""
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import models from django.db import models
@ -11,6 +15,7 @@ from django.dispatch import receiver
class InvenTreeTree(models.Model): class InvenTreeTree(models.Model):
""" Provides an abstracted self-referencing tree model for data categories. """ Provides an abstracted self-referencing tree model for data categories.
- Each Category has one parent Category, which can be blank (for a top-level Category). - Each Category has one parent Category, which can be blank (for a top-level Category).
- Each Category can have zero-or-more child Categor(y/ies) - Each Category can have zero-or-more child Categor(y/ies)
""" """
@ -69,10 +74,12 @@ class InvenTreeTree(models.Model):
@property @property
def has_children(self): def has_children(self):
""" True if there are any children under this item """
return self.children.count() > 0 return self.children.count() > 0
@property @property
def children(self): def children(self):
""" Return the children of this item """
contents = ContentType.objects.get_for_model(type(self)) contents = ContentType.objects.get_for_model(type(self))
childs = contents.get_all_objects_for_this_type(parent=self.id) childs = contents.get_all_objects_for_this_type(parent=self.id)
@ -100,11 +107,10 @@ class InvenTreeTree(models.Model):
@property @property
def parentpath(self): def parentpath(self):
""" Return the parent path of this category """ Get the parent path of this category
Todo: Returns:
This function is recursive and expensive. List of category names from the top level to the parent of this category
It should be reworked such that only a single db call is required
""" """
if self.parent: if self.parent:
@ -114,10 +120,21 @@ class InvenTreeTree(models.Model):
@property @property
def path(self): def path(self):
""" Get the complete part of this category.
e.g. ["Top", "Second", "Third", "This"]
Returns:
List of category names from the top level to this category
"""
return self.parentpath + [self] return self.parentpath + [self]
@property @property
def pathstring(self): def pathstring(self):
""" Get a string representation for the path of this item.
e.g. "Top/Second/Third/This"
"""
return '/'.join([item.name for item in self.path]) return '/'.join([item.name for item in self.path])
def __setattr__(self, attrname, val): def __setattr__(self, attrname, val):
@ -157,38 +174,19 @@ class InvenTreeTree(models.Model):
super(InvenTreeTree, self).__setattr__(attrname, val) super(InvenTreeTree, self).__setattr__(attrname, val)
def __str__(self): def __str__(self):
""" String representation of a category is the full path to that category """ String representation of a category is the full path to that category """
Todo:
This is recursive - Make it not so.
"""
return self.pathstring return self.pathstring
@receiver(pre_delete, sender=InvenTreeTree, dispatch_uid='tree_pre_delete_log') @receiver(pre_delete, sender=InvenTreeTree, dispatch_uid='tree_pre_delete_log')
def before_delete_tree_item(sender, instance, using, **kwargs): def before_delete_tree_item(sender, instance, using, **kwargs):
""" Receives pre_delete signal from InvenTreeTree object.
Before an item is deleted, update each child object to point to the parent of the object being deleted.
"""
# Update each tree item below this one # Update each tree item below this one
for child in instance.children.all(): for child in instance.children.all():
child.parent = instance.parent child.parent = instance.parent
child.save() child.save()
def FilterChildren(queryset, parent):
""" Filter a queryset, limit to only objects that are a child of the given parent
Filter is passed in the URL string, e.g. '/?parent=123'
To accommodate for items without a parent, top-level items can be specified as:
none / false / null / top / 0
"""
if not parent:
return queryset
elif str2bool(parent, False):
return queryset.filter(parent=None)
else:
parent_id = int(parent)
if parent_id == 0:
return queryset.filter(parent=None)
else:
return queryset.filter(parent=parent_id)

View File

@ -1,3 +1,8 @@
"""
Serializers used in various InvenTree apps
"""
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
@ -7,6 +12,7 @@ from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
""" Serializer for User - provides all fields """
class Meta: class Meta:
model = User model = User
@ -14,6 +20,7 @@ class UserSerializer(serializers.ModelSerializer):
class UserSerializerBrief(serializers.ModelSerializer): class UserSerializerBrief(serializers.ModelSerializer):
""" Serializer for User - provides limited information """
class Meta: class Meta:
model = User model = User

View File

@ -1,3 +1,10 @@
"""
Top-level URL lookup for InvenTree application.
Passes URL lookup downstream to each app as required.
"""
from django.conf.urls import url, include from django.conf.urls import url, include
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views

View File

@ -1,3 +1,10 @@
"""
Various Views which provide extra functionality over base Django Views.
In particular these views provide base functionality for rendering Django forms
as JSON objects and passing them to modal forms (using jQuery / bootstrap).
"""
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
@ -12,6 +19,8 @@ from rest_framework import views
class TreeSerializer(views.APIView): class TreeSerializer(views.APIView):
""" JSON View for serializing a Tree object.
"""
def itemToJson(self, item): def itemToJson(self, item):
@ -52,20 +61,34 @@ class TreeSerializer(views.APIView):
class AjaxMixin(object): class AjaxMixin(object):
""" AjaxMixin provides basic functionality for rendering a Django form to JSON.
Handles jsonResponse rendering, and adds extra data for the modal forms to process
on the client side.
"""
ajax_form_action = '' ajax_form_action = ''
ajax_form_title = '' ajax_form_title = ''
def get_data(self): def get_data(self):
""" Get extra context data (default implementation is empty dict)
Returns:
dict object (empty)
"""
return {} return {}
def getAjaxTemplate(self):
if hasattr(self, 'ajax_template_name'):
return self.ajax_template_name
else:
return self.template_name
def renderJsonResponse(self, request, form=None, data={}, context={}): def renderJsonResponse(self, request, form=None, data={}, context={}):
""" Render a JSON response based on specific class context.
Args:
request: HTTP request object (e.g. GET / POST)
form: Django form object (may be None)
data: Extra JSON data to pass to client
context: Extra context data to pass to template rendering
Returns:
JSON response object
"""
if form: if form:
context['form'] = form context['form'] = form
@ -73,7 +96,7 @@ class AjaxMixin(object):
data['title'] = self.ajax_form_title data['title'] = self.ajax_form_title
data['html_form'] = render_to_string( data['html_form'] = render_to_string(
self.getAjaxTemplate(), self.ajax_template_name,
context, context,
request=request request=request
) )
@ -88,7 +111,8 @@ class AjaxMixin(object):
class AjaxView(AjaxMixin, View): class AjaxView(AjaxMixin, View):
""" Bare-bones AjaxView """ """ An 'AJAXified' View for displaying an object
"""
# By default, point to the modal_form template # By default, point to the modal_form template
# (this can be overridden by a child class) # (this can be overridden by a child class)
@ -201,7 +225,7 @@ class AjaxDeleteView(AjaxMixin, DeleteView):
data = {'id': self.get_object().id, data = {'id': self.get_object().id,
'delete': False, 'delete': False,
'title': self.ajax_form_title, 'title': self.ajax_form_title,
'html_data': render_to_string(self.getAjaxTemplate(), 'html_data': render_to_string(self.ajax_template_name,
self.get_context_data(), self.get_context_data(),
request=request) request=request)
} }
@ -229,15 +253,24 @@ class AjaxDeleteView(AjaxMixin, DeleteView):
class IndexView(TemplateView): class IndexView(TemplateView):
""" View for InvenTree index page """
template_name = 'InvenTree/index.html' template_name = 'InvenTree/index.html'
class SearchView(TemplateView): class SearchView(TemplateView):
""" View for InvenTree search page.
Displays results of search query
"""
template_name = 'InvenTree/search.html' template_name = 'InvenTree/search.html'
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
""" Handle POST request (which contains search query).
Pass the search query to the page template
"""
context = self.get_context_data() context = self.get_context_data()

View File

@ -41,6 +41,8 @@ autoapi_dirs = [
autoapi_options = [ autoapi_options = [
'members', 'members',
'private-members',
'special-members',
] ]
autoapi_type = 'python' autoapi_type = 'python'
@ -51,6 +53,9 @@ autoapi_ignore = [
'**/manage.py', '**/manage.py',
'**/apps.py', '**/apps.py',
'**/admin.py', '**/admin.py',
'**/middleware.py',
'**/utils.py',
'**/wsgi.py',
'**/templates/', '**/templates/',
] ]